Skip to content

值插值

🌐 Value interpolation

这些是最通用的插值器,适用于大多数值。

🌐 These are the most general interpolators, suitable for most values.

插值(a, b)

🌐 interpolate(a, b)

示例 · 来源 · 返回一个在两个任意值 ab 之间的插值器。

js
d3.interpolate("red", "blue")(0.5) // "rgb(128, 0, 128)"

插值器的实现基于终值 b 的类型,使用以下算法:

🌐 The interpolator implementation is based on the type of the end value b, using the following algorithm:

  1. 如果 b 为 null、undefined 或布尔值,请使用常量 b
  2. 如果 b 是一个数字,使用 interpolateNumber
  3. 如果 b 是一个 颜色 或者可以转换为颜色的字符串,请使用 interpolateRgb
  4. 如果 b 是一个 日期,使用 interpolateDate
  5. 如果 b 是一个字符串,使用 interpolateString
  6. 如果 b 是一个数字的类型化数组,请使用 interpolateNumberArray
  7. 如果 b 是一个通用 数组,请使用 interpolateArray
  8. 如果b可以被强制转换为数字,请使用interpolateNumber
  9. 使用 interpolateObject

根据所选的插值器,a 会被强制转换为相应的适当类型。

🌐 Based on the chosen interpolator, a is coerced to the suitable corresponding type.

插值数字(a, b)

🌐 interpolateNumber(a, b)

示例 · 来源 · 返回两个数字 ab 之间的插值器。

js
d3.interpolateNumber(20, 620)(0.8) // 500

返回的插值器等同于:

🌐 The returned interpolator is equivalent to:

js
function interpolator(t) {
  return a * (1 - t) + b * t;
}

小心

在使用插值器生成字符串时,避免插值到零或从零开始。当非常小的值被转换为字符串时,它们可能会被转换为科学计数法,在旧版浏览器中这是无效的属性或样式属性值。例如,数字 0.0000001 被转换为字符串 "1e-7"。在插值透明度时,这种情况尤其明显。为避免科学计数法,请从或结束过渡值为 1e-6:这是不会以科学计数法字符串化的最小值。

interpolateRound(a, b)

示例 · 来源 · 返回一个在两个数字 ab 之间的插值器。

js
d3.interpolateRound(20, 620)(0.821) // 513

插值器类似于 interpolateNumber,只不过它会将结果值四舍五入到最接近的整数。

🌐 The interpolator is similar to interpolateNumber except it will round the resulting value to the nearest integer.

interpolateString(a, b)

示例 · 来源 · 返回一个在两个字符串 ab 之间的插值器。

js
d3.interpolateString("20px", "32px")(0.5) // "26px"

字符串插值器会在 ab 中找到嵌入的数字,每个数字的形式都为 JavaScript 可理解的形式。在字符串中可以检测到的一些数字示例包括:-1423.141596.0221413e+23

🌐 The string interpolator finds numbers embedded in a and b, where each number is of the form understood by JavaScript. A few examples of numbers that will be detected within a string: -1, 42, 3.14159, and 6.0221413e+23.

对于嵌入在 b 中的每个数字,插值器将尝试在 a 中找到对应的数字。如果找到对应的数字,则使用 interpolateNumber 创建一个数字插值器。字符串 b 的其余部分用作模板:字符串 b 的静态部分在插值过程中保持不变,插入的数字值嵌入到模板中。

🌐 For each number embedded in b, the interpolator will attempt to find a corresponding number in a. If a corresponding number is found, a numeric interpolator is created using interpolateNumber. The remaining parts of the string b are used as a template: the static parts of the string b remain constant for the interpolation, with the interpolated numeric values embedded in the template.

例如,如果 a"300 12px sans-serif"b"500 36px Comic-Sans",则会发现两个嵌入的数字。剩余的静态部分(字符串 b 的)是两个数字之间的空格(" ")和后缀("px Comic-Sans")。在 t = 0.5 时插值器的结果是 "400 24px Comic-Sans"

🌐 For example, if a is "300 12px sans-serif", and b is "500 36px Comic-Sans", two embedded numbers are found. The remaining static parts (of string b) are a space between the two numbers (" "), and the suffix ("px Comic-Sans"). The result of the interpolator at t = 0.5 is "400 24px Comic-Sans".

interpolateDate(a, b)

示例 · 来源 · 返回两个 日期 ab 之间的插值器。

js
d3.interpolateDate(new Date("2014-01-01"), new Date("2024-01-01"))(0.5) // 2019-01-01

小心

返回的日期没有创建防御性副本;每次评估插值器时返回的都是同一个 Date 实例。未进行副本复制是出于性能考虑,因为插值器通常是动画过渡内部循环的一部分。

interpolateArray(a, b)

示例 · 来源 · 返回数组 ab 之间的插值器。

js
d3.interpolateArray([0, 0, 0], [1, 2, 3])(0.5) // [0.5, 1, 1.5]

如果 b 是一个类型化数组(例如,Float64Array),则会调用 interpolateNumberArray

🌐 If b is a typed array (e.g., Float64Array), interpolateNumberArray is called instead.

在内部,会创建一个数组模板,其长度与 b 相同。对于 b 中的每个元素,如果在 a 中存在对应的元素,则使用 interpolate 为这两个元素创建一个通用插值器。如果不存在这样的元素,则模板中使用 b 中的静态值。然后,对于给定的参数 t,对模板中嵌入的插值器进行评估。随后返回更新后的数组模板。

🌐 Internally, an array template is created that is the same length as b. For each element in b, if there exists a corresponding element in a, a generic interpolator is created for the two elements using interpolate. If there is no such element, the static value from b is used in the template. Then, for the given parameter t, the template’s embedded interpolators are evaluated. The updated array template is then returned.

例如,如果 a 是数组 [0, 1]b 是数组 [1, 10, 100],那么插值器在 t = 0.5 时的结果是数组 [0.5, 5.5, 100]

🌐 For example, if a is the array [0, 1] and b is the array [1, 10, 100], then the result of the interpolator for t = 0.5 is the array [0.5, 5.5, 100].

小心

没有创建模板数组的防御性副本;返回的数组修改可能会对插值器的后续评估产生不利影响。出于性能原因,不会创建副本;插值器通常是动画过渡内部循环的一部分。

interpolateNumberArray(a, b)

示例 · 来源 · 返回数组 ab 之间的插值器。

js
d3.interpolateNumberArray([0, 1], Float64Array.of(1, 3))(0.5) // [0.5, 2]

在内部,会创建一个数组模板,其类型和长度与 b 相同。对于 b 中的每个元素,如果在 a 中存在对应的元素,则将值直接插入数组模板中。如果没有这样的元素,则复制 b 中的静态值。然后返回更新后的数组模板。

🌐 Internally, an array template is created that is the same type and length as b. For each element in b, if there exists a corresponding element in a, the values are directly interpolated in the array template. If there is no such element, the static value from b is copied. The updated array template is then returned.

小心

不会对模板数组和参数 ab 制作防御性副本;对这些数组的修改可能会影响后续对插值器的评估。

interpolateObject(a, b)

示例 · 来源 · 返回对象 ab 之间的插值器。

js
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,评估模板中嵌入的插值器,并返回更新后的对象模板。

🌐 Internally, an object template is created that has the same properties as b. For each property in b, if there exists a corresponding property in a, a generic interpolator is created for the two elements using interpolate. If there is no such property, the static value from b is used in the template. Then, for the given parameter t, the template's embedded interpolators are evaluated and the updated object template is then returned.

例如,如果 a 是对象 {x: 0, y: 1}b 是对象 {x: 1, y: 10, z: 100},则插值器在 t = 0.5 时的结果是对象 {x: 0.5, y: 5.5, z: 100}

🌐 For example, if a is the object {x: 0, y: 1} and b is the object {x: 1, y: 10, z: 100}, the result of the interpolator for t = 0.5 is the object {x: 0.5, y: 5.5, z: 100}.

对象插值对于数据空间插值特别有用,在这种情况下插值的是数据而不是属性值。例如,你可以插值一个描述饼图中弧的对象,然后使用 arc 来计算新的 SVG 路径数据。

🌐 Object interpolation is particularly useful for dataspace interpolation, where data is interpolated rather than attribute values. For example, you can interpolate an object which describes an arc in a pie chart, and then use arc to compute the new SVG path data.

小心

没有创建模板对象的防御性副本;返回对象的修改可能会对插值器的后续评估产生不利影响。出于性能原因,不会创建副本;插值器通常是动画过渡内部循环的一部分。

interpolateBasis(values)

示例 · 来源 · 返回一个一致的非有理B样条插值器,通过指定的 values 数组,该数组必须是数字。

js
d3.interpolateBasis([0, 0.1, 0.4, 1])(0.5) // 0.2604166666666667

隐式控制点是生成的,以便插值器在 t = 0 时返回 values[0],在 t = 1 时返回 values[values.length - 1]。另请参见 curveBasisinterpolateRgbBasis

🌐 Implicit control points are generated such that the interpolator returns values[0] at t = 0 and values[values.length - 1] at t = 1. See also curveBasis and interpolateRgbBasis.

interpolateBasisClosed(values)

示例 · 来源 · 返回一个一致的非有理B样条插值器,通过指定的 values 数组,该数组必须是数字。

js
d3.interpolateBasisClosed([0, 0.1, 0.4, 1])(0.5) // 0.45

控制点被隐式重复,使得当在 [0,1] 中绕 t 重复时,得到的一维样条具有循环的 C² 连续性。另请参见 curveBasisClosedinterpolateRgbBasisClosed

🌐 The control points are implicitly repeated such that the resulting one-dimensional spline has cyclical C² continuity when repeated around t in [0,1]. See also curveBasisClosed and interpolateRgbBasisClosed.

interpolateDiscrete(values)

示例 · 来源 · 返回给定 values 数组的离散插值器。

js
d3.interpolateDiscrete(["red", "blue", "green"])(0.5) // "blue"

返回的插值器将 [0, 1 / n) 范围内的 t 映射到 values[0],将 [1 / n, 2 / n) 范围内的 t 映射到 values[1],以此类推,其中 n = values.length。实际上,这是一个具有固定域 [0, 1] 的轻量级 量化比例

🌐 The returned interpolator maps t in [0, 1 / n) to values[0], t in [1 / n, 2 / n) to values[1], and so on, where n = values.length. In effect, this is a lightweight quantize scale with a fixed domain of [0, 1].

quantize(interpolator, n)

示例 · 来源 · 从指定的 插值器 返回 n 个均匀间隔的样本,其中 n 是大于一的整数。

js
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。这在从给定的插值器生成固定数量的样本时非常有用,例如从 连续插值器 推导出 量化比例 的范围。

🌐 The first sample is always at t = 0, and the last sample is always at t = 1. This can be useful in generating a fixed number of samples from a given interpolator, such as to derive the range of a quantize scale from a continuous interpolator.

小心

此方法不适用于不返回其输出防御性副本的插值器,例如 interpolateArrayinterpolateDateinterpolateObject。对于这些插值器,你必须封装插值器并为每个返回的值创建一个副本。

分段(interpolate, values)

🌐 piecewise(interpolate, values)

示例 · 来源 · 返回一个分段插值器,组合每对相邻的插值器。

js
d3.piecewise(d3.interpolateRgb.gamma(2.2), ["red", "green", "blue"])

如果未指定 interpolate,则默认为 interpolate

🌐 If interpolate is not specified, defaults to interpolate.

js
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。实际上,这是一种轻量级的线性比例

🌐 The returned interpolator maps t in [0, 1 / (n - 1)] to interpolate(values[0], values[1]), t in [1 / (n - 1), 2 / (n - 1)] to interpolate(values[1], values[2]), and so on, where n = values.length. In effect, this is a lightweight linear scale.