简体   繁体   English

SVG defs(遮罩)上的鼠标事件

[英]Mouse events on SVG defs (mask)

defs中的svg鼠标事件

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您可以重置圆的cxcy属性。 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> 

UPDATE UPDATE

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM