阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 多媒体事件('onplay'、'onpause'、'onended'等)

多媒体事件('onplay'、'onpause'、'onended'等)

作者:陈川 阅读数:27003人阅读 分类: HTML

多媒体在现代网页中扮演着重要角色,HTML5提供了一系列事件来精确控制音频和视频的播放行为。onplayonpauseonended等事件允许开发者捕捉用户交互或媒体状态变化,实现动态响应。

onplay 事件

当媒体开始播放或从暂停状态恢复时触发onplay事件。典型场景包括:

  • 更新界面播放/暂停按钮状态
  • 开始记录播放时长
  • 触发动画效果
<video id="myVideo" controls>
  <source src="video.mp4" type="video/mp4">
</video>

<script>
  const video = document.getElementById('myVideo');
  video.onplay = function() {
    console.log('视频开始播放');
    document.querySelector('.play-btn').textContent = '⏸';
  };
</script>

实际案例:视频平台在播放时自动隐藏控制栏,3秒无操作后淡出。可通过onplay重置淡出计时器:

let hideTimer;
video.onplay = () => {
  clearTimeout(hideTimer);
  controls.style.opacity = '1';
  hideTimer = setTimeout(() => {
    controls.style.opacity = '0';
  }, 3000);
};

onpause 事件

当播放被暂停或程序调用pause()方法时触发。常见用途:

  • 保存当前播放位置
  • 显示暂停状态UI
  • 暂停相关动画
video.onpause = () => {
  localStorage.setItem('videoPosition', video.currentTime);
  document.querySelector('.play-btn').textContent = '▶';
};

高级用法:结合requestAnimationFrame实现暂停时的帧精确截图:

let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');

video.onpause = () => {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  ctx.drawImage(video, 0, 0);
  document.body.appendChild(canvas);
};

onended 事件

媒体播放完成时触发,适用于:

  • 自动播放下一集
  • 显示结束推荐内容
  • 重置播放器状态
video.onended = () => {
  if (playlist.length > 0) {
    video.src = playlist.shift();
    video.play();
  }
};

直播场景扩展:当直播流结束时自动切换到录播回放:

const liveStream = document.getElementById('live');
const replayStream = document.getElementById('replay');

liveStream.onended = () => {
  liveStream.style.display = 'none';
  replayStream.style.display = 'block';
  replayStream.play();
};

其他相关事件

ontimeupdate 事件

在播放位置改变时持续触发,适合实现:

  • 进度条实时更新
  • 字幕同步
  • 基于时间的交互功能
video.ontimeupdate = () => {
  const progress = (video.currentTime / video.duration) * 100;
  progressBar.style.width = `${progress}%`;
  
  // 实现章节跳转
  chapters.forEach(chapter => {
    if (video.currentTime >= chapter.start && 
        video.currentTime < chapter.end) {
      chapterNav.classList.add('active');
    }
  });
};

onvolumechange 事件

音量变化或静音状态改变时触发:

video.onvolumechange = () => {
  volumeDisplay.textContent = Math.round(video.volume * 100);
  muteBtn.classList.toggle('active', video.muted);
};

onwaitingonplaying 事件

缓冲状态切换时触发,用于显示加载指示器:

const spinner = document.querySelector('.spinner');

video.onwaiting = () => spinner.style.display = 'block';
video.onplaying = () => spinner.style.display = 'none';

事件组合应用

实现一个完整的播放器控制逻辑:

const video = document.getElementById('videoPlayer');
const controls = {
  playBtn: document.querySelector('.play-btn'),
  timeDisplay: document.querySelector('.time'),
  progress: document.querySelector('.progress-bar')
};

// 综合事件处理
video.onplay = () => {
  controls.playBtn.textContent = '❚❚';
  startPlaybackAnalytics();
};

video.onpause = () => {
  controls.playBtn.textContent = '►';
  sendPlaybackAnalytics();
};

video.onended = () => {
  showRecommendations();
  resetPlayer();
};

video.ontimeupdate = () => {
  const minutes = Math.floor(video.currentTime / 60);
  const seconds = Math.floor(video.currentTime % 60);
  controls.timeDisplay.textContent = 
    `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
  
  const progress = (video.currentTime / video.duration) * 100;
  controls.progress.style.width = `${progress}%`;
};

// 自定义方法
function startPlaybackAnalytics() {
  // 实现播放统计逻辑
}

function showRecommendations() {
  // 显示相关推荐内容
}

移动端特殊处理

移动浏览器通常限制自动播放,需要特殊处理:

// 检测是否允许自动播放
video.onplay = () => {
  console.log('播放开始');
};

const playPromise = video.play();

if (playPromise !== undefined) {
  playPromise.catch(error => {
    // 显示点击播放按钮
    showPlayButton();
  });
}

function showPlayButton() {
  const overlay = document.createElement('div');
  overlay.className = 'play-overlay';
  overlay.onclick = () => {
    video.play();
    overlay.remove();
  };
  document.body.appendChild(overlay);
}

性能优化建议

  1. 事件节流:对高频事件如timeupdate进行节流
let lastUpdate = 0;
video.ontimeupdate = () => {
  const now = Date.now();
  if (now - lastUpdate > 200) {  // 每200ms更新一次
    updateProgressBar();
    lastUpdate = now;
  }
};
  1. 事件委托:多个媒体元素时使用事件委托
document.addEventListener('play', function(e) {
  if (e.target.tagName === 'VIDEO') {
    // 处理所有视频播放事件
  }
}, true);
  1. 内存管理:移除不需要的事件监听器
function setupPlayer() {
  video.onplay = handlePlay;
}

function teardownPlayer() {
  video.onplay = null;
}

浏览器兼容性实践

处理不同浏览器的事件差异:

// 检测能否自动播放
function checkAutoPlay() {
  const promise = video.play();
  if (promise !== undefined) {
    promise.catch(() => {
      // 旧版本浏览器处理
      video.muted = true;
      video.play();
    }).then(() => {
      // 新版本浏览器处理
      if (video.muted) {
        showUnmuteButton();
      }
    });
  }
}

// 统一事件处理
const events = ['play', 'playing', 'waiting', 'pause'];
events.forEach(event => {
  video.addEventListener(event, handleAllEvents);
});

高级应用场景

画中画模式控制

video.onenterpictureinpicture = () => {
  console.log('进入画中画模式');
  updatePiPControls(true);
};

video.onleavepictureinpicture = () => {
  console.log('退出画中画模式');
  updatePiPControls(false);
};

function updatePiPControls(isInPiP) {
  pipBtn.classList.toggle('active', isInPiP);
}

媒体会话API集成

video.onplay = () => {
  if ('mediaSession' in navigator) {
    navigator.mediaSession.playbackState = 'playing';
    navigator.mediaSession.setActionHandler('pause', () => {
      video.pause();
    });
  }
};

WebRTC 流处理

const stream = await navigator.mediaDevices.getUserMedia({video: true});
const video = document.createElement('video');
video.srcObject = stream;

video.onplay = () => {
  console.log('摄像头视频流开始');
  startFaceDetection();
};

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌