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

事件起因

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

相关推荐
喵叔哟12 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django