由为学姐庆祝生日所想到的——网站背景音乐播放

事件起因

在为漂亮姐姐写庆祝生日的网站时,想添加一段背景音乐烘托气氛,但是发现仅仅使用js来控制背景音乐触发没用,会报错,报错原因如下

Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.

检索发现是因为浏览器禁止在用户不交互时触发音乐视频等,所以搜索了半天,最后还是才有业内比较常见的交互式触发。

固定按钮触发

用绝对定位在右上角添加一个固定按钮,通过点击按钮来控制音乐的暂停和播放。代码逻辑是通过js代码控制图片的切换来反映音乐的播放和暂停的状态

实现步骤:

  1. HTML 结构:创建一个按钮元素,用于用户点击切换播放和暂停。
  2. CSS 样式:定义按钮的基本样式,以及播放和暂停状态下的不同背景图片。
  3. JavaScript 逻辑:编写脚本来处理点击事件,切换播放和暂停状态,并更新按钮的样式。

HTML

bash 复制代码
<button id="playPauseButton" class="play-pause"></button>

CSS

css 复制代码
.play-pause {
  width: 50px;
  height: 50px;
  background-size: contain;
  background-repeat: no-repeat;
  background-image: url("../svg/播放.svg");
  border: none;
  cursor: pointer;
}

.play-pause.playing {
  background-image: url("../svg/暂停.svg");
}

JavaScript/TypeScript

ini 复制代码
const playPauseButton = document.getElementById('playPauseButton');
let isPlaying = false; // 初始状态为未播放

playPauseButton.addEventListener('click', () => {
  isPlaying = !isPlaying; // 切换播放状态

  if (isPlaying) {
    // 如果当前是播放状态,则开始播放音频并更新按钮样式
    audio.play();
    playPauseButton.classList.add('playing');
  } else {
    // 如果当前是暂停状态,则暂停音频并更新按钮样式
    audio.pause();
    playPauseButton.classList.remove('playing');
  }
});

这样,当点击按钮时,isPlaying 变量的状态会切换。根据这个状态,脚本会控制音频的播放或暂停,并且切换按钮的 CSS 类以更新背景图片。

切换实现效果如下

添加一点小旋转

当然,播放时最好设置一个图片的旋转,可以使用css的动画帧

具体来说,可以创建一个 @keyframes 动画,它定义了从开始到结束的动画过程,然后将这个动画应用到图标元素上。

CSS

首先,定义一个 @keyframes 规则来描述旋转动作:

css 复制代码
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

然后,将这个动画应用到你想要旋转的元素上。例如,如果你想让 .play-pause 类的元素旋转:

css 复制代码
.play-pause {
  animation: rotate 2s linear infinite;
  /* 其他样式 */
}

在这个例子中,动画名称是 rotate,它将在 2 秒内从 0 度旋转到 360 度,并且会无限次重复。linear 表示动画的速度在其整个持续时间内保持不变。

其它业内方案

闲的没事还同时考察了一些其它网页的音乐播放设置。发现业内在该方面还是有一些不同的解决方案。

如原神的官网中,他就默认实现了自动播放音乐,但是很奇怪的是需要从首页进入main页才能播放音频,而直接进入main是播放不了的,同时浏览器搜索只能搜出首页,搜不到main,很怀疑是不是为了故意让用户交互而设置。不知道米哈游是搞了什么奇怪的黑科技,同样有音乐按钮

ys.mihoyo.com/

ys.mihoyo.com/main/

在腾讯的白荆回廊中,它是使用的是全局点击捕捉(我觉得有点奇怪的),对全局的按钮点击进行捕获,这让我想起了js的冒泡事件,对冒泡事件的捕获。似乎在window上加的事件监听,对功能性按钮的点击会往上冒泡到最顶层的全局事件------音乐播放。同时没有音乐按钮。

白荆回廊-官方网站「于世界交点之处,逢似曾相识之人」 (qq.com)

原理探讨

developer.mozilla.org/zh-CN/docs/...

核心逻辑在mdn的文章中已经讲的很清楚了。小结一下就是通常浏览器会提供各种方式禁用自动播放音频功能,但是有以下例外:

  • 音频被静音或其音量设置为 0
  • 用户和网页已有交互行为(包括点击、触摸、按下某个键等等)
  • 网站已被列入白名单;如果浏览器确定用户经常与媒体互动,这可能会自动发生,也可能通过首选项或其他用户界面功能手动发生
  • 自动播放权限策略被应用于 <iframe> 或者其文档上,从而获得了自动播放的权限。

普遍采用的是第二种交互行为方案。同时除js设置触发外,也可通过autoplay属性触发自动播放。如下

ini 复制代码
<audio id="musicplayer" autoplay>
  <source src="/music/chapter1.mp4" />
</audio>

综上,真是学无止境,随便写点小网站也能发现这么多的背后知识,真是学海无涯。 最后贴一下项目的Github地址,求Star:abandon888/happy-birthday: 简约的生日祝福网站,可用于表白和祝福特别的人 (github.com)

相关推荐
Momo__21 分钟前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
程序员小富27 分钟前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇27 分钟前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇27 分钟前
React中的forwardRef
前端·react.js·面试
槑有老呆36 分钟前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马38 分钟前
Verilog开发常见问题汇总解析
前端
子兮曰40 分钟前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端
weedsfly44 分钟前
语法糖褪去之后——Babel 转译产物中的 JavaScript 本貌
前端·javascript
JustHappy1 小时前
「软件设计思想杂谈🤔」“切图仔”也能懂编译原理?框架源码也许没那么难。聊聊 Vue 的编译(上)
前端·javascript·vue.js