d3 使用记录: 插值

插值:

  插值有很多种实现, 常用的如线性插值; 插值的概念适用于大多数场景
    如动画,通过计算出每一帧的形状, 位置, 绘制出逐帧画面
       曲线,通过插值, 计算出位置点, 链接样条可以得到近似曲线
 
一个简易实现
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: 数值的线性插值, 如: d3.interpolateNumber(10, 100)(0.5); // 55
interpolateRgb: 对 rgba 四个属性值的线性插值, 如: d3.interpolateRgb('green', 'rgba(100, 20, 10, 0.8)')(0.5); // rgba(50, 74, 5, 0.9)
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 的点连接起来, 会是两条抛物线,在中点处平滑连接
这条曲线的高度值变化正好反映运动的状态
原文地址:https://www.cnblogs.com/liuyingde/p/13786034.html