JavaScript 代码在 Firefox 中有效,但在 Chrome 或 Edge 中无效

JavaScript Code works in Firefox but not in Chrome or Edge

我使用 p5.js 库制作了自己的 JavaScript 音频播放器。该脚本使用 onload() 遍历网页的所有元素,并向 class [=18= 的所有 html 元素添加一个 canvas(显示图形的东西)对象].使用 Firefox 一切正常,它可以播放来自指定文件路径的音频文件。当我在 Chrome 或 Edge 中加载我的网站时,我在控制台中收到以下错误消息:

Not allowed to load local resource: blob:null/59e0d5f9-cf73-4135-9595-3214e6cc964e

此错误消息出现多次,每次都在 blop:null/ 之后出现另一个字符串。还有错误信息:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on
the page. https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio

我认为问题在于 JavaScript 出于安全考虑,不喜欢加载本地文件。但如果是这样的话,为什么它可以在 Firefox 上运行呢?它是一个不安全的浏览器吗? 另外,如果必须在用户交互的帮助下加载音频,有没有办法解决这个问题?就像我说的,在 Firefox 上,这没问题。

我应该补充一点,该网站不在线,它 运行 在本地,我正在使用 Firefox Developer Edition。

此外,如果有 p5.js 用户,我使用 function windowResized() 使 canvas 的大小适应浏览器 window。同样,它在使用 Firefox 时运行良好,但在 Chrome 和 Edge 中它会抛出错误,因为我使用的是我之前未创建的 class 变量(即使我在 function setup() 应该在 windowResized() 之前 运行 并且 - 再次 - 它在 Firefox 上工作正常。

这是 JavaScript 文件的代码:

$(document).ready(function () {

    let audioPanel = function (p) {
        let track;
        let isPlaying;
        let width;
        let height;

        let margin;
        let x;
        let y;
        let dim;

        let volumeSlider;
        let timeSlider;

        let parentTag;
        let filename;
        let playMeta;

        p.windowResized = function () {
            width = innerWidth * 0.6;
            height = innerWidth * 9 / 16 * 0.18;
            p.resizeCanvas(width, height);

            margin = 20;
            x = margin;
            y = margin;
            dim = height - 2 * margin;

            volumeSlider = new slider(this, margin * 3 + dim, height * 0.8, width * 0.5 - margin * 4 - dim, volumeSlider.min, volumeSlider.max, volumeSlider.actualValue, volumeSlider.decimalPrecision, width, height);
            timeSlider = new slider(this, margin * 3 + dim, height * 0.5, width - margin * 12 - dim, timeSlider.min, timeSlider.max, timeSlider.actualValue, timeSlider.decimalPrecision, width, height);
        };

        p.setup = function () {
            p.soundFormats('mp3', 'ogg');
            width = innerWidth * 0.6;
            height = innerWidth * 9 / 16 * 0.18;
            var window = p.createCanvas(width, height);
            //window.parent(parentTag.id);

            parentTag = p.canvas.parentElement;
            filename = parentTag.getElementsByTagName('meta')[0].getAttribute('content');
            track = new Audio(filename);
            let element = p.createElement('h1', parentTag.id);
            element.parent(parentTag.id);
            track.addEventListener('ended', p.finished);


            isPlaying = false;

            margin = 20;
            x = margin;
            y = margin;
            dim = height - 2 * margin;

            track.volume = 0.1;

            volumeSlider = new slider(this, margin * 3 + dim, height * 0.8, width * 0.5 - margin * 4 - dim, 0, 100, 20, 0, width, height);
            timeSlider = new slider(this, margin * 3 + dim, height * 0.5, width - margin * 12 - dim, 0, track.duration, 0, 2, width, height);

            track.addEventListener('loadeddata', function () {
                timeSlider.max = track.duration;
                timeSlider.Update();
            });

            playMeta = p.createElement('meta');
            playMeta.attribute('name', 'isPlaying');
            playMeta.attribute('content', 'false');
        };

        p.draw = function () {
            p.clear();
            p.background(0, 0, 0, 50);

            p.noStroke();
            p.fill(0, 20);
            p.rectMode(p.CORNER);
            p.rect(0, 0, dim + 2 * margin, dim + 2 * margin);

            p.ellipseMode(p.CORNER);
            let alpha = 100;

            if (p.insideButton()) {
                alpha = 200;
            }

            p.fill(255, 255, 255, alpha);
            p.ellipse(x, y, dim, dim);

            p.fill(0, 150);
            p.noStroke();
            if (isPlaying) {
                let dist = dim * 0.15;
                p.rectMode(p.CENTER);
                let w = dim * 0.15;
                let h = dim * 0.5;
                p.rect(x + dim / 2 - dist, y + dim / 2, w, h);
                p.rect(x + dim / 2 + dist, y + dim / 2, w, h);
            } else {
                p.beginShape();
                let r = dim * 0.35;
                let angle = 0;
                let da = p.TWO_PI / 3;
                for (let i = 0; i < 3; i++) {
                    angle = da * i;
                    p.vertex(Math.cos(angle) * r + x + dim / 2, Math.sin(angle) * r + y + dim / 2);
                }
                p.endShape(p.CLOSE);
            }

            timeSlider.Update();
            timeSlider.showText(p.SecondsToTime(track.currentTime) + ' / ' + p.SecondsToTime(track.duration));
            timeSlider.actualValue = track.currentTime;
            timeSlider.onChange = function () {
                track.currentTime = timeSlider.actualValue;
            }
            timeSlider.Render();

            volumeSlider.Update();
            volumeSlider.showText('Volume: ' + volumeSlider.value + '%');
            track.volume = volumeSlider.value / 100;
            volumeSlider.Render();

            if (playMeta.elt.getAttribute('content') == 'false' && isPlaying) {
                p.PauseTrack();
            } else if (playMeta.elt.getAttribute('content') == 'true' && !isPlaying) {
                p.PlayTrack();
            }
        };

        p.PlayTrack = function () {
            track.play();
            isPlaying = true;
            playMeta.attribute('content', 'true');

            let audioPlayers = document.getElementsByClassName('audioPlayer');
            let otherPlayers = [];
            for (let i = 0; i < audioPlayers.length; i++) {
                if (audioPlayers[i].id != parentTag.id) {
                    otherPlayers.push(audioPlayers[i]);
                }
            }
            for (let i = 0; i < otherPlayers.length; i++) {
                let metas = otherPlayers[i].getElementsByTagName('meta');

                let others = [];
                for (let j = 0; j < metas.length; j++) {
                    if (metas[j].getAttribute('content') != filename && metas[j].getAttribute('name') == 'isPlaying') {
                        others.push(metas[j]);
                    }
                }

                for (let j = 0; j < others.length; j++) {
                    let otherPlayMeta = others[j];
                    otherPlayMeta.setAttribute('content', false);
                }
            }
        }

        p.PauseTrack = function () {
            track.pause();
            isPlaying = false;
            playMeta.attribute('content', 'false');
        }

        p.SecondsToTime = function (secs) {
            let minutes = p.nf(p.floor(secs / 60), 2);
            let seconds = p.nf(p.floor(secs % 60), 2, 0);
            let time = minutes + ':' + seconds;

            return time;
        };

        p.mousePressed = function () {
            if (p.insideButton() && p.mouseButton == p.LEFT) {
                if (isPlaying) {
                    p.PauseTrack();
                } else {
                    p.PlayTrack();
                }
            }

            if (volumeSlider.insideSlider() && p.mouseButton == p.LEFT) {
                volumeSlider.followMouse();
            } else if (timeSlider.insideSlider() && p.mouseButton == p.LEFT) {
                timeSlider.followMouse();
            }
        };

        p.mouseReleased = function () {
            volumeSlider.letGo();
            timeSlider.letGo();
        };

        p.finished = function () {
            p.PauseTrack();
            track.currentTime = 0;
            timeSlider.actualValue = track.currentTime;
        };

        p.insideButton = function () {
            return (p.dist(p.mouseX, p.mouseY, x + dim / 2, y + dim / 2) <= dim / 2);
        };

        sketchhandleFile = function (file) {
            track = createAudio(file.data, '');
            track.hide();
        };
    };

    let audioPlayers = document.getElementsByClassName('audioPlayer');

    for (let i = 0; i < audioPlayers.length; i++) {
        let newP5 = new p5(audioPanel, audioPlayers[i].id);
    }

    class slider {
        constructor(p, x, y, w, min, max, startVal, decPris) {
            this.width = p.width;
            this.height = p.height;
            this.decimalPrecision = decPris;
            this.x = x;
            this.y = y;
            this.w = w;
            this.stickToMouse = false;
            this.margin = this.width * 0.08;
            this.offset = 0;
            this.min = min;
            this.max = max;
            this.actualValue = startVal;
            this.onChange = function () { };
            this.p = p;

            this.dotR = p.height * 0.05;
            // this.dotX = map(startVal, min, max, this.x, this.x + w);
            this.value = startVal;
            this.Update();
        }

        Update() {
            if (this.stickToMouse) {
                this.actualValue = this.p.constrain(this.p.map(this.p.mouseX - this.offset, this.x, this.x + this.w, this.min, this.max), this.min, this.max);
                this.onChange();
            }

            // console.log(this.actualValue);
            // console.log(this.min);
            // console.log(this.max);
            // console.log(this.x);
            this.dotX = this.p.map(this.actualValue, this.min, this.max, this.x, this.x + this.w);
            this.value = Math.round(this.actualValue * 10 ^ this.decimalPrecision) / 10 ^ this.decimalPrecision;
        }

        Render() {
            this.p.strokeWeight(this.height * 0.05);
            this.p.stroke(255, 255, 255, 100);
            this.p.strokeCap(this.p.SQUARE);
            this.p.line(this.x, this.y, this.x + this.w, this.y);

            this.p.noStroke();
            let alpha = 150;
            let magnifier = 0;
            if (this.insideSlider() || this.stickToMouse) {
                alpha = 255;
            }
            if (this.stickToMouse) {
                magnifier = this.dotR;
            }
            this.p.fill(0, 0, 0, alpha);
            this.p.rectMode(this.p.CENTER);
            this.p.rect(this.dotX, this.y, this.dotR * 2 + magnifier, this.dotR * 2 + magnifier);
        }

        showText(txt) {
            this.p.fill(0, 0, 0, 100);
            //textFont(font);
            this.p.textAlign(this.p.LEFT, this.p.CENTER);
            this.p.textSize(20);
            this.p.text(txt, this.x + this.w + this.margin / 3, this.y);
        }

        followMouse() {
            this.stickToMouse = true;
            this.offset = this.p.mouseX - this.dotX;
        }

        letGo() {
            this.stickToMouse = false;
        }

        insideSlider() {
            return (this.p.dist(this.p.mouseX, this.p.mouseY, this.dotX, this.y) <= this.dotR);
        }
    }
});

这里是 html 文件的一部分:

<div id="Interstellar - Piano Version" class="audioPlayer">
    <meta name="file" content="audioTracks/interstellar.mp3">
</div>

Firefox 的安全策略 与 chrome 和 edge 不同。可能是因为你直接在本地机器上打开 html 文件。这会导致Chrome和Edge无法直接访问本地资源。如果你想运行在chrome和边缘,请创建一个网络服务器到运行这个文件。

类似于此

并且你可以让chrome有权限访问该文件。 link