[英]Mouse events on SVG defs (mask)
There is svg over background image. 在背景图片上有svg。 SVG is a square with a round hole in the middle (as an example). SVG是一个在中间带有圆孔的正方形(例如)。 A background image appears through the circle. 通过圆圈出现背景图像。
I want to drag this circle by the mouse. 我想用鼠标拖动该圆圈。 But how to get access from javascript to defs inside svg is not clear. 但是如何从javascript访问svg中的defs还不清楚。 I can change properties, but onclick events do not work on them. 我可以更改属性,但是onclick事件对它们不起作用。
Here is my SVG, and I want to access mouse events on element with id = my_mask
: 这是我的SVG,我想访问id = my_mask
元素上的鼠标事件:
<svg>
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="#fff"/>
<g id="my_mask">
<circle r="50" cx="100" cy="100" fill="#000"/>
</g>
</mask>
</defs>
<rect fill="#00f" width="100%" height="100%" mask="url(#hole)" />
</svg>
On mousemove
you reset the cx
and cy
attributes of the circle. 在mousemove
您可以重置圆的cx
和cy
属性。 I hope this is what you were asking. 我希望这就是你的要求。
//on `mousemove` you reset the `cx` and `cy` attributes of the circle svg.addEventListener("mousemove",(e)=>{ let m = oMousePosSVG(e) c.setAttributeNS(null,"cx",mx) c.setAttributeNS(null,"cy",my) }) // a function to get the position of the mouse over the svg canvas function oMousePosSVG(e) { var p = svg.createSVGPoint(); px = e.clientX; py = e.clientY; var ctm = svg.getScreenCTM().inverse(); var p = p.matrixTransform(ctm); return p; }
svg{background:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg); background-size:cover}
<svg id="svg" viewBox="0 0 300 300"> <defs> <mask id="hole"> <rect width="100%" height="100%" fill="#fff"/> <g id="my_mask"> <circle id="c" r="50" cx="100" cy="100" fill="#000"/> </g> </mask> </defs> <rect fill="#00f" width="100%" height="100%" mask="url(#hole)" /> </svg>
You cannot attach an event to a mask however you can use the circle inside the mask and attach an event to the use as I do in the next example: 您不能将事件附加到蒙版上,但是可以使用蒙版内的圆圈并将事件附加到使用上,如我在下一个示例中所做的那样:
In this example I'm using the mousedown
event but you van use mouseover
instead. 在此示例中,我使用mousedown
事件,但您可以使用mouseover
代替。
let m,dx,dy; let dragging = false; theUse.addEventListener("mousedown",(e)=>{ m = oMousePosSVG(e); dx = Number(c.getAttribute("cx")) - mx; dy = Number(c.getAttribute("cy")) - my; dragging = true; }) svg.addEventListener("mouseup",(e)=>{ dragging = false; }) svg.addEventListener("mousemove",(e)=>{ if(dragging){ m = oMousePosSVG(e) c.setAttributeNS(null,"cx",mx + dx) c.setAttributeNS(null,"cy",my + dy) } }) function oMousePosSVG(e) { var p = svg.createSVGPoint(); px = e.clientX; py = e.clientY; var ctm = svg.getScreenCTM().inverse(); var p = p.matrixTransform(ctm); return p; }
svg{background:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg); background-size:cover}
<svg id="svg" viewBox="0 0 300 300"> <defs> <mask id="hole"> <rect width="100%" height="100%" fill="#fff"/> <g id="my_mask"> <circle id="c" r="50" cx="100" cy="100" /> </g> </mask> </defs> <rect fill="#00f" width="100%" height="100%" mask="url(#hole)" /> <use id="theUse" xlink:href="#c" fill="none" pointer-events="all" /> </svg>
I suggest following variant with help of d3.js
but this effect can be achieved without d3 too: 我建议在d3.js
帮助下进行以下变体,但也可以在没有d3的情况下实现此效果:
Here is a another transparent circle with drag possibility and position sync with masking circle when dragging, try it live snippet: 这是另一个具有拖动可能性的透明圆圈,并且在拖动时与遮罩圈保持位置同步,请尝试对其进行实时演示:
let d = [[100,100,50], [300,100,40], [500,100,30]] .map(d=>({x: d[0], y: d[1], r: d[2]})); let mask = circles('mask').call(upd); circles('g').style('fill','transparent') .style('cursor','pointer') .call(upd) .call(d3.drag().on("drag", function (d) { d3.select(this) .attr("cx", dx = d3.event.x) .attr("cy", dy = d3.event.y); mask.call(upd) })); function circles(selector) { return d3.select(selector) .selectAll('circle') .data(d) .enter() .append('circle') } function upd(selection) { selection.attr("cx", d => dx) .attr("cy", d => dy) .attr('r', d => dr); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg viewBox="0 0 600 600" style="background: center url(https://i.imgur.com/cdqfoqZ.png)"> <defs> <mask id="hole"> <rect width="100%" height="100%" fill="#fff"/> </mask> </defs> <rect fill="#00f" width="100%" height="100%" mask="url(#hole)" /> <g></g> </svg>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.