我使用以下 HTML、CSS 和 Javascript 将视频播放器伪装成音频播放器。
它在 Firefox 中完美运行,但在 Chrome 中按播放按钮实际上并没有播放任何内容。
是什么阻止它在 Chrome 中工作以及如何让它在 Chrome 中也工作?
更新:
我想扩展一个我认为可能有帮助的观察(特别感谢@AHaworth 在评论中做出类似的观察):
如果我删除 iframe
{ display: none; }
并且视频播放器最初与音频播放器一起加载,则音频播放器控件(仍然)对视频播放器没有影响。但是,如果我单击视频播放器上的播放,然后使用 CSS 完全隐藏它,我现在可以通过音频播放器完全控制视频播放器..即使视频播放器完全隐藏。
这一观察结果与评论中的 @AHaworth 类似,“控制台中似乎最相关的错误是无法播放视频,因为用户尚未进行交互。”
所以正确的做法是强制“交互”但如何?
在此处查看CodePen。
let player;
const playBtn = document.getElementById('play');
const rewindBtn = document.getElementById('rewind');
const forwardBtn = document.getElementById('forward');
const progressBar = document.getElementById('progress-bar');
const currentTimeEl = document.getElementById('current-time');
const endTimeEl = document.getElementById('end-time');
const speedControl = document.getElementById('speed-control');
const volumeBtn = document.getElementById('volume-btn');
const volumeSlider = document.getElementById('volume-slider');
let duration = 0;
window.addEventListener('load', function() {
player = new playerjs.Player(document.getElementById("bunny-stream-embed"));
player.on('ready', () => {
console.log('Player is ready');
player.getDuration(d => {
duration = d;
endTimeEl.innerText = formatTime(duration);
progressBar.max = duration;
});
// Set initial volume to 70%
player.setVolume(70);
volumeSlider.value = 70;
updateVolumeIcon(0.7);
// Set up event listeners after player is ready
setupEventListeners();
});
player.on('timeupdate', (data) => {
currentTimeEl.innerText = formatTime(data.seconds);
progressBar.value = data.seconds;
});
player.on('play', () => {
playBtn.innerHTML = '❚❚'; // Pause icon
});
player.on('pause', () => {
playBtn.innerHTML = '►'; // Play icon
});
});
function setupEventListeners() {
playBtn.addEventListener('click', () => {
player.getPaused(paused => {
if (paused) {
player.play();
} else {
player.pause();
}
});
});
rewindBtn.addEventListener('click', () => {
player.getCurrentTime(currentTime => {
player.setCurrentTime(Math.max(0, currentTime - 15));
});
});
forwardBtn.addEventListener('click', () => {
player.getCurrentTime(currentTime => {
player.setCurrentTime(Math.min(duration, currentTime + 15));
});
});
progressBar.addEventListener('input', (e) => {
const time = parseFloat(e.target.value);
player.setCurrentTime(time);
});
volumeSlider.addEventListener('input', (e) => {
const volume = e.target.value;
player.setVolume(volume);
updateVolumeIcon(volume);
});
speedControl.addEventListener('click', () => {
const speedOptions = [1, 1.25, 1.5, 2];
let currentSpeed = parseFloat(speedControl.innerText.replace('x', ''));
const newSpeed = speedOptions[(speedOptions.indexOf(currentSpeed) + 1) % speedOptions.length];
speedControl.innerText = `${newSpeed}x`;
player.setPlaybackRate(newSpeed);
});
volumeBtn.addEventListener('click', () => {
player.getVolume(volume => {
if (volume > 0) {
player.setVolume(0);
volumeSlider.value = 0;
} else {
player.setVolume(70);
volumeSlider.value = 70;
}
updateVolumeIcon(volume > 0 ? 0 : 0.7);
});
});
}
function updateVolumeIcon(volume) {
if (volume > 0.5) {
volumeBtn.innerHTML = '🔊';
} else if (volume > 0) {
volumeBtn.innerHTML = '🔉';
} else {
volumeBtn.innerHTML = '🔇';
}
}
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
}
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
iframe {
display: none;
}
.audio-player {
background-color: #1e3d59;
color: white;
width: 100%;
max-width: 800px;
border-radius: 10px;
overflow: hidden;
}
.player-top {
display: flex;
align-items: center;
padding: 20px;
}
.cover {
width: 60px;
height: 60px;
border-radius: 5px;
margin-right: 15px;
}
.info {
flex-grow: 1;
}
.title {
margin: 0;
font-size: 18px;
}
.author {
margin: 5px 0 0;
font-size: 14px;
opacity: 0.8;
}
.bookmark {
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
}
.player-bottom {
background-color: #102c43;
padding: 15px 20px;
}
.progress {
display: flex;
align-items: center;
margin-bottom: 15px;
}
#progress-bar {
flex-grow: 1;
margin: 0 10px;
cursor: pointer;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
}
.control-btn {
background: none;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
}
.play-pause {
font-size: 24px;
}
.playback-rate,
.volume-control {
display: flex;
align-items: center;
}
#volume-slider {
width: 80px;
margin-left: 10px;
}
input[type="range"] {
-webkit-appearance: none;
background: transparent;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
background: #ffffff50;
border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
background: white;
border-radius: 50%;
cursor: pointer;
margin-top: -4px;
}
<script type="text/javascript" src="https:////assets.mediadelivery.net/playerjs/player-0.1.0.min.js"></script>
<iframe id="bunny-stream-embed" src="https://iframe.mediadelivery.net/embed/197133/dc48a09e-d9bb-420a-83d7-72dc2304c034?autoplay=false&preload=true" width="720" height="400" frameborder="0" allow="autoplay"></iframe>
<div class="audio-player">
<div class="player-top">
<img class="cover" src="https://images.blinkist.io/images/books/5bf9dc9c6cee070007cab481/1_1/470.jpg" alt="Book Cover">
<div class="info">
<h2 class="title">Atomic Habits</h2>
<p class="author">James Clear</p>
</div>
<button class="bookmark">★</button>
</div>
<div class="player-bottom">
<div class="progress">
<span id="current-time">00:00</span>
<input id="progress-bar" type="range" min="0" max="100" value="0">
<span id="end-time">00:00</span>
</div>
<div class="controls">
<button id="rewind" class="control-btn">← 15</button>
<button id="play" class="control-btn play-pause">►</button>
<button id="forward" class="control-btn">15 →</button>
<div class="playback-rate">
<button id="speed-control" class="control-btn">1x</button>
</div>
<div class="volume-control">
<button id="volume-btn" class="control-btn">🔊</button>
<input type="range" id="volume-slider" min="0" max="100" value="70">
</div>
</div>
</div>
</div>
<script src="script.js"></script>
这不是完整的答案,但我将信息放在这里,以防它可以引导某人获得完整的解释和解决方案。
在给定的 codepen 中,如果我将初始样式表中的 iframe CSS 更改为:
iframe {
opacity: 0;
z-index: 1;
position: absolute;
}
然后播放箭头更改为暂停图标,我将 iframe 的显示属性更改为“无”播放器工作。
player.on('play', () => {
playBtn.innerHTML = '❚❚'; // Pause icon
document.querySelector('iframe').style.display = 'none';
});
或者至少,看起来可以工作,因为当然第一次点击是直接在 iframe 上,而不是控制面板上的某个特定位置。