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

如何实现嵌入Three.JS的iframe与上层div滚动同步

Three.js iframe背景与上层内容滚动同步实现方案

优先采用父页单向传值的同步逻辑,不要做双向滚动事件绑定,从根源上避免事件死循环、滚动卡顿、跨域通信失败问题,完全适配Webflow部署场景,具体步骤如下:

一、基础结构与样式配置

先保证DOM层级和样式符合要求,避免后续同步逻辑出现偏移:

  • 外层设置统一的滚动容器,高度和Three.js动画预设的总滚动长度完全一致(比如做5屏滚动动画就设为500vh)
  • iframe背景层设为sticky定位,始终贴在视口内,z-index低于内容层,禁用自身滚动条、禁止接收鼠标事件,避免抢滚动焦点
  • 上层内容层正常放页面内容,高度由内容自然撑开,和外层容器高度保持一致

基础DOM结构参考:

<!-- 外层滚动容器 -->
<div class="scroll-wrapper">
  <!-- Three.js背景iframe -->
  <iframe 
    id="three-bg" 
    src="你的Three.js页面部署地址" 
    frameborder="0"
    class="three-bg-frame"
  ></iframe>
  <!-- 上层内容承载层,Webflow里的所有页面内容都放在这个div里 -->
  <div class="content-layer"></div>
</div>

对应CSS参考(不会写CSS的话直接在Webflow可视化样式面板配相同属性即可):

.scroll-wrapper {
  position: relative;
  width: 100%;
  /* 按动画需要调整总高度,比如300vh就是3屏滚动长度 */
  min-height: 500vh;
}
.three-bg-frame {
  position: sticky;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1;
  border: none;
  /* 禁止iframe拦截鼠标事件,避免影响上层内容交互 */
  pointer-events: none;
  /* 彻底隐藏iframe自身滚动条 */
  overflow: hidden;
}
.content-layer {
  position: relative;
  z-index: 2;
  width: 100%;
}

二、父页面(Webflow端)滚动传值逻辑

把这段代码粘贴到Webflow后台的「页脚自定义代码」区域即可,作用是监听页面滚动,把实时滚动进度传给iframe:

const iframe = document.getElementById('three-bg');
const wrapper = document.querySelector('.scroll-wrapper');

iframe.addEventListener('load', () => {
  const syncScroll = () => {
    const scrollTop = window.scrollY;
    const wrapperTop = wrapper.offsetTop;
    const scrollableHeight = wrapper.offsetHeight - window.innerHeight;
    // 计算滚动进度:0为滚动到容器顶部,1为滚动到容器底部
    const progress = Math.max(0, Math.min(1, (scrollTop - wrapperTop) / scrollableHeight));
    // 向iframe传值
    iframe.contentWindow.postMessage({
      type: 'scroll-sync',
      progress: progress,
      offset: scrollTop - wrapperTop
    }, '*');
    // 正式上线时把*替换成你托管Three.js页面的域名,安全性更高
  }
  window.addEventListener('scroll', syncScroll, { passive: true });
  window.addEventListener('resize', syncScroll);
  // 初始化时同步一次初始状态
  syncScroll();
});

三、iframe内Three.js页面适配

  1. 先给iframe页面加全局样式,禁用自身滚动:
html, body {
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
  1. 在Three.js逻辑里加消息监听,用父页面传过来的滚动进度驱动动画,不需要再监听iframe自身的滚动事件:
// 全局存当前滚动进度
let scrollProgress = 0;

// 接收父页面的滚动数据
window.addEventListener('message', (e) => {
  // 正式上线可以加来源校验,避免无关消息干扰
  // if (e.origin !== '你的Webflow站点域名') return;
  if (e.data?.type === 'scroll-sync') {
    scrollProgress = e.data.progress;
  }
});

// 原有渲染循环不需要大改,直接读scrollProgress的值更新场景即可
function animate() {
  requestAnimationFrame(animate);
  // 示例:原来用window.scrollY控制的动画参数,全部换成基于scrollProgress计算的值
  // camera.position.y = scrollProgress * 20;
  // mesh.rotation.y = scrollProgress * Math.PI * 2;
  renderer.render(scene, camera);
}
animate();

Webflow部署注意事项

  • 不要尝试双向同步滚动(即监听iframe内滚动再传回父页面),非常容易触发事件死循环导致页面卡顿,单向传值的性能和兼容性最好
  • Safari浏览器下必须给iframe加pointer-events: none,否则会出现滚动到iframe区域时滚轮失效的问题
  • 外层容器的总高度一定要和Three.js动画预设的滚动长度匹配,否则会出现进度计算错位的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:31:01