以下是一些示例代码及其中的一小部分:
var w = 400;
var h = 400;
var r = 20;
var factor = 5;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")");
svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", r)
.style("fill", "black");
svg.append("circle")
.attr("cx", 150)
.attr("cy", 150)
.attr("r", r)
.style("fill", "red");
svg.selectAll("circle")
.transition()
.duration(2000)
.attr("transform", "scale(" + 1/factor +")")
.attr("r", r*factor);
http://jsfiddle.net/o1wzfas7/2/
在这个例子中,我将两个圆圈缩小了5倍(这也缩放了它们的位置,从而使它们彼此“靠近”)并同时将圆圈的半径按比例缩放了5倍。我们的想法是,它们似乎在不改变尺寸的情况下彼此靠近(就好像我正在改变它们的“cx”和“cy”属性),但由于某种原因,尺度转换和半径转换看起来有不同的速度,所以你看到圆圈变大,然后恢复到初始尺寸。
有没有人知道如何使用比例和半径转换来做这件事,但让两个相互抵消,这样圆圈的大小似乎没有变化?
答案 0 :(得分:1)
首先,解释发生了什么:
问题在于您所做的更改会成倍地抵消,但转换会以相加的方式进行。
因此,对于您的简单示例,其中radius(r)从20开始,比例(隐式)开始为1,并且您将转换因子5,圆的有效半径为r * s :
在过渡开始时:
转型结束时:
现在,你脑海中想到它的方式是因子应该从1过渡到5,但这不会发生什么。默认的过渡函数看不到您的因子,他们只看到半径从20过渡到4,并且比例从1过渡到5.
因此,在转换的中点,每个属性将处于其起始值和结束值的中点(平均值):
为了做你想做的事,你将不得不创建一个自定义补间,直接转换因子,然后从那里计算半径和比例:
svg.selectAll("circle")
.transition()
.duration(2000)
.tween("factor", function(d,i){
/* create an interpolator for your factor */
var f = d3.interpolateNumber(1,factor);
/* store the selected element in a variable for easy modification */
var c = d3.select(this);
/* return the function which will do the updates at each tick */
return function(t) {
var f_t = f(t);
c.attr("transform", "scale(" + 1/f_t + ")" );
c.attr("r", r*f_t );
};
});
请注意,在您的实际应用程序中,您需要在全局变量或每个数据对象中存储因子转换的“开始”值,因为当您转换到不同的缩放因子时它不会自动为1 。
var w = 400;
var h = 400;
var r = 20;
var factor = 5;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")");
svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", r)
.style("fill", "black");
svg.append("circle")
.attr("cx", 150)
.attr("cy", 150)
.attr("r", r)
.style("fill", "red");
svg.selectAll("circle")
.transition()
.duration(2000)
.tween("factor", function(d,i){
/* create an interpolator for your factor */
var f = d3.interpolateNumber(1,factor);
/* store the selected element in a variable for easy modification */
var c = d3.select(this);
/* return the function which will do the updates at each tick */
return function(t) {
var f_t = f(t);
c.attr("transform", "scale(" + 1/f_t + ")" );
c.attr("r", r*f_t );
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>