d3 js中动画线和圆的剪辑路径
Clip path for animated line and circle in d3 js
如何沿路径剪辑动画线和圆?
对于this example,我也尝试过剪圆和点。
我添加了以下代码:
svg.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", 960/2)
.attr("height", 500/2);
并添加了以下定义圆和路径的部分
.attr('clip-path', 'url(#clip)')
路径裁剪工作正常,但圆和线的裁剪工作不同。
如何添加剪辑路径,使其仅在路径的 visible/clipped 部分显示圆和线?
N.B。需要对沿多条路径移动的多个圆和线应用裁剪。
这是因为你在圆上使用了变换:圆的剪辑路径也发生了变换,这意味着它是相对于圆的。随着圆圈的移动,剪辑路径也随之移动。由于圆相对于其变换以 0,0 为中心(变换随着圆的移动而变化,而不是居中属性),剪辑路径将其切割成四分之一圆(因为它也通过 0,0)。
一种解决方案是使用 cx 和 cy 属性来定位圆圈。一个更快的选择是将路径、线、圆和点附加到 g
并剪裁 g,剪裁过程中的所有子项:
var g = svg.append("g")
.attr("clip-path", "url(#clip)")
var path = g.append("path")
.data([points])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
g.selectAll(".point")
.data(points)
.enter()
.append("circle")
.attr("r", 4)
.attr("transform", function(d) { return "translate(" + d + ")"; });
circle = g.append("circle")
.attr("r", 13)
.attr("transform", "translate(" + points[0] + ")");
line = g.append("line")
.attr("y1", -50)
.attr("y2", 50)
.attr("class", "x-hover-line hover-line")
.attr("transform", "translate(" + points[0] + ")");
更新代码:
var points = [
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
svg.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", 960/2)
.attr("height", 500/2);
var g = svg.append("g")
.attr("clip-path", "url(#clip)")
var path = g.append("path")
.data([points])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
g.selectAll(".point")
.data(points)
.enter()
.append("circle")
.attr("r", 4)
.attr("transform", function(d) { return "translate(" + d + ")"; });
circle = g.append("circle")
.attr("r", 13)
.attr("transform", "translate(" + points[0] + ")");
line = g.append("line")
.attr("y1", -50)
.attr("y2", 50)
.attr("class", "x-hover-line hover-line")
.attr("transform", "translate(" + points[0] + ")");
transition();
function transition() {
circle.transition()
.duration(10000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
line.transition()
.duration(10000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
}
// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + p.x + "," + p.y + ")";
};
};
}
path {
fill: none;
stroke: #000;
stroke-width: 3px;
}
circle {
fill: steelblue;
stroke: #fff;
stroke-width: 3px;
}
.hover-line {
/*stroke: #6F257F;*/
stroke: #140917;
stroke-width: 2.5px;
/*stroke-dasharray: 3,3;*/
}
.hover-text {
font-size: 22px;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min.js"></script>
或查看更新后的 fiddle。
如果您不想剪辑其中一个,您可以按原样附加它们(或使用不同的父 g)。看到这个fiddle,线条随处可见
如何沿路径剪辑动画线和圆?
对于this example,我也尝试过剪圆和点。
我添加了以下代码:
svg.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", 960/2)
.attr("height", 500/2);
并添加了以下定义圆和路径的部分
.attr('clip-path', 'url(#clip)')
路径裁剪工作正常,但圆和线的裁剪工作不同。
如何添加剪辑路径,使其仅在路径的 visible/clipped 部分显示圆和线?
N.B。需要对沿多条路径移动的多个圆和线应用裁剪。
这是因为你在圆上使用了变换:圆的剪辑路径也发生了变换,这意味着它是相对于圆的。随着圆圈的移动,剪辑路径也随之移动。由于圆相对于其变换以 0,0 为中心(变换随着圆的移动而变化,而不是居中属性),剪辑路径将其切割成四分之一圆(因为它也通过 0,0)。
一种解决方案是使用 cx 和 cy 属性来定位圆圈。一个更快的选择是将路径、线、圆和点附加到 g
并剪裁 g,剪裁过程中的所有子项:
var g = svg.append("g")
.attr("clip-path", "url(#clip)")
var path = g.append("path")
.data([points])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
g.selectAll(".point")
.data(points)
.enter()
.append("circle")
.attr("r", 4)
.attr("transform", function(d) { return "translate(" + d + ")"; });
circle = g.append("circle")
.attr("r", 13)
.attr("transform", "translate(" + points[0] + ")");
line = g.append("line")
.attr("y1", -50)
.attr("y2", 50)
.attr("class", "x-hover-line hover-line")
.attr("transform", "translate(" + points[0] + ")");
更新代码:
var points = [
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
svg.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", 960/2)
.attr("height", 500/2);
var g = svg.append("g")
.attr("clip-path", "url(#clip)")
var path = g.append("path")
.data([points])
.attr("d", d3.svg.line()
.tension(0) // Catmull–Rom
.interpolate("cardinal-closed"));
g.selectAll(".point")
.data(points)
.enter()
.append("circle")
.attr("r", 4)
.attr("transform", function(d) { return "translate(" + d + ")"; });
circle = g.append("circle")
.attr("r", 13)
.attr("transform", "translate(" + points[0] + ")");
line = g.append("line")
.attr("y1", -50)
.attr("y2", 50)
.attr("class", "x-hover-line hover-line")
.attr("transform", "translate(" + points[0] + ")");
transition();
function transition() {
circle.transition()
.duration(10000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
line.transition()
.duration(10000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
}
// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + p.x + "," + p.y + ")";
};
};
}
path {
fill: none;
stroke: #000;
stroke-width: 3px;
}
circle {
fill: steelblue;
stroke: #fff;
stroke-width: 3px;
}
.hover-line {
/*stroke: #6F257F;*/
stroke: #140917;
stroke-width: 2.5px;
/*stroke-dasharray: 3,3;*/
}
.hover-text {
font-size: 22px;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min.js"></script>
或查看更新后的 fiddle。
如果您不想剪辑其中一个,您可以按原样附加它们(或使用不同的父 g)。看到这个fiddle,线条随处可见