程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了单击 SVG 元素会停止触发关键事件大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决单击 SVG 元素会停止触发关键事件?

开发过程中遇到单击 SVG 元素会停止触发关键事件的问题如何解决?下面主要结合日常开发的经验,给出你关于单击 SVG 元素会停止触发关键事件的解决方法建议,希望对你解决单击 SVG 元素会停止触发关键事件有所启发或帮助;

我正在制作一款游戏,使用 PIXI 制作图形,使用 Mithril 制作一些 UI 元素。我为各种输入创建事件侦听器(WASD 用于移动,鼠标单击用于操作)。我将 SVG 渲染为 UI 的一部分(带有 标记),当我单击该 SVG 时,浏览器中必须有一些“重新聚焦”,因为键输入停止触发事件。特别是,我什至无法使用应该打开/关闭 SVG 的键!

我不能简单地关闭与元素的交互,因为我需要能够将事件侦听器附加到 SVG 中的某些元素。我该如何解决这种“重新聚焦”的行为?奇怪的是,我也无法在单击 svg 时触发 onclick(在将 onclick 函数传递给 元素之后)。

解决方法

您的 SVG 被加载到 元素中,就像在

在一个上下文中发生的事件对另一个上下文是不可见的。这是故意的,您不希望页面上的随机广告能够读取在其嵌入器中输入的所有内容,其他方式也类似。

所以这里的简单解决方案是将您的 SVG 作为内联元素直接附加到主文档中:

onkeydown = (evt) => {
  evt.preventDefault();
  console.log( "pressed",evt.key );
}
Press any key or click on the rect<br>
<svg viewBox="0 0 100 100" width="100">
  <rect fill="green" width="100" height="100"/>
  <script>
    document.querySELEctor("rect")
      .addEventListener("click",(evt) =>
        evt.target.setAttribute("fill","#" + ((Math.random()*0xFFFFF)|0) )
      );
  </script>
</svg>


如果您的 svg 图像和您的文档共享同一来源,您甚至可以从主文档访问 .contentDocument 并在那里附加事件。

document.querySELEctor("object").addEventListener("load",(evt) => {
  const doc = evt.target.contentDocument;
  // add your event here
  doc.addEventListener("keydown",handler);
});

Outsourced example 因为 StackSnippet 的空域 iframe 不能是同源的...


对于跨源文档,更复杂的方法是在两个上下文之间创建一个枢纽,并让另一方知道事件何时发生。

有一个 proposal going which should allow this,然它已经很久没有更新了,它更像是将 Web-Workers 中的 OffscreenCanvas 作为一个用例。但是 last update 的情况可以让希望这种情况也能得到处理。

I wrote an hackish implementation 大致基于最后一个提议,这里是一个使用示例:

const svg_content = `
<svg viewBox="0 0 100 100" width="100" xmlns="http://www.w3.org/2000/svg">
  <rect fill="green" width="100" height="100"/>
  <!-- load the script from both sides
    note that here we load the "cross-origin" version,because StackSnippet's null-origined iframes make this object cross-origin...
  -->
  <script href="https://cdn.jsdelivr.net/gh/Kaiido/EventPort.js@cross-origin/EventPort.js"/>
  <script>
    document.querySELEctor("rect")
      .addEventListener("click","#" + ((Math.random()*0xFFFFF)|0) )
      );
    // "parent" will listen to Events firing on "window"
    const eventPort = window.createEventPort();
    parent.postmessage( eventPort,"*",[eventPort] );
  <\/script>
</svg>
`;

document.querySELEctor("object")
  .data = URl.createObjectURL( new Blob( [ svg_content ],{ type: "image/svg+xml" } ) );

// we wait for the SVG document to send our EventPort object
window.addEventListener("message",(evt) => {
  const eventPort = evt.eventPorts[ 0 ];
  // now we can listen to the events occuring there
  eventPort.addEventListener( "keydown",(evt) => {
    console.log( "pressed in svg document",evt.key );
  });
  eventPort.addEventListener( "click",(evt) => {
    console.log( "clicked in svg document" );
  });
});
addEventListener("keydown",(evt) => {
  console.log( "pressed in main document",evt.key );
})
<!-- load the script from both sides -->
<script src="https://Kaiido.github.io/EventPort.js/EventPort.js"></script>
Press any key or click on the rect<br>
<object></object>

但实际上,我的脚本很黑,我写它只是作为概念证明来帮助更好地设计可能的 API,并且因为它覆盖了很多全局变量,所以它可以很好地破坏页面上的其他内容。
所以如果可以的话,走简单的路:内联你的 svg

大佬总结

以上是大佬教程为你收集整理的单击 SVG 元素会停止触发关键事件全部内容,希望文章能够帮你解决单击 SVG 元素会停止触发关键事件所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:单击