参数化 D3 中的 bounceOut 缓动效果
parametrize the bounceOut ease effect in D3
在下图中,黑线描述的是bounceOut函数,如D3-ease documentation所示。有什么办法可以让反弹变小,如红线所示?
没有更改特定缓动方法的本机方法。
但是,如果您查看 source code,您会发现反弹步骤是硬编码的:
var b1 = 4 / 11,
b2 = 6 / 11,
b3 = 8 / 11,
b4 = 3 / 4,
b5 = 9 / 11,
b6 = 10 / 11,
b7 = 15 / 16,
b8 = 21 / 22,
b9 = 63 / 64,
b0 = 1 / b1 / b1;
因此,您可以轻松地使用一组不同的值创建自定义缓动。
为了比较,这里是 D3 缓动:
d3.select("svg")
.append("circle")
.attr("r", 20)
.attr("cx", 20)
.attr("cy", 50)
.transition()
.ease(d3.easeBounceOut)
.duration(2000)
.attr("cx", 280);
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
这里是相同的代码,带有我们的自定义缓动:
d3.select("svg")
.append("circle")
.attr("r", 20)
.attr("cx", 20)
.attr("cy", 50)
.transition()
.ease(customBounce)
.duration(2000)
.attr("cx", 280);
function customBounce(t) {
var b1 = 50 / 64,
b2 = 54 / 64,
b3 = 58 / 64,
b4 = 60 / 64,
b5 = 62 / 64,
b6 = 63 / 64,
b0 = 1 / b1 / b1;
return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : b0 * (t -= b5) * t + b6;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
我没有根据你想要的结果选择最好的数学,这只是一个笼统的解释,所以你可以自己做。
我在 Mike Bostock 在 bl.ocks.org 的 Custom Easing 页面上找到的以下代码正是我想要的,描述了参数化的反弹:
它定义了函数:
function bounce(h) {
if (!arguments.length) h = 0.25;
var b0 = 1 - h,
b1 = b0 * (1 - b0) + b0,
b2 = b0 * (1 - b1) + b1,
x0 = 2 * Math.sqrt(h),
x1 = x0 * Math.sqrt(h),
x2 = x1 * Math.sqrt(h),
t0 = 1 / (1 + x0 + x1 + x2),
t1 = t0 + t0 * x0,
t2 = t1 + t0 * x1,
m0 = t0 + t0 * x0 / 2,
m1 = t1 + t0 * x1 / 2,
m2 = t2 + t0 * x2 / 2,
a = 1 / (t0 * t0);
return function(t) {
return t >= 1 ? 1
: t < t0 ? a * t * t
: t < t1 ? a * (t -= m0) * t + b0
: t < t2 ? a * (t -= m1) * t + b1
: a * (t -= m2) * t + b2;
};
}
然后在转换中将其指定为 ease 参数:
d3element.transition()
.duration(1500)
.ease(bounce(0.2))
...omissis...
在下图中,黑线描述的是bounceOut函数,如D3-ease documentation所示。有什么办法可以让反弹变小,如红线所示?
没有更改特定缓动方法的本机方法。
但是,如果您查看 source code,您会发现反弹步骤是硬编码的:
var b1 = 4 / 11,
b2 = 6 / 11,
b3 = 8 / 11,
b4 = 3 / 4,
b5 = 9 / 11,
b6 = 10 / 11,
b7 = 15 / 16,
b8 = 21 / 22,
b9 = 63 / 64,
b0 = 1 / b1 / b1;
因此,您可以轻松地使用一组不同的值创建自定义缓动。
为了比较,这里是 D3 缓动:
d3.select("svg")
.append("circle")
.attr("r", 20)
.attr("cx", 20)
.attr("cy", 50)
.transition()
.ease(d3.easeBounceOut)
.duration(2000)
.attr("cx", 280);
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
这里是相同的代码,带有我们的自定义缓动:
d3.select("svg")
.append("circle")
.attr("r", 20)
.attr("cx", 20)
.attr("cy", 50)
.transition()
.ease(customBounce)
.duration(2000)
.attr("cx", 280);
function customBounce(t) {
var b1 = 50 / 64,
b2 = 54 / 64,
b3 = 58 / 64,
b4 = 60 / 64,
b5 = 62 / 64,
b6 = 63 / 64,
b0 = 1 / b1 / b1;
return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : b0 * (t -= b5) * t + b6;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
我没有根据你想要的结果选择最好的数学,这只是一个笼统的解释,所以你可以自己做。
我在 Mike Bostock 在 bl.ocks.org 的 Custom Easing 页面上找到的以下代码正是我想要的,描述了参数化的反弹:
它定义了函数:
function bounce(h) {
if (!arguments.length) h = 0.25;
var b0 = 1 - h,
b1 = b0 * (1 - b0) + b0,
b2 = b0 * (1 - b1) + b1,
x0 = 2 * Math.sqrt(h),
x1 = x0 * Math.sqrt(h),
x2 = x1 * Math.sqrt(h),
t0 = 1 / (1 + x0 + x1 + x2),
t1 = t0 + t0 * x0,
t2 = t1 + t0 * x1,
m0 = t0 + t0 * x0 / 2,
m1 = t1 + t0 * x1 / 2,
m2 = t2 + t0 * x2 / 2,
a = 1 / (t0 * t0);
return function(t) {
return t >= 1 ? 1
: t < t0 ? a * t * t
: t < t1 ? a * (t -= m0) * t + b0
: t < t2 ? a * (t -= m1) * t + b1
: a * (t -= m2) * t + b2;
};
}
然后在转换中将其指定为 ease 参数:
d3element.transition()
.duration(1500)
.ease(bounce(0.2))
...omissis...