编写属于自己的音乐播放器

前言

我们在 Web 开发过程中,有很多用到音频元素audio的场景,如音乐播放器、语音播放等功能,但是由于原生组件有以下缺点:

  • 原生UI样式丑,在追求美观的页面中需要重写元素样式,而且支持重写的样式不多。
  • 浏览器兼容问题,不同浏览器的音频元素展示不同。

因为以上两个问题,这就导致我们需要对原生的audio进行修改时比较困难。而对于大多数音频的需求,我们可以使用满足我们要求的第三方组件库中选择,如:

而对于 UI 有要求的需求,比如音乐播放器的需求,那就要遵循整个页面的 UI 主题,这种情况下我们就需要自定义编写一个音频组件了。

在本文中,我们将学会:

  1. 如何修改音频元素的默认样式
  2. 如何重写音频自定义样式

如何修改音频元素的默认样式

默认情况下,音频元素不可见。需要添加控件属性以使其控件可见。

<audio controls="true" src="音频.mp3" ></audio>

image.png

音频元素在CSS中具有以下伪元素选择器:

audio::-webkit-media-controls-panel
audio::-webkit-media-controls-mute-button
audio::-webkit-media-controls-play-button
audio::-webkit-media-controls-timeline-container
audio::-webkit-media-controls-current-time-display
audio::-webkit-media-controls-time-remaining-display
audio::-webkit-media-controls-timeline
audio::-webkit-media-controls-volume-slider-container
audio::-webkit-media-controls-volume-slider
audio::-webkit-media-controls-seek-back-button
audio::-webkit-media-controls-seek-forward-button
audio::-webkit-media-controls-fullscreen-button
audio::-webkit-media-controls-rewind-button
audio::-webkit-media-controls-return-to-realtime-button
audio::-webkit-media-controls-toggle-closed-captions-button

这写伪类选择器,可以改变音频元素的基本样式,但是仅在Chrome浏览器下有效。

我把所有的伪类都给上不同的背景颜色,最后呈现的效果如下图所示:

audio::-webkit-media-controls-xxx{
  background-color: 颜色随机;
}

image.png

也就是,只能修改部分样式,没有提供更细致的修改。

如果想要设置进度条的颜色,基本只能自定义重写播放器了。

自定义音频播放器

接下来,将是我们本文的重点,我们将创建自己的自定义音频播放器。

我们自定义的播放器,它使用不同的元素来实现控件的UI。然后在 Javascript 的帮助下将音频元素的功能绑定到这些元素。

首先我们先写一个简单的布局

    <div id="audio-player">
      <audio src="xx.mp3" style="display: none" ></audio><!--audio 播放器,隐藏掉-->
      <div class="poster"> <img src='xx.png'/></div><!--封面图-->
      <div class="controls">
        <div class="poster">音乐播放器</div>
        <div class="controls-con">
          <button class="player-button"> <!-- 播放暂停按钮图片 --> </button>
          <input type="range" class="timeline" max="100" value="0" /><!--进度条 使用input[ragne]实现-->
          <button class="sound-button"> <!-- 音量开关按钮图片 --></button>
        </div>
      </div>
    </div>

我们首先创建了一个audio元素,但是不需要它显示,只需要它的音频功能,也不需要它的UI。然后我们自定义播放器的封面图、控件等UI元素,样式可以自己调整,就不放CSS了,我调整后显示结果大概是这样。

image.png

然后我们如何将自己定义的元素控件去作用于这个audio元素呢?这就需要用到它的一些属性和方法了,如:

  • 属性

    • currentTime-当前音频的播放位置<string>
    • duration-音频的播放总长度<string>
    • muted-是否静音<boolean>
  • 方法

    • play()-播放
    • pause()-暂停
    • ended()-播放结束
    • timeupdate()-音频位置变化

具体参考 MDN-audio

还有关于进度条的改变,可以通过<input type='range'>去简单实现进度条。从而可以监听进度条位置,改变音频位置。反之可以通过监听audiotimeupdate方法改变进度条。 这里主要用到的属性和方法为:

  • 属性

    • value-当前进度<number>
  • 方法

    • change-进度条改变

说到这,大家也就应该明白了,我们利用原有的audio的方法和属性去实现自己的 UI 控件,这其实也是流行音频组件库的做法。
下面直接看音频控件的 javaScript 代码:

const playerButton = document.querySelector(".player-button"),// 获取播放/暂停按钮
  audio = document.querySelector("audio"),// 获取音频
  timeline = document.querySelector(".timeline"),// 获取进度条
  soundButton = document.querySelector(".sound-button"),// 过去音量按钮(是否静音)

// 1. 通过监听按钮的点击时间,修改音频的播放、暂停状态,并设置对应的 icon.
playerButton.addEventListener("click", ()=> {
  if (audio.paused) {
    audio.play();
    playerButton.innerHTML = pauseIcon;
  } else {
    audio.pause();
    playerButton.innerHTML = playIcon;
  }
});
// 2. 通过监听音频播放的进度设置 input 进度条的 value.
audio.ontimeupdate=()=> {
  const percentagePosition = (100 * audio.currentTime) / audio.duration;
  timeline.style.backgroundSize = `${percentagePosition}% 100%`;
  timeline.value = percentagePosition;
}

// 3. 如果播放结束,将播放按钮重置为暂停状态。
audio.onended = audioEnded=()=>{
  playerButton.innerHTML = playIcon;
}

// 4. 监听进度条变化,并设置音频位置。
timeline.addEventListener("change", ()=>{
  const time = (timeline.value * audio.duration) / 100;
  audio.currentTime = time;
});

// 5. 监听音频按钮变化,并设置对应的状态(是否静音)和icon
soundButton.addEventListener("click", ()=>{
  audio.muted = !audio.muted;
  soundButton.innerHTML = audio.muted ? muteIcon : soundIcon;
});

代码片段

结论

使用伪元素选择器,您可以对音频元素进行简单的设计更改。

对于更复杂的设计更改,最好实现自定义音频播放器,然后使用 Javascript 将其绑定到音频元素以提供必要的功能。

到这里,基本就学会了自定义音频播放器了,希望大家能有所收获。


九旬的博客
关注我,每周输出一篇前端技术文章, 博客地址:[链接]

关注我,每周输出一篇前端技术文章,

1k 声望
1.2k 粉丝
0 条评论
推荐阅读
学会这些 Web API 使你的开发效率翻倍
随着浏览器的日益壮大,浏览器自带的功能也随着增多,在 Web 开发过程中,我们经常会使用一些 Web API 增加我们的开发效率。本篇文章主要选取了一些有趣且有用的 Web API 进行介绍,并且 API 可以在线运行预览。C...

九旬13阅读 1.6k

封面图
ESlint + Stylelint + VSCode自动格式化代码(2023)
安装插件 ESLint,然后 File -&gt; Preference-&gt; Settings(如果装了中文插件包应该是 文件 -&gt; 选项 -&gt; 设置),搜索 eslint,点击 Edit in setting.json

谭光志34阅读 20.8k评论 9

安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城32阅读 7.3k评论 5

封面图
涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco24阅读 2.3k评论 3

你可能不需要JS!CSS实现一个计时器
CSS现在可不仅仅只是改一个颜色这么简单,还可以做很多交互,比如做一个功能齐全的计时器?样式上并不复杂,主要是几个交互的地方数字时钟的变化开始、暂停操作重置操作如何仅使用 CSS 来实现这样的功能呢?一起...

XboxYan25阅读 1.7k评论 1

封面图
在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 2k

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.8k评论 3

封面图

关注我,每周输出一篇前端技术文章,

1k 声望
1.2k 粉丝
宣传栏