d3 变换插值详解:d3.interpolateTransformCss 与 d3.interpolateTransformSvg 背后的矩阵分解原理

发布时间:2026/9/7 2:17:27
d3 变换插值详解:d3.interpolateTransformCss 与 d3.interpolateTransformSvg 背后的矩阵分解原理
d3 变换插值详解d3.interpolateTransformCss 与 d3.interpolateTransformSvg 背后的矩阵分解原理【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3在 d3 的过渡系统中transform属性是最常参与动画的属性之一但它也是最容易被错误插值的属性。本篇技术指南围绕 docs/d3-interpolate/transform.md 展开完整覆盖d3.interpolateTransformCss与d3.interpolateTransformSvg两个变换插值器的用法、参数与行为并顺着CSS 矩阵分解标准这一线索深入到为什么不能直接对矩阵 6 个系数做线性插值、d3 是如何把 transform 字符串拆解成 translate / rotate / x-skew / scale 四个分量再逐分量过渡的。读完本篇你将能够正确地为 SVG 元素和 CSS 样式编写变换过渡理解 d3-transition 在attr(transform)与style(transform)上自动选用变换插值器的机制。什么是变换插值d3-interpolate 为颜色、数字、字符串等提供了一系列插值器见 docs/d3-interpolate/value.md 与 docs/d3-interpolate/color.md而变换插值专用于插值 CSS 和 SVG 的 2D 变换。原始文档给出的核心定义是Interpolators for CSS and SVG transforms. The interpolation method is standardized by CSS: see matrix decomposition for animation.即两个变换字符串之间的插值方法遵循 CSS 规范中matrix decomposition for animation矩阵分解用于动画的标准算法。d3 并不发明自己的算法而是把浏览器 CSS 动画处理 2D 变换的同一套数学搬到了 JavaScript 里这保证了手写的 d3 过渡与浏览器原生 transform 过渡在视觉上保持一致。d3 主包src/index.js以export * from d3-interpolate的方式把 d3-interpolate 的全部 API 并入命名空间因此d3.interpolateTransformCss和d3.interpolateTransformSvg与d3.rgb、d3.interpolateRgb一样在引入整包d3后直接可用package.json 中声明的依赖为d3-interpolate: ^3.0.1。两个变换插值器 APId3.interpolateTransformCss(a, b)d3.interpolateTransformCss(translateY(12px) scale(2), translateX(30px) rotate(5deg))(0.5) // translate(15px,6px) scale(1.5,1.5) 前实际输出 translate(15px,6px) rotate(2.5deg) scale(1.5,1.5)以文档原例为准调用与返回值为d3.interpolateTransformCss(translateY(12px) scale(2), translateX(30px) rotate(5deg))(0.5) // translate(15px,6px) rotate(2.5deg) scale(1.5,1.5)语义说明继承自原始文档接收两个 2D CSS 变换字符串a起点与b终点返回一个插值器每个 transform 先被分解为标准表示translate、rotate、x-skew、scale四个分量然后对这四个分量在t ∈ [0, 1]上做线性插值结果是一个新的 2D CSS 变换字符串。以该示例核验一下中间过程起点translateY(12px) scale(2)分解为translate(0, 12) · scale(2, 2)终点translateX(30px) rotate(5deg)分解为translate(30, 0) · rotate(5deg)。t 0.5时平译为(15px, 6px)、旋转角为2.5deg、缩放为1.5——与返回值完全吻合这正是分解后再插值而非矩阵系数插值的直接体现。重要前提绝对单位。从仓库变更历史 CHANGES.md 可以确认两条关键演进Change d3.interpolateTransformCss to require absolute units——CSS 版变换要求长度带绝对单位px等像translateX(30)这种不带单位的 CSS 写法不被接受Change d3.interpolateTransformCss to use DOMMatrix——d3-interpolate v2 起底层改用浏览器原生的DOMMatrix做矩阵运算解析与合成都委托给标准 DOMMatrix API这也是它能可靠处理复合变换写法的基础。d3.interpolateTransformSvg(a, b)d3.interpolateTransformSvg(skewX(-60), skewX(60) translate(280,0)) // translate(140,0) skewX(0)语义与 CSS 版一致返回两个 2D SVG 变换之间的插值器每个 transform 被分解为 translate、rotate、x-skew、scale 四个分量后逐分量插值。与 CSS 版的差异在于输入遵循SVG transform 属性的语法无单位数字、rotate(5)而非rotate(5deg)等。这个例子特别值得展开因为它展示了变换顺序造成的非线性视觉轨迹。终点skewX(60) translate(280,0)中translate 发生在 skew 之后矩阵乘法顺序相当于在倾斜坐标系里平移其等价矩阵为skewX(60) [[1, 0], [tan(60°), 1]]与 T(280,0) 相乘后 ≈ [[1, 280], [1.732, 1]]而起点skewX(-60)的分解结果约为translate(-1.4px, 0) skewX(-60)因为负角度切向分量近似为零矩阵近乎纯 skew。因此t 0.5的中间状态是接近零的 skewX 约 140 的平移最终输出translate(140,0) skewX(0)。若对两条轨迹的原始矩阵系数直接线性取中点得到的中间形状会与文档返回值不同——再次说明分量插值保证了运动语义而不是矩阵数值被插值。核心原理CSS 矩阵分解两个插值器共同的数学基础是 CSS 规范定义的 2D 变换矩阵分解。流程可以概括为解析把 transform 列表字符串解析为一个 2D 仿射矩阵3×3平移、旋转、缩放、错切分解将该唯一矩阵重写为规范化的四步分解形式M translate(tx, ty) · rotate(α) · skewX(φ) · scale(sx, sy)分量插值对(tx, ty)、α、φ、(sx, sy)六个标量分别在t处线性插值合成按同样的四步顺序把分量拼回一个变换字符串输出。这种分解之所以必要是因为 2D 仿射矩阵只有 6 个自由度而平移多少、旋转多少、错切多少、缩放多少这 4 类语义参数也是 6 个自由度。直接对 6 个矩阵系数线性插值时中间帧通常不再是一个干净的纯旋转/缩放组合会出现意料之外的错切与形变而分解-插值-合成保证了中间帧仍是语义正确的标准变换运动轨迹与 CSS 动画的行为一致。从源码结构看这套实现位于 d3-interpolate 子包当前仓库通过 src/index.js 的export * from d3-interpolate聚合其全部导出文档中给出的实现入口为d3-interpolate的src/transform/index.js模块本仓库中不携带该子包源码因此上文的矩阵数值推演属于按 CSS 分解规范的计算核验而行为描述均以 docs/d3-interpolate/transform.md 的原文与示例为准。与 d3-transition 的配合变换插值器的真正舞台在 d3-transition 中。从 CHANGES.md 的 4.0 变更说明可知The d3.interpolateTransform interpolator has been renamed to d3.interpolateTransformSvg, and there is a new d3.interpolateTransformCss to interpolate CSS transforms! This allows d3-transition to automatically interpolate both the SVG transform attribute and the CSS transform style property.也就是说transition.attr(transform, …)—— 目标是 SVG 的transform属性d3-transition 会自动使用interpolateTransformSvgtransition.style(transform, …)—— 目标是 CSS 的transform样式属性则自动使用interpolateTransformCss两者都只支持 2D 变换rotateX/rotateY/rotate3d、perspective等 3D 写法不在支持范围内原文 4.0 说明明确标注 only 2D CSS transforms are supported。典型用法示例属性过渡写法可直接复用// SVG对 transform 属性过渡内部走 interpolateTransformSvg selection.transition() .attr(transform, (d, i) translate(${i * 80},0) rotate(45)); // CSS对 transform 样式过渡内部走 interpolateTransformCss长度必须带绝对单位 selection.transition() .style(transform, translateX(30px) rotate(5deg));也可以绕过 transition 的自动分发手动构造变换插值器作为 tweenselection.transition() .attrTween(transform, function() { return d3.interpolateTransformSvg(skewX(-60), skewX(60) translate(280,0)); });这种手动 tween 变换插值器的组合适合起点不是 DOM 当前值、或者需要精确控制中间轨迹的场景。版本沿革与使用注意结合 CHANGES.md 的变更记录使用这两个 API 时需要注意以下历史约束变更影响d3.interpolateTransform更名为d3.interpolateTransformSvg新增d3.interpolateTransformCss4.0旧代码中的d3.interpolateTransform(...)只应作用于 SVG transform 语法升级后请显式选择 Svg/Css 版本d3.transform方法被移除4.0不能再依赖旧的公开 API 手动解析变换矩阵统一交给两个插值器内部处理interpolateTransformCss改用 DOMMatrix2.x运行环境需支持标准DOMMatrix现代浏览器均支持interpolateTransformCss要求绝对单位CSS 变换中的平移量必须写12px这类带单位形式此外还有两点实践要点只支持 2D两个插值器均面向 2D 变换若元素同时使用 3D CSS 变换请改用浏览器原生过渡或自行处理。分量插值的边界情况分解过程中若矩阵接近奇异例如某轴缩放趋近于 0分解出的角度可能不稳定这在 CSS 规范本身中就是已知特性实践中避免在过渡端点使用scale(0)之类的退化变换即可。小结d3.interpolateTransformCss(a, b)与d3.interpolateTransformSvg(a, b)分别面向 CSS transform 样式与 SVG transform 属性均返回一个t ∈ [0,1]的插值器插值方法遵循 CSS 标准的矩阵分解解析 → 分解为 translate/rotate/x-skew/scale → 分量线性插值 → 合成输出d3-transition 对attr(transform)与style(transform)会自动分派这两个插值器但仅限 2D 变换使用 CSS 版本时保持长度带绝对单位pxSVG 版本则使用无单位语法文档原文位于 docs/d3-interpolate/transform.mdAPI 索引见 docs/api.md 中 interpolate 2D CSS/SVG transforms 两条历史行为变更见 CHANGES.md。【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考