You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTML5浏览器Fullscreen模式下视频Hotspot显示定位异常求助

HTML5视频全屏模式下Hotspot失效问题解决方案

1. 修复层级与交互遮挡

  • 将Hotspot容器直接嵌套在视频的父容器内,确保全屏时它属于全屏元素的子节点,不会被浏览器的全屏上下文遮挡。
  • 给Hotspot设置z-index: 9999(需高于视频原生控件层级),同时显式声明pointer-events: auto,强制启用鼠标交互。如果视频元素曾设置pointer-events: none,需要单独为Hotspot解除限制。

2. 同步全屏时的位置与尺寸

  • 监听全屏状态变化事件,在进入/退出全屏时重新计算Hotspot的坐标和大小:
    // 兼容各浏览器的全屏事件
    const fullscreenEvents = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'msfullscreenchange'];
    const video = document.getElementById('target-video');
    const hotspot = document.getElementById('video-hotspot');
    
    // 存储原始窗口模式下的Hotspot参数
    const originalHotspot = {
      x: parseFloat(hotspot.style.left),
      y: parseFloat(hotspot.style.top),
      width: parseFloat(hotspot.style.width),
      height: parseFloat(hotspot.style.height)
    };
    
    function adjustHotspot() {
      if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement) {
        // 获取全屏视频的实际渲染尺寸
        const videoRect = video.getBoundingClientRect();
        // 计算缩放比例:全屏尺寸 / 视频原生分辨率
        const scaleX = videoRect.width / video.videoWidth;
        const scaleY = videoRect.height / video.videoHeight;
        // 按比例更新Hotspot位置和大小
        hotspot.style.left = `${originalHotspot.x * scaleX}px`;
        hotspot.style.top = `${originalHotspot.y * scaleY}px`;
        hotspot.style.width = `${originalHotspot.width * scaleX}px`;
        hotspot.style.height = `${originalHotspot.height * scaleY}px`;
      } else {
        // 退出全屏,恢复原始参数
        hotspot.style.left = `${originalHotspot.x}px`;
        hotspot.style.top = `${originalHotspot.y}px`;
        hotspot.style.width = `${originalHotspot.width}px`;
        hotspot.style.height = `${originalHotspot.height}px`;
      }
    }
    
    fullscreenEvents.forEach(event => document.addEventListener(event, adjustHotspot));
    
  • 优先使用相对定位+百分比单位定义Hotspot的初始位置和尺寸,比如left: 20%、top: 30%,这样全屏时父容器尺寸变化,Hotspot会自动适配比例,减少手动计算的工作量。

3. 时间戳同步的稳定实现

  • 监听视频timeupdate事件,根据当前播放时间切换对应Hotspot的样式和状态:
    // 示例:存储各时间节点的Hotspot配置
    const hotspotConfigs = [
      { start: 0, end: 5, x: 100, y: 150, width: 80, height: 80, shape: 'circle' },
      { start: 5, end: 12, x: 200, y: 200, width: 120, height: 60, shape: 'rect' }
    ];
    
    video.addEventListener('timeupdate', throttle(() => {
      const currentTime = video.currentTime;
      const matchedConfig = hotspotConfigs.find(config => currentTime >= config.start && currentTime <= config.end);
      
      if (matchedConfig) {
        const videoRect = video.getBoundingClientRect();
        const scaleX = videoRect.width / video.videoWidth;
        const scaleY = videoRect.height / video.videoHeight;
        
        hotspot.style.display = 'block';
        hotspot.style.left = `${matchedConfig.x * scaleX}px`;
        hotspot.style.top = `${matchedConfig.y * scaleY}px`;
        hotspot.style.width = `${matchedConfig.width * scaleX}px`;
        hotspot.style.height = `${matchedConfig.height * scaleY}px`;
        hotspot.style.borderRadius = matchedConfig.shape === 'circle' ? '50%' : '0';
      } else {
        hotspot.style.display = 'none';
      }
    }, 100)); // 节流到每100ms执行一次,优化性能
    
    // 节流函数实现
    function throttle(func, delay) {
      let lastCall = 0;
      return function(...args) {
        const now = Date.now();
        if (now - lastCall >= delay) {
          func.apply(this, args);
          lastCall = now;
        }
      };
    }
    

4. 浏览器兼容性细节

  • 避免依赖浏览器全屏模式的默认样式,比如不要用visibility: hidden控制Hotspot显示,改用display: none或opacity: 0配合pointer-events: none禁用非目标状态的交互。
  • 测试时注意:部分浏览器会在全屏时隐藏页面其他元素的滚动条,确保Hotspot的计算不受滚动偏移影响,始终基于getBoundingClientRect()获取视频的视口坐标。

内容的提问来源于stack exchange,提问作者Ursa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:07:15