移动端按住说话样式

下面是最终效果,手指移出指定区域就改为取消状态,松开手指就取消,手指没有移出指定区域,状态为录音中,松开手指为结束录音状态

下面是代码

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>语音交互样式</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #f5f5f5;
    }

    .voice-container {
      position: relative;
      width: 200px;
      height: 200px;
    }

    /* 语音交互按钮 */
    .voice-btn {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      width: 80px;
      height: 80px;
      background-color: #4CAF50;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-size: 20px;
      cursor: pointer;
      transition: background-color 0.3s;
    }

    .voice-btn:active {
      background-color: #388E3C;
    }

    /* 正在语音识别的状态 */
    .voice-recognizing {
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%);
      width: 100%;
      height: 100px;
      background-color: rgba(0, 0, 0, 0.2);
      border-radius: 20px 20px 0 0;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-size: 16px;
      display: none; /* 默认隐藏 */
      transition: background-color 0.3s;
    }

    /* 预取消状态:当手指移出语音识别区域时,改变样式 */
    .voice-recognizing.canceling {
      background-color: rgba(255, 0, 0, 0.5); /* 改为红色表示预取消 */
    }

    /* 取消区域:顶部区域用于取消语音识别 */
    .cancel-area {
      position: absolute;
      top: 0;
      left: 50%;
      transform: translateX(-50%);
      width: 100%;
      height: 30px;
      background-color: rgba(255, 0, 0, 0.8); /* 红色背景 */
      color: white;
      text-align: center;
      line-height: 30px;
      font-size: 14px;
      display: none; /* 默认隐藏 */
      cursor: pointer;
      z-index: 1;
    }

    /* 取消区域显示 */
    .cancel-area.show {
      display: block;
    }

    /* 取消区域 hover 样式 */
    .cancel-area:hover {
      background-color: rgba(255, 0, 0, 1);
    }
  </style>
</head>
<body>

  <div class="voice-container">
    <!-- 语音交互按钮 -->
    <div class="voice-btn" id="voiceBtn">
      🎤
    </div>

    <!-- 正在语音识别 -->
    <div class="voice-recognizing" id="voiceRecognizing">
      正在识别...
    </div>

    <!-- 取消区域 -->
    <div class="cancel-area" id="cancelArea">
      松开手指取消语音识别
    </div>
  </div>

  <script>
    const voiceBtn = document.getElementById('voiceBtn');
    const voiceRecognizing = document.getElementById('voiceRecognizing');
    const cancelArea = document.getElementById('cancelArea');

    let isRecognizing = false;  // 标识当前是否正在识别
    let isTouching = false;     // 标识是否有触摸事件正在进行
    let touchStartY = 0;        // 记录触摸开始的位置
    let isCanceling = false;    // 标识是否进入预取消状态

    // 按下按钮开始语音识别
    voiceBtn.addEventListener('mousedown', startRecognition);
    voiceBtn.addEventListener('touchstart', startRecognition);

    function startRecognition(e) {
      e.preventDefault();  // 阻止默认事件,避免页面滚动等
      isRecognizing = true;
      voiceRecognizing.style.display = 'flex';  // 显示正在语音识别的状态
      cancelArea.classList.add('show');         // 显示取消区域
      isTouching = true;
      isCanceling = false;  // 初始状态不是预取消

      // 记录触摸开始的位置,用于判断手指滑动方向
      if (e.type === 'touchstart') {
        touchStartY = e.touches[0].clientY;
      }

      // 禁止页面滚动
      document.body.style.overflow = 'hidden';
    }

    // 松开按钮结束语音识别
    voiceBtn.addEventListener('mouseup', stopRecognition);
    voiceBtn.addEventListener('touchend', stopRecognition);

    function stopRecognition(e) {
      if (isRecognizing && isCanceling) {
        // 如果处于预取消状态,取消语音识别
        cancelRecognition();
      } else if (isRecognizing) {
        // 如果没有进入取消区域,正常结束语音识别
        finishRecognition();
      }
      isTouching = false;
      isCanceling = false;

      // 恢复页面滚动
      document.body.style.overflow = 'auto';
    }

    // 取消语音识别
    function cancelRecognition() {
      isRecognizing = false;
      voiceRecognizing.style.display = 'none';  // 隐藏正在识别状态
      cancelArea.classList.remove('show');      // 隐藏取消区域
      voiceRecognizing.classList.remove('canceling');  // 清除预取消状态样式
      alert('语音识别已取消');
    }

    // 完成语音识别
    function finishRecognition() {
      isRecognizing = false;
      voiceRecognizing.style.display = 'none';  // 隐藏正在识别状态
      cancelArea.classList.remove('show');      // 隐藏取消区域
      voiceRecognizing.classList.remove('canceling');  // 清除预取消状态样式
      alert('语音识别结束');
    }

    // 在触摸时,检测是否滑动出了 voice-recognizing 区域
    document.addEventListener('touchmove', handleTouchMove, { passive: false });

    function handleTouchMove(e) {
      e.preventDefault(); // 阻止默认的滚动行为

      if (isTouching) {
        const touch = e.touches[0];
        const recognizerRect = voiceRecognizing.getBoundingClientRect();

        // 判断手指是否离开了 voice-recognizing 区域
        if (touch.clientY < recognizerRect.top || touch.clientY > recognizerRect.bottom) {
          // 进入预取消状态
          if (!isCanceling) {
            voiceRecognizing.classList.add('canceling');  // 改为红色表示预取消
            isCanceling = true;
          }
        } else {
          // 手指回到识别区域,取消预取消状态
          if (isCanceling) {
            voiceRecognizing.classList.remove('canceling');
            isCanceling = false;
          }
        }
      }
    }

    // 取消区域的点击事件
    cancelArea.addEventListener('click', cancelRecognition);
  </script>

</body>
</html>

 

posted @ 2024-11-15 11:21  unique-yb  阅读(202)  评论(0)    收藏  举报