我尝试使用找到here的代码作为项目的起点。此代码使用D3在两个路径之间使用名为pathTween()的函数进行转换,如下所示:
function pathTween(d1, precision) {
return function() {
var path0 = this,
path1 = path0.cloneNode(),
n0 = path0.getTotalLength(),
n1 = (path1.setAttribute("d", d1), path1).getTotalLength();
// Uniform sampling of distance based on specified precision.
var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
while ((i += dt) < 1) distances.push(i);
distances.push(1);
// Compute point-interpolators at each distance.
var points = distances.map(function(t) {
var p0 = path0.getPointAtLength(t * n0),
p1 = path1.getPointAtLength(t * n1);
return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
});
return function(t) {
return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
};
};
}
让我感到困惑的是,在这个例子中,这段代码中的某些东西使转换成为一种轻松的移动,我希望将其更改为线性。我认为它必须是pathTween()中使用的一个函数中的D3默认值,除非我忽略了添加该缓动的pathTween()部分。
任何人都知道可能会有什么违约行为以及如何改变它?
由于
答案 0 :(得分:3)
在D3 v3.x中transition,
默认缓动功能是“立方体输出”。
这cubic-in-out
缓和......
...提供合适的slow-in slow-out动画。
因此,如果你想要线性缓动,你只需要明确地设置它:
path.transition()
.duration(2000)
.ease("linear")//set the ease here
.attrTween("d", pathTween(d1, 4))
.each("end", function() { d3.select(this).call(transition, d1, d0); });
以下是缓解的代码:http://blockbuilder.org/anonymous/d0f28de24658467d48053ef6e39e8413
S.O.中的相同代码片段:
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var d0 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100",
d1 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100c100,0 0,100 100,100";
svg.append("path")
.attr("transform", "translate(180,150)scale(2,2)")
.attr("d", d0)
.call(transition, d0, d1);
function transition(path, d0, d1) {
path.transition()
.duration(2000)
.ease("linear")
.attrTween("d", pathTween(d1, 4))
.each("end", function() { d3.select(this).call(transition, d1, d0); });
}
function pathTween(d1, precision) {
return function() {
var path0 = this,
path1 = path0.cloneNode(),
n0 = path0.getTotalLength(),
n1 = (path1.setAttribute("d", d1), path1).getTotalLength();
// Uniform sampling of distance based on specified precision.
var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
while ((i += dt) < 1) distances.push(i);
distances.push(1);
// Compute point-interpolators at each distance.
var points = distances.map(function(t) {
var p0 = path0.getPointAtLength(t * n0),
p1 = path1.getPointAtLength(t * n1);
return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
});
return function(t) {
return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
};
};
}
path {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
<script src="//d3js.org/d3.v3.min.js"></script>
编辑:你在评论中说你正在使用D3 v4.x.在这种情况下,您会有一些变化:
path.transition()
.duration(2000)
.ease(d3.easeLinear)
.attrTween("d", pathTween(d1, 4))
.on("end", function() { d3.select(this).call(transition, d1, d0); });
它们是:d3.easeLinear
而不是"linear"
和.on
而不是.each
。
以下是blockbuilder:http://blockbuilder.org/GerardoFurtado/90f1d1040bcfd3b4172f3965efab2b37