首页 > 解决方案 > 调度轮事件以模拟可滚动 div 上的滚动

问题描述

所以我有两个 div - div1 和 div2。div2 在 z 顺序上高于 div1。div2 不可滚动,而 div1 可滚动。我正在捕获 div2 元素上的“wheel”事件并将它们发送到 div1。我希望 div1 在调度“wheel”事件后滚动,但没有真正发生。

div2.addEventListener("wheel", ev => {
     var new_event = new ev.constructor(ev.type, ev)
     div1.dispatchEvent(new_event);
});

我不想通过调用 div1.scrollBy(...) 方法手动滚动 div1 。任何帮助,将不胜感激。

标签: javascriptscrollmouseeventmousewheel

解决方案


不知道为什么要这样做,但很遗憾这是不可能的,因为 JavaScript 代码调度的事件是不可信的。

请参阅W3C UI 事件规范中的 3.4 可信事件

由用户代理生成的事件,无论是作为用户交互的结果,还是作为对 DOM 更改的直接结果,都受到用户代理的信任,其权限是通过 DocumentEvent.createEvent 由脚本生成的事件所不具备的("Event") 方法,使用 Event.initEvent() 方法修改,或通过 EventTarget.dispatchEvent() 方法调度。受信任事件的 isTrusted 属性值为 true,而不受信任事件的 isTrusted 属性值为 false。

大多数不受信任的事件不应触发默认操作,但单击事件除外。此事件始终触发默认操作,即使 isTrusted 属性为 false(保留此行为是为了向后兼容)。所有其他不受信任的事件必须表现得好像在该事件上调用了 Event.preventDefault() 方法。

此代码演示了当您取消受信任wheel事件并尝试使用以下命令调度一个事件时会发生什么dispatchEvent

const [container, overlay] = ['container', 'overlay'].map(x => document.getElementsByClassName(x)[0]);

overlay.addEventListener('wheel', e => {
  'use strict'; // Effectively throws an error when trying to assign isTrusted
  console.log(`Is the user event trusted? ${e.isTrusted}`); // true
  e.preventDefault(); // Stops the default behavior
  const newEvent = new e.constructor(e.type, e); // Clone the event
  console.log(`Is the generated event trusted? ${newEvent.isTrusted}`); // false
  try {
    newEvent.isTrusted = true;
  }
  catch (e) {
    console.error(e); // TypeError
  }
  container.dispatchEvent(newEvent);
});

container.addEventListener('wheel', e => {
  console.log(`Wheel event received by the container, is it trusted? ${e.isTrusted} Is it cancelled? ${e.defaultPrevented}`);
  
  // You have to implement the scroll behavior yourself because it won't happen otherwise
});
.container {
  overflow-y: scroll;
  height: 200px;
}

.content {
  height: 600px;
}
 
.overlay {
  position: static;
  width: 100vw;
  height: 100vh;
}
<div class="container">
  <div class="content">
  <div>
</div>

<div class="overlay">
</div>


推荐阅读