audio标签的播放、暂停、重播、进度拖拽等操作

9 篇文章 0 订阅

前言

最近在做题库项目的时候,需要对听力题进行手动控制等一系列操作,其中最主要的用到的一些方法就是loadeddatatimeupdateended等,次功能花了不少时间,此文仅作记录,不喜勿喷,上代码。


1.HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>

  <link rel="stylesheet" href="./index.css">
  <script src=" https://www.w3school.com.cn/jquery/jquery.js"></script>
  <script src="./index.js"></script>
  <body>
    <div class="box">
      <div class="listenQuest cf">
        <audio>
          <source class="audioMp3"
            src="./mmmmmmp3.mp3"
            type="audio/mp3">
          <source class="audioWav"
            src="./mmmmmmp3.mp3"
            type="audio/wav">
        </audio>
        <div class="listenQ_l fl">
          <div class="listenQ_l_t cf">
            <div class="title fl">听录音材料,回答下面问题</div>
            <div class="time fr">
              <span class="start_time"
                class="audioCurTime">00:00</span>/<span
                class="end_time"
                class="allTime">00:00</span>
            </div>
          </div>
          <div class="listenQ_l_b">
            <div class="proress_box">
              <div class="Strip"
                class="progressBarBg">
                <span
                  class="progressDot"></span>
                <p style="width:0%"></p>
              </div>
            </div>
          </div>
        </div>
        <div class="listenQ_r fr">
          <img
            src="./t_icon_play.png"
            class="play_btn control icon"
            class="audioPlayer" alt="播放按钮">
        </div>
      </div>
    </div>
    <!-- 一个页面只能由一个audio -->
    <div class="listenQuest audioBox cf" id="audioDrag">
      <i class="closeBtn"></i>
      <div class="listenQ_l fl">
        <div class="listenQ_l_t cf">
          <div class="title fl">听录音材料,回答下面问题</div>
          <div class="time fr">
            <span class="start_time"
              id="audioCurTime">00:00</span>/<span
              class="end_time"
              id="allTime">00:00</span>
          </div>
        </div>
        <div class="listenQ_l_b">
          <audio id="audioAll">
            <source id="audioMp3"
              src="./mmmmmmp3.mp3"
              type="audio/mp3">
            <source id="audioWav"
              src="./mmmmmmp3.mp3"
              type="audio/wav">
            Your browser does not
            support the audio tag.
          </audio>
          <div class="proress_box">
            <div class="Strip"
              id="progressBarBg">
              <span id="progressDot"></span>
              <p style="width:0%"
                id="progressBar"></p>
            </div>
          </div>
        </div>
      </div>
      <div class="listenQ_r fr">
        <div class="iconBox_tt fl" id="audioPlayer">
          <img src="./t_icon_pause_big.png" class="pause_btn
            icon" alt="暂停按钮">
          <img src="./t_icon_play.png" class="play_btn icon"
            alt="播放按钮">
        </div>
        <img src="./t_icon_replay.png" class="replay_btn icon"
          id="resetBtn" alt="重播按钮">
      </div>
    </div>
  </body>
</html>
2.CSS
*{padding: 0;margin: 0;}
.box{width: 840px; margin: 200px auto 0;}
.cf:before,
.cf:after {content: "";display: table;}
.cf:after { clear: both;}
.cf { *zoom: 1;}
.fl{float: left;}
.fr{float: right;}

.listenQuest.audioBox{border: 1px solid #DADADA; position: fixed;left: 20%; top: 30%;z-index: -1;opacity: 0; width: 840px; padding: 20px 30px; box-sizing: border-box;border-radius: 10px;background: #F6F6F6;}
.listenQuest{width: 100%;margin-bottom: 10px; padding: 20px 30px; box-sizing: border-box;border-radius: 10px;background: #F6F6F6;}
.listenQuest .listenQ_l{width:650px;}
.listenQuest .closeBtn{display: inline-block; width: 24px; height: 24px; border-radius: 24px; background: url('./t_icon_closeBtn.png') no-repeat;background-size: 100% auto;background-position:center;background-color:#6E6E6E ; position: absolute;right: -12px; top: -12px; cursor: pointer;}
.listenQuest .listenQ_l .title{font-size: 18px;color: #111;}
.listenQuest .listenQ_l .time{font-size: 15px;color: #999;}
.listenQuest .listenQ_l .start_time{color: #111;}
.listenQuest .listenQ_l .listenQ_l_t{margin-bottom: 5px;}
.listenQuest .listenQ_r {margin-top: 4px;}
.listenQuest .listenQ_l{position: relative;}
.listenQuest .listenQ_l .audioMedia{position: absolute;z-index: 0;}
.listenQuest  .title_info {font-size: 15px;color: #999;margin-top: 15px;}
.listenQuest .Strip,.listenQuest .Strip p{height: 8px; font-size: 0;border-radius: 8px;}
.listenQuest .Strip {background: #CFD1D4; margin-top: 4px; width: 650px;display: inline-block;position: relative;}
.listenQuest .Strip p{background: #FF6810;position: relative;}
.listenQuest .Strip #progressDot{position: absolute;display: block;transform: translateX(-6px);z-index: 2; left: 0;top: 0;bottom: 0;margin: auto;width: 12px;height: 12px;border-radius: 50%;background: #FFFFFF;box-shadow: 0 3px 10px #9e9c9c;}
.listenQuest .listenQ_r .icon{cursor: pointer; width: 45px;height: 45px;margin-right: 5px;}
.iconBox_tt .pause_btn{display: block;}
.iconBox_tt .play_btn{display: none;}
.iconBox_tt.play .pause_btn{display: none;}
.iconBox_tt.play .play_btn{display: block;}
.audioShow{z-index: 1000!important;opacity: 1!important}
3.JS

//练习模式听力题
$(window).load(function () {
  var audio = document.getElementById("audioAll");
  if (!audio) {
    return false;
  }
  document.getElementById("audioAll").load();

  $(".control").click(function () {
    $(".audioBox").addClass("audioShow");
  });
  $(".closeBtn").click(function () {
    $(".audioBox").removeClass("audioShow");
    document.getElementById("audioAll").load();
    audioEnded();
    $(".control").css("pointer-events", "auto");
  });
});

document.addEventListener(
  "DOMContentLoaded",
  function () {
    //设置音频地址(必须是服务器地址)
    var audioMp3 = document.getElementById("audioMp3");
    var audioWav = document.getElementById("audioWav");
    $(".control").click(function () {
      $(".audioBox").addClass("audioShow");

      drag(document.getElementById('audioDrag'))
      // 初始化音频控制事件
      var mp3Add = $(this).parents(".listenQuest").find(".audioMp3")[0].src;
      var wavAdd = $(this).parents(".listenQuest").find(".audioWav")[0].src;
      audioMp3.setAttribute("src", mp3Add);
      audioWav.setAttribute("src", wavAdd);
      document.getElementById("audioAll").load();
      var audio = document.getElementById("audioAll");
      audio.play();
      $('#audioPlayer').removeClass('play')
      $(".control").css("pointer-events", "auto");
      $(this).css("pointer-events", "none");
    });
    var audio = document.getElementById("audioAll");
    if (audio) {
      initAudioEvent();
    }
  },
  false
);

function initAudioEvent() {
  console.log("初始化");
  var audio = document.getElementById("audioAll");
  var audioPlayer = document.getElementById("audioPlayer");
  var resetBtn = document.getElementById("resetBtn");
  //音频初始化
  audio.addEventListener("loadeddata", function () {
    var allTime = audio.duration;
    timeChange(allTime, "allTime");
  });
  // 监听音频播放时间并更新进度条
  audio.addEventListener(
    "timeupdate",
    function () {
      updateProgress(audio);
    },
    false
  );
  // 监听播放完成事件
  audio.addEventListener(
    "ended",
    function () {
      audioEnded();
    },
    false
  );
  // 点击播放/暂停图片时,控制音乐的播放与暂停
  audioPlayer.addEventListener(
    "click",
    function () {
      // 改变播放/暂停图片
      if (audio.paused) {
        // 开始播放当前点击的音频
        audio.play();
        $('#audioPlayer').removeClass('play')
      } else {
        audio.pause();
        $('#audioPlayer').addClass('play')
      }
    },
    false
  );
  resetBtn.addEventListener(
    "click",
    function () {
      audio.currentTime = 0;
      audio.play();
      $('#audioPlayer').removeClass('play')
    },
    false
  );

  // 点击进度条跳到指定点播放
  // PS:此处不要用click,否则下面的拖动进度点事件有可能在此处触发,此时e.offsetX的值非常小,会导致进度条弹回开始处(简直不能忍!!)
  var progressBarBg = document.getElementById("progressBarBg");
  progressBarBg.addEventListener(
    "mousedown",
    function (event) {
      // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
      if (!audio.paused || audio.currentTime != 0) {
        var pgsWidth = parseFloat(
          window.getComputedStyle(progressBarBg, null).width.replace("px", "")
        );
        var rate = event.offsetX / pgsWidth;
        audio.currentTime = audio.duration * rate;
        updateProgress(audio);
      }
    },
    false
  );

  // 拖动进度点调节进度
  dragProgressDotEvent(audio);
}

/**
 * 鼠标拖动进度点时可以调节进度
 * @param {*} audio
 */
function dragProgressDotEvent(audio) {
  var dot = document.getElementById("progressDot");
  var position = {
    oriOffestLeft: 0, // 移动开始时进度条的点距离进度条的偏移值
    oriX: 0, // 移动开始时的x坐标
    maxLeft: 0, // 向左最大可拖动距离
    maxRight: 0, // 向右最大可拖动距离
  };
  var flag = false; // 标记是否拖动开始
  // 鼠标按下时
  dot.addEventListener("mousedown", down, false);
  dot.addEventListener("touchstart", down, false);
  // 开始拖动
  document.addEventListener("mousemove", move, false);
  document.addEventListener("touchmove", move, false);
  // 拖动结束
  document.addEventListener("mouseup", end, false);
  document.addEventListener("touchend", end, false);

  function down(event) {
    if (!audio.paused || audio.currentTime != 0) {
      // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
      flag = true;
      position.oriOffestLeft = dot.offsetLeft;
      position.oriX = event.touches ? event.touches[0].clientX : event.clientX; // 要同时适配mousedown和touchstart事件
      position.maxLeft = position.oriOffestLeft; // 向左最大可拖动距离
      position.maxRight =
        document.getElementById("progressBarBg").offsetWidth -
        position.oriOffestLeft; // 向右最大可拖动距离
      // 禁止默认事件(避免鼠标拖拽进度点的时候选中文字)
      if (event && event.preventDefault) {
        event.preventDefault();
      } else {
        event.returnValue = false;
      }

      // 禁止事件冒泡
      if (event && event.stopPropagation) {
        event.stopPropagation();
      } else {
        window.event.cancelBubble = true;
      }
    }
  }

  function move(event) {
    if (flag) {
      var clientX = event.touches ? event.touches[0].clientX : event.clientX; // 要同时适配mousemove和touchmove事件
      var length = clientX - position.oriX;
      if (length > position.maxRight) {
        length = position.maxRight;
      } else if (length < -position.maxLeft) {
        length = -position.maxLeft;
      }
      var progressBarBg = document.getElementById("progressBarBg");
      var pgsWidth = parseFloat(
        window.getComputedStyle(progressBarBg, null).width.replace("px", "")
      );
      var rate = (position.oriOffestLeft + length) / pgsWidth;
      audio.currentTime = audio.duration * rate;
      updateProgress(audio);
    }
  }

  function end() {
    flag = false;
  }
}

/**
 * 更新进度条与当前播放时间
 * @param {object} audio - audio对象
 */
function updateProgress(audio) {
  var value = audio.currentTime / audio.duration;
  console.log(audio, value);
  document.getElementById("progressBar").style.width = value * 100 + "%";
  document.getElementById("progressDot").style.left = value * 100 + "%";
  document.getElementById("audioCurTime").innerText = transTime(
    audio.currentTime
  );
}

/**
 * 播放完成时把进度调回开始的位置
 */
function audioEnded() {
  document.getElementById("progressBar").style.width = 0;
  document.getElementById("progressDot").style.left = 0;
  document.getElementById("audioCurTime").innerText = transTime(0);
  // document.getElementById("audioPlayer").src =
  //   imgDomain + "/static/platform/pic/play.png";
    $('#audioPlayer').addClass('play')
}

/**
 * 音频总时间计算
 */
function timeChange(time, timePlace) {
  //默认获取的时间是时间戳改成我们常见的时间格式
  var timePlace = document.getElementById(timePlace);
  var minute = time / 60;
  var minutes = parseInt(minute);
  if (minutes < 10) {
    minutes = "0" + minutes;
  }
  var second = time % 60;
  seconds = parseInt(second);
  if (seconds < 10) {
    seconds = "0" + seconds;
  }
  var allTime = "" + minutes + "" + ":" + "" + seconds + "";
  timePlace.innerHTML = allTime;
}

/**
 * 音频播放时间换算
 * @param {number} value - 音频当前播放时间,单位秒
 */
function transTime(value) {
  var time = "";
  var h = parseInt(value / 3600);
  value %= 3600;
  var m = parseInt(value / 60);
  var s = parseInt(value % 60);
  if (h > 0) {
    time = formatTime(h + ":" + m + ":" + s);
  } else {
    time = formatTime(m + ":" + s);
  }

  return time;
}

/**
 * 格式化时间显示,补零对齐
 * eg:2:4  -->  02:04
 * @param {string} value - 形如 h:m:s 的字符串
 */
function formatTime(value) {
  var time = "";
  var s = value.split(":");
  var i = 0;
  for (; i < s.length - 1; i++) {
    time += s[i].length == 1 ? "0" + s[i] : s[i];
    time += ":";
  }
  time += s[i].length == 1 ? "0" + s[i] : s[i];

  return time;
}
// 元素的拖拽
function getInner() {
  if (typeof innerHeight == "undefined") {
    return {
      w: document.documentElement.clientWidth,
      h: document.documentElement.clientHeight,
    }; //IE浏览器适用
  } else {
    return {
      w: innerWidth,
      h: innerHeight,
    }; //非IE浏览器适用
  }
}
// 窗口拖拽
function drag(obj) {
  var box = document.getElementById("audioDrag");
  //当鼠标在被拖拽元素上按下,开始拖拽
  obj.onmousedown = function (event) {
    //设置obj捕获所有的鼠标按下事件,而不仅仅是在元素内部区域
    event = event || window.event;
    //鼠标在元素中的偏移量等于 鼠标的clientX - 元素的offsetLeft
    var ol = event.clientX - box.offsetLeft;
    var ot = event.clientY - box.offsetTop;
    //为document绑定一个onmousemove事件
    document.onmousemove = function (event) {
      event = event || window.event;
      //获取鼠标的坐标
      var left = event.clientX - ol;
      var top = event.clientY - ot;
      //修改元素的位置 修改元素的位置只能通过 元素.style.属性 = "属性值";
      box.style.left = left + "px";
      box.style.top = top + "px";
      //边界判断
      if (left <= 0) {
        //左右边界限定
        left = 0;
        box.style.left = 0 + "px";
      } else if (left >= getInner().w - box.offsetWidth) {
        //元素在最右边时的判定,屏幕的宽度减去元素自身的宽度
        left = getInner().w - box.offsetWidth-12;
        box.style.left = left + "px";
      }
      if (top <= 0) {
        //上下边界限定
        top = 0;
        box.style.top = 0 + "px";
      } else if (top >= getInner().h - box.offsetHeight) {
        //元素在最下边时的判定,屏幕的高度减去元素自身的高度
        top = getInner().h - box.offsetHeight-12;
        box.style.top = top + "px";
      }
    };
    //为document绑定一个鼠标松开事件onmouseup
    document.onmouseup = function () {
      document.onmousemove = null;
      document.onmouseup = null;
    };
    return false;
  };
}

效果图:
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值