插值:
插值有很多种实现, 常用的如线性插值; 插值的概念适用于大多数场景
如动画,通过计算出每一帧的形状, 位置, 绘制出逐帧画面
曲线,通过插值, 计算出位置点, 链接样条可以得到近似曲线
一个简易实现
function ease(start, end) { var generate = null, dis = end - start, k = 0; return { step: function(k) { k = typeof generate === 'function' ? generate(k) : k; return k * dis + start }, use: function(fn) { generate = fn return this } } } function linear(t) { return t }; function easeInOut(k) { if ((k *= 2) < 1) { return 0.5 * k * k; } return - 0.5 * (--k * (k - 2) - 1); } var ins0 = ease(10, 100).use(linear); var ins1 = ease(10, 100).use(easeInOut); ins0.step(0.1); // 19 ins0.step(0.2); // 28 ins1.step(0.1); // 11.8 ins1.step(0.2); // 17.2
d3 的插值不仅局限于数值, d3提供了很多插值的便捷方法, 究其原理都是一样的。
interpolateNumber: 数值的线性插值, 如:
interpolateRgb: 对 rgba 四个属性值的线性插值, 如: d3.interpolateRgb('green', 'rgba(100, 20, 10, 0.8)')(0.5); //
interpolateString: 对两个字符串中出现的数值 的线性插值, 如: d3.interpolateString('px23', 'aa46')(0.5); // aa34.5
interpolateArray: 对两个数组中同位的值进行线性插值, 如: d3.interpolateArray([10, 8], [60, 20, 36])(0.5); // [35, 14, 36]
...
关键还是看插值函数。以下摘自 tween.js 中二次插值算法的实现:
Quadratic: {
// 从慢到快
In: function (k) { return k * k; }, // 从快到慢 Out: function (k) { return k * (2 - k); }, // 从慢到快再从快衰减到慢, 并且相对中心点对称 InOut: function (k) { if ((k *= 2) < 1) { return 0.5 * k * k; } return - 0.5 * (--k * (k - 2) - 1); } },
不便上图, 简单对比一下吧
function Qin(k) { return k * k; } function Qout(k) { return k * (2 - k); } function QInOut(k) { if ((k *= 2) < 1) { return 0.5 * k * k; } return - 0.5 * (--k * (k - 2) - 1); } var arr1 = [], arr2 = [], arr3 = []; for (var i = 0; i <=10; i++) { arr1.push(Qin(i / 10).toFixed(2)) arr2.push(Qout(i / 10).toFixed(2)) arr3.push(QInOut(i / 10).toFixed(2)) } console.log('In :::', arr1); // In ::: (11) ["0.00", "0.01", "0.04", "0.09", "0.16", "0.25", "0.36", "0.49", "0.64", "0.81", "1.00"] console.log('Out :::', arr2); // Out ::: (11) ["0.00", "0.19", "0.36", "0.51", "0.64", "0.75", "0.84", "0.91", "0.96", "0.99", "1.00"] console.log('InOut :::', arr3); // InOut ::: (11) ["0.00", "0.02", "0.08", "0.18", "0.32", "0.50", "0.68", "0.82", "0.92", "0.98", "1.00"]
设想一下, 如果把
Quadratic-in 的点连接起来, 会是一条抛物线 内凹
Quadratic-out 的点连接起来,会是一条抛物线 外凸
Quadratic-InOut 的点连接起来, 会是两条抛物线,在中点处平滑连接
这条曲线的高度值变化正好反映运动的状态