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

应用Matrix3d变换后div无法滚动的技术问题咨询

解决带Matrix3D变换元素的滚动失效问题

问题场景

尝试滚动#content div时无法生效,但拖动滚动条可正常使用。经测试发现该问题与所应用的Matrix3d变换相关,移除变换后滚动功能恢复正常。由于当前页面结构由three.js的CSS3DObject生成,因此不能修改结构,且任意变换参数均会引发该问题。

复现代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    .page {
      position: absolute;
      background-color: red;
      width: 90vw;
      height: 90vh;
      overflow-y: scroll;
    }
    #content {
      width: 100%;
      height: 200vh;
      background-color: green;
    }
    </style>
</head>
<body>
<div style="width: 1440px; height: 820px; perspective: 989.827561px;">
<div style="transform-style: preserve-3d; width: 1440px; height: 820px; transform: translateZ(989.827561px) matrix3d(0.599134, 0.00687, 0.800619, 0, -0.004679, -0.999916, 0.012081, 0, -0.800635, 0.010985, 0.599052, 0, -33.888354, 168.546007, 72.503973, 1) translate(720px, 410px);">
<div class="page track0" style="transform: translate(-50%, -50%) matrix3d(0.032176, 0, -0.042115, 0, 0.000519, -0.052996, 0.000396, 0, 0.042112, 0.000653, 0.032173, 0, -94.514369, 166.635279, -114.904453, 1);"><div id="content"></div></div>
</div>
</div>
</body>
</html>

问题原因

浏览器对应用了复杂3D变换(如matrix3d)的元素会创建独立的合成层,导致鼠标滚轮事件的命中检测出现偏差——滚轮事件被外层变换元素捕获,无法正确传递到内部的滚动容器,只有拖动滚动条能直接触发容器的滚动逻辑。

解决方案

方案1:通过指针事件穿透解决

给内部滚动容器强制开启指针事件接收,同时让外层变换元素不捕获鼠标事件,确保滚轮事件直接落到滚动容器上:

.page {
  position: absolute;
  background-color: red;
  width: 90vw;
  height: 90vh;
  overflow-y: scroll;
  pointer-events: auto; /* 强制滚动容器接收指针事件 */
}

/* 给所有带matrix3d变换的外层容器设置指针事件穿透 */
div[style*="matrix3d"]:not(.page) {
  pointer-events: none;
}

注意:如果外层变换元素本身需要交互(比如点击、拖拽),这个方法会影响其功能,此时建议用方案2。

方案2:事件委托手动转发滚轮事件

在外层变换容器上监听滚轮事件,手动将事件转发给内部滚动容器,既保留外层元素的交互性,又能让滚动容器响应滚轮:

// 获取外层3D变换容器
const transformWrapper = document.querySelector('div[style*="transform-style: preserve-3d"]');
// 获取内部滚动容器
const scrollBox = document.querySelector('.page');

transformWrapper.addEventListener('wheel', (e) => {
  e.stopPropagation();
  // 复制滚轮事件并派发给滚动容器
  scrollBox.dispatchEvent(new WheelEvent('wheel', {
    deltaY: e.deltaY,
    deltaX: e.deltaX,
    deltaMode: e.deltaMode,
    bubbles: true,
    cancelable: true
  }));
}, { passive: true });

这个方法不会影响外层元素的其他交互,适合页面存在多元素交互的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:57:17