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
我使用 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