值插值
这些是最通用的插值器,适用于大多数值。
interpolate(a, b)
示例 · 源代码 · 返回两个任意值 a 和 b 之间的插值器。
d3.interpolate("red", "blue")(0.5) // "rgb(128, 0, 128)"
插值器实现基于结束值 b 的类型,使用以下算法
- 如果 b 为 null、undefined 或布尔值,则使用常量 b。
- 如果 b 为数字,则使用 interpolateNumber.
- 如果 b 为 颜色 或可转换为颜色的字符串,则使用 interpolateRgb.
- 如果 b 为 日期,则使用 interpolateDate.
- 如果 b 为字符串,则使用 interpolateString.
- 如果 b 为 类型化数组 的数字,则使用 interpolateNumberArray.
- 如果 b 为通用的 数组,则使用 interpolateArray.
- 如果 b 可转换为数字,则使用 interpolateNumber.
- 使用 interpolateObject.
基于所选插值器,a 被强制转换为适当的对应类型。
interpolateNumber(a, b)
示例 · 源代码 · 返回两个数字 a 和 b 之间的插值器。
d3.interpolateNumber(20, 620)(0.8) // 500
返回的插值器等效于
function interpolator(t) {
return a * (1 - t) + b * t;
}
注意
当插值器用于生成字符串时,避免插值为或从数字零插值。当非常小的值被转换为字符串时,它们可能会被转换为科学计数法,这在较旧的浏览器中是不合法的属性或样式属性值。例如,数字 0.0000001
被转换为字符串 "1e-7"
。这在插值不透明度时尤其明显。为了避免科学计数法,在过渡开始或结束时使用 1e-6:最小的值,不会以科学计数法被转换为字符串。
interpolateRound(a, b)
示例 · 源代码 · 返回两个数字 a 和 b 之间的插值器。
d3.interpolateRound(20, 620)(0.821) // 513
插值器类似于 interpolateNumber,除了它会将结果值四舍五入到最接近的整数。
interpolateString(a, b)
示例 · 源代码 · 返回两个字符串 a 和 b 之间的插值器。
d3.interpolateString("20px", "32px")(0.5) // "26px"
字符串插值器查找嵌入在 a 和 b 中的数字,其中每个数字都是 JavaScript 理解的形式。一些将被检测到的数字的示例:-1
、42
、3.14159
和 6.0221413e+23
。
对于嵌入在 b 中的每个数字,插值器将尝试在 a 中找到一个对应的数字。如果找到了对应的数字,则使用 interpolateNumber 创建一个数值插值器。字符串 b 的其余部分用作模板:字符串 b 的静态部分在插值过程中保持不变,插值的数值嵌入在模板中。
例如,如果 a 为 "300 12px sans-serif"
,而 b 为 "500 36px Comic-Sans"
,则会找到两个嵌入的数字。其余静态部分(字符串 b 的)是两个数字之间的空格(" "
)和后缀("px Comic-Sans"
)。插值器在 t = 0.5 时结果为 "400 24px Comic-Sans"
。
interpolateDate(a, b)
示例 · 源代码 · 返回两个 日期 a 和 b 之间的插值器。
d3.interpolateDate(new Date("2014-01-01"), new Date("2024-01-01"))(0.5) // 2019-01-01
注意
没有对返回的日期进行防御性复制;对于每次插值器评估,都会返回同一个 Date 实例。为了性能考虑,没有进行复制,因为插值器通常是 动画过渡 内部循环的一部分。
interpolateArray(a, b)
示例 · 源代码 · 返回两个数组 a 和 b 之间的插值器。
d3.interpolateArray([0, 0, 0], [1, 2, 3])(0.5) // [0.5, 1, 1.5]
如果 b 为类型化数组(例如,Float64Array),则会改为调用 interpolateNumberArray.
在内部,会创建一个与 b 长度相同的数组模板。对于 b 中的每个元素,如果在 a 中存在对应的元素,则使用 interpolate 为这两个元素创建一个通用插值器。如果没有这样的元素,则在模板中使用 b 中的静态值。然后,对于给定的参数 t,评估模板的嵌入插值器。然后返回更新后的数组模板。
例如,如果 a 为数组 [0, 1]
,而 b 为数组 [1, 10, 100]
,则插值器在 t = 0.5 时的结果为数组 [0.5, 5.5, 100]
。
注意
没有对模板数组进行防御性复制;对返回数组的修改可能会对插值器的后续评估产生不利影响。为了性能考虑,没有进行复制;插值器通常是 动画过渡 内部循环的一部分。
interpolateNumberArray(a, b)
示例 · 源代码 · 返回两个数字数组 a 和 b 之间的插值器。
d3.interpolateNumberArray([0, 1], Float64Array.of(1, 3))(0.5) // [0.5, 2]
在内部,会创建一个与 b 类型和长度相同的数组模板。对于 b 中的每个元素,如果在 a 中存在对应的元素,则直接在数组模板中对这些值进行插值。如果没有这样的元素,则复制 b 中的静态值。然后返回更新后的数组模板。
注意
没有对模板数组和参数 a 和 b 进行防御性复制;对这些数组的修改可能会影响插值器的后续评估。
interpolateObject(a, b)
示例 · 源代码 · 返回两个对象 a 和 b 之间的插值器。
d3.interpolateObject({x: 0, y: 1}, {x: 1, y: 10, z: 100})(0.5) // {x: 0.5, y: 5.5, z: 100}
在内部,会创建一个与 b 具有相同属性的对象模板。对于 b 中的每个属性,如果在 a 中存在对应的属性,则使用 interpolate 为这两个元素创建一个通用插值器。如果没有这样的属性,则在模板中使用 b 中的静态值。然后,对于给定的参数 t,评估模板的嵌入插值器,然后返回更新后的对象模板。
例如,如果a 是对象 {x: 0, y: 1}
且b 是对象 {x: 1, y: 10, z: 100}
,则插值器在t = 0.5 时返回的对象为 {x: 0.5, y: 5.5, z: 100}
。
对象插值在数据空间插值中特别有用,其中插值的是数据而不是属性值。例如,可以插值描述饼图中圆弧的对象,然后使用 arc 计算新的 SVG 路径数据。
注意
不会创建模板对象的防御性副本;对返回对象的修改可能会对插值器的后续评估产生负面影响。出于性能原因,不会创建副本;插值器通常是 动画过渡 内循环的一部分。
interpolateBasis(values)
示例 · 源代码 · 返回通过指定values 数组的均匀非有理 B 样条插值器,这些values 必须为数字。
d3.interpolateBasis([0, 0.1, 0.4, 1])(0.5) // 0.2604166666666667
隐式控制点是生成的,以便插值器在t = 0 时返回values[0],在t = 1 时返回values[values.length - 1]。另请参见 curveBasis 和 interpolateRgbBasis。
interpolateBasisClosed(values)
示例 · 源代码 · 返回通过指定values 数组的均匀非有理 B 样条插值器,这些values 必须为数字。
d3.interpolateBasisClosed([0, 0.1, 0.4, 1])(0.5) // 0.45
控制点被隐式重复,以便生成的单维样条在t 在 [0,1] 中重复时具有循环 C² 连续性。另请参见 curveBasisClosed 和 interpolateRgbBasisClosed。
interpolateDiscrete(values)
示例 · 源代码 · 返回给定values 数组的离散插值器。
d3.interpolateDiscrete(["red", "blue", "green"])(0.5) // "blue"
返回的插值器将t 在 [0, 1 / n) 中映射到values[0],t 在 [1 / n, 2 / n) 中映射到values[1],依此类推,其中n = values.length。实际上,这是一个轻量级的 quantize 刻度,具有 [0, 1] 的固定域。
quantize(interpolator, n)
示例 · 源代码 · 从指定的interpolator 返回n 个均匀间隔的样本,其中n 是大于一的整数。
d3.quantize(d3.interpolate("red", "blue"), 4) // ["rgb(255, 0, 0)", "rgb(170, 0, 85)", "rgb(85, 0, 170)", "rgb(0, 0, 255)"]
第一个样本始终位于t = 0,最后一个样本始终位于t = 1。这在从给定插值器生成固定数量的样本时很有用,例如从 连续插值器 推导出 quantize 刻度 的范围。
注意
此方法不适用于不返回其输出的防御性副本的插值器,例如 interpolateArray、interpolateDate 和 interpolateObject。对于这些插值器,必须包装插值器并为每个返回值创建一个副本。
piecewise(interpolate, values)
示例 · 源代码 · 返回分段插值器,为每对相邻的values 合成插值器。
d3.piecewise(d3.interpolateRgb.gamma(2.2), ["red", "green", "blue"])
如果未指定interpolate,则默认为 interpolate。
d3.piecewise(["red", "green", "blue"])
返回的插值器将t 在 [0, 1 / (n - 1)] 中映射到interpolate(values[0], values[1]),t 在 [1 / (n - 1), 2 / (n - 1)] 中映射到interpolate(values[1], values[2]),依此类推,其中n = values.length。实际上,这是一个轻量级的 线性刻度。