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

为什么HTML5滚动视频在Safari更流畅?其他浏览器如何优化?

滚动同步视频动画跨浏览器流畅度差异问题

我和合作者正在开发滚动同步视频动画效果,要求页面向下滚动时视频能够同步播放。我们经过多轮视频压缩迭代优化播放流畅度,过程中发现哪怕是体积最大的视频在桌面端和移动端Safari上都播放流畅,但最小体积的视频在其他浏览器上仍存在明显卡顿。我们的目标是让视频达到滚动控制HTML5视频示例的流畅度。

为什么Safari上的播放表现要流畅得多?我们希望在其他浏览器上也达到同等流畅度,目前推测enter-view.js所依赖的requestAnimationFrame函数在Safari上的优化程度更高,不确定是否应当更换其他动画策略。

实现代码

JavaScript 代码

const container = d3.select('#scrolly-overlay');
const stepSel = container.selectAll('.step');
const progressCounter = d3.select('#progress');
let vid = document.getElementById('v0');
const containerHeightMultiplier = 300;
const vidUrls = [{
    format: 'webm',
    name: '10FPS_CQ_35',
    file: 'TestVidLowRes_VP8_10FPS_CQ35',
    size: "6.5MB"
  },
  {
    format: 'webm',
    name: '10FPS_CQ_45',
    file: 'TestVidLowRes_VP8_10FPS_CQ45',
    size: "4.8MB"
  },
  {
    format: 'mp4',
    name: '10FPS_RF_27',
    file: 'TestVidLowRes_H264_10FPS_RF27',
    size: "4.7MB"
  },
  {
    format: 'mp4',
    name: '10FPS_RF_40',
    file: 'TestVidLowRes_H264_10FPS_RF40',
    size: "0.5MB"
  },
  {
    format: 'webm',
    name: '5FPS_RF_40',
    file: 'testVidLowRes_VP8_5FPS_CQ35',
    size: '3.4MB'
  }
]
d3.select('#vid-selection').selectAll('button').data(vidUrls).join('button')
  .text(d => d.name + '.' + d.format + '-' + d.size)
  .on('click', (event, d) => {
    d3.select('#vid-source')
      .attr('type', 'video/' + d.format)
      .attr('src', "https://s3.us-west-1.amazonaws.com/tao.mo.2021/" + d.file + '.' + d.format)
    d3.select('#selected-vid')
      .text(d.format + ': ' + d.name + ' (' + d.size + ')')
    vid.load()

    vid.addEventListener('loadedmetadata', function() {
      console.log(vid.fileSize)
      d3.select('#scrolly-overlay .scrolly article .step').style('min-height', Math.floor(vid.duration) * containerHeightMultiplier + "px")

    });
  })

function updateChart(index) {
  stepSel.classed('is-active', (d, i) => i === index);
}

function updateVid(progress) {
  progressCounter.text(progress);
}

function init() {
  Stickyfill.add(d3.select('.sticky').node());

  enterView({
    selector: stepSel.nodes(),
    offset: 0.5,
    enter: el => {
      const index = +d3.select(el).attr('data-index');
      updateChart(index);
    },
    progress: (el, progress) => {
      progressCounter.text(progress);
      vid.currentTime = progress * vid.duration
    },
    exit: el => {
      let index = +d3.select(el).attr('data-index');
      index = Math.max(0, index - 1);
      updateChart(index);
    }
  })
}

init();

CSS 代码

.filler {
  height: 20rem;
  text-align: center;
}

#scrolly-overlay .scrolly {
  max-width: 60rem;
  margin: 3rem auto;
  background-color: #f4f4f4;
  padding: 1rem;
}

#scrolly-overlay .scrolly article {
  padding: 0;
  max-width: 30rem;
  margin: 0 auto;
  position: relative;
}

#scrolly-overlay .scrolly article .step {
  margin-bottom: 1rem;
}

#scrolly-overlay .scrolly article .step:last-of-type {
  margin-bottom: 0;
}

#scrolly-overlay .scrolly article .step.is-active p {
  background-color: #008080;
}

#scrolly-overlay .scrolly article .step p {
  margin: 0;
  padding: 1rem;
  text-align: center;
  font-weight: 400;
  background-color: #5b5b5b;
  transition: background-color 250ms ease-in-out;
  color: #f4f4f4;
}

#scrolly-overlay .scrolly figure.sticky {
  position: sticky;
  width: 100%;
  height: 75vh;
  margin: 0;
  top: 3vh;
  left: 0;
}

#scrolly-overlay .scrolly figure.sticky video {
  position: absolute;
  top: 1%;
  left: 0.5%;
  width: 99%;
  background-color: #fff;
}

#scrolly-overlay .scrolly figure.sticky #progress {
  position: absolute;
  background-color: #fff;
}

HTML 代码

<section class='filler'>
  <p>
    Scroll
  </p>
  <div id='vid-selection'></div>
  <h2 style='margin-top:10px;font-weight:bold;' id='selected-vid'></h2>
</section>

<section id='scrolly-overlay'>
  <div class='scrolly'>
    <figure class='sticky'>
      <video id="v0" playsinline tabindex="0" autobuffer="autobuffer" preload="preload">
        <source id='vid-source'></source>
      </video>
      <div id='progress'>0</div>
    </figure>
    <article>
      <div class='step' data-width='10%' data-index='0'>
        <p>Text to Trigger Scroll</p>
      </div>
    </article>
  </div>
</section>

<section class='filler'>
  <p>
    End
  </p>
</section>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:21:03