在背景图片上有svg。 SVG是一个在中间带有圆孔的正方形(例如)。通过圆圈显示背景图像。
我想用鼠标拖动该圆圈。但是如何从javascript访问svg中的defs还不清楚。我可以更改属性,但是onclick事件对它们不起作用。
这是我的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>
答案 0 :(得分:1)
在mousemove
上,重置圆的cx
和cy
属性。我希望这就是你的要求。
//on `mousemove` you reset the `cx` and `cy` attributes of the circle
svg.addEventListener("mousemove",(e)=>{
let m = oMousePosSVG(e)
c.setAttributeNS(null,"cx",m.x)
c.setAttributeNS(null,"cy",m.y)
})
// a function to get the position of the mouse over the svg canvas
function oMousePosSVG(e) {
var p = svg.createSVGPoint();
p.x = e.clientX;
p.y = 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>
您不能将事件附加到蒙版上,但是您可以使用蒙版内的圆圈并将事件附加到使用上,如在下一个示例中一样:
在此示例中,我使用的是mousedown
事件,但是您可以使用mouseover
。
let m,dx,dy;
let dragging = false;
theUse.addEventListener("mousedown",(e)=>{
m = oMousePosSVG(e);
dx = Number(c.getAttribute("cx")) - m.x;
dy = Number(c.getAttribute("cy")) - m.y;
dragging = true;
})
svg.addEventListener("mouseup",(e)=>{
dragging = false;
})
svg.addEventListener("mousemove",(e)=>{
if(dragging){
m = oMousePosSVG(e)
c.setAttributeNS(null,"cx",m.x + dx)
c.setAttributeNS(null,"cy",m.y + dy)
}
})
function oMousePosSVG(e) {
var p = svg.createSVGPoint();
p.x = e.clientX;
p.y = 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>
答案 1 :(得分:1)
我建议在d3.js
的帮助下进行以下变体,但也可以在没有d3的情况下实现这种效果:
这是另一个具有拖动可能性的透明圆圈,并且在拖动时与遮罩圈保持位置同步,请尝试对其进行直播:
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", d.x = d3.event.x)
.attr("cy", d.y = 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 => d.x)
.attr("cy", d => d.y)
.attr('r', d => d.r);
}
<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>