小程序按住说话

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

使用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>
相关推荐
炫饭第一名10 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
进击的尘埃12 小时前
Vue3 响应式原理:从 Proxy 到依赖收集,手撸一个迷你 reactivity
javascript
willow12 小时前
JavaScript数据类型整理1
javascript
LeeYaMaster12 小时前
20个例子掌握RxJS——第十一章实现 WebSocket 消息节流
javascript·angular.js
UIUV13 小时前
RAG技术学习笔记(含实操解析)
javascript·langchain·llm
颜酱14 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
FansUnion15 小时前
我如何用 Next.js + Supabase + Cloudflare R2 搭建壁纸销售平台——月成本接近 $0
javascript
左夕16 小时前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
滕青山16 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力17 小时前
编程常用模式集合
前端·javascript·typescript