小程序按住说话

小程序按住说话、上滑取消的实现。

使用view作为容器总有奇怪的问题,比如touchend事件有时候不触发。

需要使用事件修饰符来阻止冒泡,不如有时候touchend、touchmove也不会触发。

下面是效果及源码。


html 复制代码
<template>
  <view class="w-full bg-white">
    <button
      class="record-btn w-full"
      style="padding: 0; line-height: 22px; background-color: transparent"
      @touchend.stop="handleTouchEnd"
      @touchmove.stop="handleTouchmove"
      @longpress.stop="handleLongPress"
    >
      <view v-if="isRecording">
        <view class="text-center text-secondary text-xs py-3">
          <text v-if="isUp">松开取消</text>
          <text v-else>松手发送,上滑取消</text>
        </view>
        <Wave :bgColor="`var(--wot-color-${isUp ? 'danger' : 'theme'})`" />
      </view>

      <view v-else class="leading-22px py-3">
        <view>
          <text class="font-bold">按住说话</text>
        </view>
      </view>
    </button>
  </view>
</template>

<script lang="ts" setup>
import Wave from './Wave.vue'

const isRecording = ref(false) // 状态,当前是否在录音
const isUp = ref(false) // 是否上滑
const startY = ref(0)
const handleLongPress = (event) => {
  startY.value = event.touches[0].clientY
  isRecording.value = true
  console.log(`output->按压的坐标`, startY.value)
}
const handleTouchEnd = () => {
  isRecording.value = false
  startY.value = 0
  isUp.value = false
  console.log(`output->离开后的坐标`, startY.value)
}
const handleTouchmove = (event) => {
  if (!isRecording.value) return

  const currentY = event.touches[0].clientY
  const diffY = startY.value - currentY

  // 设定阈值,防止误判
  isUp.value = diffY > 10
}
</script>

wave.vue

html 复制代码
<template>
  <view
    class="wave-container"
    :style="{
      'background-color': bgColor,
    }"
  >
    <view :class="`wave-bar wave-bar-delay-${n}`" v-for="n in generateSequence(20)" :key="n"></view>
  </view>
</template>
<script lang="ts" setup>
type PropsType = { bgColor: string }

const props = defineProps<PropsType>()

function generateSequence(n) {
  const result = []

  // 递增部分:1 到 n
  for (let i = 1; i <= n; i++) {
    result.push(i)
  }

  // 递减部分:n-1 到 1
  for (let i = n - 1; i >= 1; i--) {
    result.push(i)
  }

  return result
}
</script>

<style lang="scss" scoped>
$number: 20;

.wave-container {
  display: flex;
  gap: 5px;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 22px;
  padding: 12px 0;
  border-radius: 10px;
}
.wave-bar {
  width: 3px;
  height: 10px;
  background-color: #fff;
  border-radius: 2px;
  animation: wave 1s infinite ease-in-out;
}

@for $i from 1 through $number {
  .wave-bar-delay-#{$i} {
    animation-delay: $i * -0.8 + s;
  }
}

@keyframes wave {
  0%,
  100% {
    transform: scaleY(0.8);
  }
  50% {
    transform: scaleY(1);
  }
}
</style>
相关推荐
qq_417129252 分钟前
C++中的桥接模式变体
开发语言·c++·算法
开源技术16 分钟前
如何将本地LLM模型与Ollama和Python集成
开发语言·python
Hello World . .20 分钟前
数据结构:队列
c语言·开发语言·数据结构·vim
jin12332228 分钟前
React Native鸿蒙跨平台完成剧本杀组队详情页面,可以复用桌游、团建、赛事等各类组队详情页开发
javascript·react native·react.js·ecmascript·harmonyos
clever10133 分钟前
在QtCreator 4.10.2中调试qt程序qDebug()输出中文为乱码问题的解决
开发语言·qt
测试开发Kevin1 小时前
小tip:换行符CRLF 和 LF 的区别以及二者在实际项目中的影响
java·开发语言·python
经年未远1 小时前
vue3中实现耳机和扬声器切换方案
javascript·学习·vue
松☆1 小时前
Dart 核心语法精讲:从空安全到流程控制(3)
android·java·开发语言
刘一说2 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
可触的未来,发芽的智生2 小时前
狂想:为AGI代称造字ta,《第三类智慧存在,神的赐名》
javascript·人工智能·python·神经网络·程序人生