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

事件起因

在为漂亮姐姐写庆祝生日的网站时,想添加一段背景音乐烘托气氛,但是发现仅仅使用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)

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端