gpt4 book ai didi

javascript - 将 Javascript 事件添加到 SVG 元素而不是直接添加到子元素上?

转载 作者:行者123 更新时间:2023-12-03 05:15:02 25 4
gpt4 key购买 nike

我知道可以将普通的 Javascript 事件处理程序附加到 SVG 标记内的元素。我希望复制一个对象的很多实例,因此我计划使用 <def><use>标签来简化一些事情。然而,我的每个子项目都需要处理“点击”和其他事件。我可以为每个 child 定义这些事件,但如果我能以某种方式在初始项目中定义它们一次,然后“重用”该单击事件,那就太好了。这可能吗?

https://jsfiddle.net/khyp1o0w/

<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<rect id="someDef" x="0" y="0" width="60" height="30" fill="#f00" />
<!-- ^^ would like to define an event here... -->
</defs>

<use x="150" y="150" xlink:href="#someDef" />
<use x="250" y="250" xlink:href="#someDef" />
<!-- ^^ ... that is used by these guys -->

</svg>

编辑:添加示例 SVG。

最佳答案

use 元素所针对的 IIRC 元素应在内部复制到 <use> 元素中,就像 <use> 是 iframe 一样,并且内容已被克隆。

因此,这意味着附加在原始节点上的事件不会复制到副本上,除非该事件是节点标记的一部分(内联)。但是 chrome 并没有真正遵循这里的规范,甚至无法使其工作......所以这里是 FF 的示例:

// this won't work
document.getElementById('someDef').addEventListener('click', function() {
this.setAttribute('stroke', randomColor());
});
<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<script type="application/javascript">
function randomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[~~(Math.random() * 15)];
}
return color;
}
</script>
<!-- this will work in FF -->
<rect id="someDef" onclick="this.setAttribute('fill',randomColor())" x="0" y="0" width="60" height="30" fill="#f00" />
</defs>

<use x="150" y="150" xlink:href="#someDef" />
<use x="250" y="250" xlink:href="#someDef" />
</svg>

您当然可以通过监听根 svg 元素上的单击事件来使用事件委托(delegate),但这仅适用于直接目标元素,不适用于嵌套元素:

var svg = document.querySelector('svg');
svg.addEventListener('click', function(e) {
var usedTargetID = e.target.getAttributeNS("http://www.w3.org/1999/xlink", 'href');
switch (usedTargetID) {
case '#direct':
clickDirect(e);
break;
case '#nested':
clickNested(e);
break;
default:
return;
}
});

function clickDirect(e) {
// what you seem to want
e.target.setAttribute('fill', randomColor());
}

function clickNested(e) {
// will set both nested...
e.target.setAttribute('fill', randomColor());
}

function randomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[~~(Math.random() * 15)];
}
return color;
}
<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<rect id="direct" x="0" y="0" width="60" height="30" />
<g id="nested">
<!-- you can only access this -->
<!-- not its content individually -->
<rect x="80" y="0" width="60" height="30" />
<rect x="20" y="70" width="60" height="30" />
</g>

</defs>

<use x="150" y="50" xlink:href="#direct" />
<use x="250" y="150" xlink:href="#nested" />
</svg>
或者,您也可以为每个元素添加一个事件,但这将具有与委托(delegate)相同的限制...

关于javascript - 将 Javascript 事件添加到 SVG <def> 元素而不是直接添加到子元素上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41644645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com