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

事件起因

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

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排5 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!6 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰7 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen9 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马9 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒10 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端