jQuery点击引用模板的SVG group时如何选中特定子元素添加描边
首先明确:你当前的写法取不到元素是正常的,<use> 引用的SVG模板属于Shadow DOM范畴,不会将内部节点暴露到当前文档的DOM树中,所以contents()方法无法获取到内部的<polygon>元素。
该需求完全可实现,推荐以下两种方案:
方案1:CSS变量控制(推荐)
无需修改现有DOM结构,仅需要调整模板样式和点击逻辑即可:
- 给
#interceptor内的第一个<polygon>的描边属性用CSS变量做兜底:
<g id="interceptor"> <ellipse cx="0" cy="15" rx="6" ry="14" fill="url(#gradient)"/> <polygon points="0,-20 7,10 0,0 -7,10" fill="blue" stroke="var(--ship-stroke, none)" stroke-width="var(--ship-stroke-width, 0)"/> <polygon points="0,-20 7,10 0,0" fill="darkblue"/> </g>
- 点击时直接给当前
.ship元素注入CSS变量即可,变量会被内部引用的模板继承,仅作用于当前实例:
$(".ship").click(function() { // 可选:如果需要只保留一个选中状态,先清空其他实例的描边 $(".ship").css({ "--ship-stroke": "none", "--ship-stroke-width": 0 }); // 给当前点击的实例添加描边 $(this).css({ "--ship-stroke": "white", "--ship-stroke-width": 1 }); });
该方案不会增加额外DOM节点,也不会出现组内多元素多余描边的问题,性能最优。
方案2:克隆节点替换use引用(兼容旧浏览器)
如果需要兼容不支持CSS变量的老旧浏览器,可以放弃<use>复用逻辑,改为每次生成ship时直接克隆模板节点:
// 生成ship实例的逻辑替换为克隆 function createShip(shipId, transformAttr) { const tpl = $("#interceptor").clone().removeAttr("id"); return $("<g></g>") .addClass("ship") .attr("id", shipId) .attr("transform", transformAttr) .append(tpl); } // 示例调用,插入到svg根节点 createShip("ship3", "rotate(-180,480,24) translate(480,24)").appendTo("svg");
修改后即可直接操作内部节点,点击逻辑可以按你最初的思路实现:
$(".ship").click(function() { // 可选:清空其他实例的描边 $(".ship").find("polygon").first().attr({stroke: "none", "stroke-width": 0}); // 给当前实例添加描边 $(this).find("polygon").first().attr({stroke: "white", "stroke-width": 1}); });
内容的提问来源于stack exchange,提问作者PaulJK
相关产品推荐
相关产品推荐

