在 d3.js 中更新剪辑路径?
Posted
技术标签:
【中文标题】在 d3.js 中更新剪辑路径?【英文标题】:Updating a clip-path in d3.js? 【发布时间】:2022-01-20 09:35:39 【问题描述】:在我最近的项目中,我有兴趣创建一个随鼠标移动而移动的剪辑路径。我最初的想法是使用鼠标移动坐标选择并重新定位省略号及其属性cx
和cy
,然后选择矩形并重新初始化其clip-path
属性。
但是,这似乎不起作用。到目前为止,我发现的唯一可行的解决方案是删除矩形和剪辑路径,然后在新坐标处重新初始化它们。这适用于下面的简单测试用例,但在我的实际实验中,我将尝试剪辑的对象是外部加载的 svg,并且每次鼠标悬停时都必须重新加载它可能会非常昂贵。
您对如何在不重新初始化所有内容的情况下达到我下面显示的相同效果有什么建议吗?
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/mathjs/lib/browser/math.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
</style>
</head>
<!-- Create a div where the graph will take place -->
<div id="my_datavisualization">
<svg id="click" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="pointer" transform="scale(0.5)">
<circle cx="0" cy="0" r="20" id="dragcircle" />
</g>
</defs>
</svg>
</div>
<body style='overflow:hidden'>
<script>
// Get the viewport height and width
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
// Fit to viewport
var height = vw*0.7;
var width = vw;
// Create the canvas. We will use only part of it for the main plot
var svg = d3.select("#click") // This selects the div
.attr("width", width) // This defines the canvas' width
.attr("height", height) // This defines the canvas' height
// define the clipPath
svg.append("clipPath") // define a clip path
.attr("id", "ellipse-clip") // give the clipPath an ID
.append("ellipse") // shape it as an ellipse
.attr("cx", 175) // position the x-centre
.attr("cy", 100) // position the y-centre
.attr("rx", 100) // set the x radius
.attr("ry", 50); // set the y radius
// draw clipped path on the screen
svg.append("rect") // attach a rectangle
.attr("id","cliprect")
.attr("x", 125) // position the left of the rectangle
.attr("y", 75) // position the top of the rectangle
.attr("clip-path", "url(#ellipse-clip)") // clip the rectangle
.style("fill", "lightgrey") // fill the clipped path with grey
.attr("height", 100) // set the height
.attr("width", 200); // set the width
// Shift the marker around on mouseover; restrict it to the contour
var movex
var movey
svg
.on("mousemove", function ()
// Get the current mouseover coordinates
movex = d3.event.x;
movey = d3.event.y;
// The only way I get this to work right now is by removing the previous clipped shape, then re-adding it
d3.select("#cliprect").remove()
d3.select("#ellipse-clip").remove()
// define the clipPath
svg.append("clipPath") // define a clip path
.attr("id", "ellipse-clip") // give the clipPath an ID
.append("ellipse") // shape it as an ellipse
.attr("cx", movex) // position the x-centre
.attr("cy", movey) // position the y-centre
.attr("rx", 100) // set the x radius
.attr("ry", 50); // set the y radius
// draw clipped path on the screen
svg.append("rect") // attach a rectangle
.attr("id","cliprect")
.attr("x", 125) // position the left of the rectangle
.attr("y", 75) // position the top of the rectangle
.attr("clip-path", "url(#ellipse-clip)") // clip the rectangle
.style("fill", "lightgrey") // fill the clipped path with grey
.attr("height", 100) // set the height
.attr("width", 200); // set the width
);
</script>
</body>
</html>
【问题讨论】:
【参考方案1】:用它代替你的 mousemove 回调
function()
// Get the current mouseover coordinates
movex = d3.event.x;
movey = d3.event.y;
// move the clipPath
d3.select("#ellipse-clip") // selects the clipPath
.select("ellipse") // selects the ellipse
.attr("cx", movex) // position the x-centre
.attr("cy", movey) // position the y-centre
// move clipped path on the screen
svg.select("rect") // attach a rectangle
.attr("x", movex) // position the left of the rectangle
.attr("y", movey) // position the top of the rectangle
【讨论】:
以上是关于在 d3.js 中更新剪辑路径?的主要内容,如果未能解决你的问题,请参考以下文章
D3.js 和 Knockout Force Diagram API 更新