找到一个 程序员表白神器 的动画页面,看着画面非常好,结合其他的一些 表白 动画页面是可以有音乐的,就想着给它加一个。结果翻开代码一看,已经添加了,并且还设置了自动播放:

<body>
    <audio autoplay="autoplay">
        <source src="renxi.mp3" type="audio/mp3">
    </audio>
...

都知道的一个事实是,最近(有可能是好几年之前了)浏览器都做了更新,不允许页面一进来就播放音乐,需要有用户的互动操作才能播放。所以这个自动播放播放了个寂寞。

在页面加载之后使用 js 播放音乐也是不行的。原因就想上面说的,浏览器禁用了,这时会报错:

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

可以用一个按钮的点击来触发音乐播放。这个动画页面一开始恰好有一个按钮,找到这个按钮的点击事件并添加播放就好:

程序员表白神器动画页面 - 开始页面

$("audio")[0].play();

html 直接定位显示,这个 ? 的开始按钮是被画到 canvas 画布里的。直接放在 canvas 的点击事件上也可以,但最好能够是在点击 ? 开始按钮时触发。

canvas.click(function(e) {

    var offset = canvas.offset(), x, y;

    x = e.pageX - offset.left;

    y = e.pageY - offset.top;

    if (seed.hover(x, y)) {

        hold = 0; 

        canvas.unbind("click");

        canvas.unbind("mousemove");

        canvas.removeClass('hand');

        $('audio')[0].play();
    }

})

其中的 seed.hover(x, y) 根据 canvas 上的坐标点背景图片颜色为红色来识别 ? 开始按钮,结合 canvas.click() canvas 点击事件,就能组合成 ? 开始按钮的点击事件处理。

此时还想点击的时候就触发全屏显示,正好其中一个样例有现成的,直接拿过来用:

function kaishi() {
    document.getElementsByTagName("audio")[0].play();
    var docElm = document.documentElement;
    //W3C
    if (docElm.requestFullscreen) {
        docElm.requestFullscreen();
    }
    //FireFox
    else if (docElm.mozRequestFullScreen) {
        docElm.mozRequestFullScreen();
    }
    //Chrome等
    else if (docElm.webkitRequestFullScreen) {
        docElm.webkitRequestFullScreen();
    }
    //IE11
    else if (elem.msRequestFullscreen) {
        elem.msRequestFullscreen();
    }
}
...
canvas.click(function(e) {

    var offset = canvas.offset(), x, y;

    x = e.pageX - offset.left;

    y = e.pageY - offset.top;

    if (seed.hover(x, y)) {

        hold = 0; 

        canvas.unbind("click");

        canvas.unbind("mousemove");

        canvas.removeClass('hand');

        kaishi()
    }

})

完美!

在快结束的时候,突然发现一个奇怪的现象:程序员表白神器 页面上点击查看演示,打开的演示 demo 页面会自动播放音乐。刷新 demo 页面后就不会自动播放了,但如果是在刷新 demo 页面,底栏进度条加载到 80-90 的时候点击页面,此时音乐也会播放。源码应该是一样的,demo 页面就是在当前页面中通过 iframe 引入了这个源码页面:

    <div id="iframe-wrap">
        <iframe id="iframe" src="https://www.jq22.com/demo/love-141127195922" frameborder="0" width="100%" height="758px"></iframe>
    </div>

暂时没有找到原因。

PS

jquery 播放 mp3 代码为 $('audio')[0].play();。因为通过 $('audio') 标签获取到的是一个标签元素数组。

通过按钮控制暂停和播放(参考:jquery播放mp3):

$("#playButton").click(function() {
    var audio = document.getElementById("myAudio");
    if (audio.paused) {
      audio.play();
      $(this).text("暂停");
    } else {
      audio.pause();
      $(this).text("播放");
    }
  });

另外,还可以参考:HTML页面激活态:为何音频无法自动播放?,定时判断页面是否属于激活可播放状态:

<script>
    const t = setInterval(() => {
            if (navigator.userActivation.hasBeenActive){
                // 页面进入粘性激活态
                const v = document.createElement('video')
                v.src = './test.mp4'
                v.autoplay = true
                document.body.appendChild(v)
                clearInterval(t)
            }
        }, 1000);
</script>

但因为激活需要用户的互动操作,比如点击,所以感觉没用上。