将gradientTransform应用于linearGradient

Raz*_*con 5 svg

我在 svg 文件中应用所有转换矩阵时遇到问题。如果文件只包含路径,而没有渐变 - 一切正常。但是在对linearGradient 添加和应用gradientTransform 之后会导致渲染错误。

算法:

  1. 将组矩阵和路径矩阵相乘
  2. 用链接的 linearGradient gradientTransform 乘以路径变换
  3. 将变换应用于路径
  4. 将gradientTransform应用于linearGradient

输入文件:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="linearGradient3755">
      <stop offset="0" />
      <stop offset="1" stop-opacity="0" />
    </linearGradient>
    <linearGradient id="linearGradient3761" xlink:href="#linearGradient3755" x1="16.162441" y1="66.128159" x2="117.17769" y2="66.128159" gradientUnits="userSpaceOnUse" />
  </defs>
  <g transform="translate(0,-924.36218)">
    <g transform="matrix(0.95516166,-0.46694301,0.71994792,0.61949768,-706.90347,408.6637)">
      <path d="M 2.1428571,3 L 126.07143,3 L 126.07143,123 L 2.1428571,123 z" transform="translate(0,924.36218)" style="fill:#ff0000;fill-opacity:1;stroke:none" />
      <path d="M 16.162441,21.428905 L 117.17769,21.428905 L 117.17769,110.8274 L 16.162441,110.8274 z" transform="matrix(0.96592583,-0.25881905,0.25881905,0.96592583,-17.36888,938.82017)" style="fill:url(#linearGradient3761);fill-opacity:1;stroke:none" />
    </g>
  </g>
</svg>
Run Code Online (Sandbox Code Playgroud)

输出文件:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="linearGradient3755">
      <stop offset="0" />
      <stop offset="1" stop-opacity="0" />
    </linearGradient>
    <linearGradient id="linearGradient3761" xlink:href="#linearGradient3755" y1="95.70844949469" x1="26.6443734054997" y2="33.95075671356" x2="101.020294143975" gradientUnits="userSpaceOnUse" />
  </defs>
  <path fill="#f00" d="M -37.2023,57.8018 C -37.2023,57.8018 81.1699,-.0654 81.1699,-.0654 81.1699,-.0654 167.5631,74.2746 167.5631,74.2746 167.5631,74.2746 49.1909,132.1418 49.1909,132.1418 z" />
  <path fill="url(#linearGradient3761)" d="M -15.4903,74.3628 C -15.4903,74.3628 58.8856,12.6051 58.8856,12.6051 58.8856,12.6051 143.155,55.2964 143.155,55.2964 143.155,55.2964 68.7791,117.0541 68.7791,117.0541 z" />
</svg>
Run Code Online (Sandbox Code Playgroud)

我的问题是当向量相等时,为什么梯度不同?我该如何解决?

YeH*_*Hao 4

只要您的变换矩阵不扭曲梯度,您的算法就是正确的。

在您的情况下,应用于渐变的最终变换是

translate(0,-924.36218) matrix(0.95516166,-0.46694301,0.71994792,0.61949768,-706.90347,408.6637) matrix(0.96592583,-0.25881905,0.25881905,0.96592583,-17.36888,938.82017)

这与以下相同

matrix(0.7363,-0.6113,0.9426,0.4775,-47.6376,74.0101)

这相当于

translate(-47.6376, 74.0101) rotate(-39.7) scale(0.957, 0.9695) skewX(23.4337)

如果最后一个skew(23.4337)不存在,一切都应该按您的意愿进行。

在不使用属性的情况下实现倾斜效果是相当困难的,或者更准确地说,我应该说是不可能的gradientTransform。根据SVG 1.1 规范

gradientTransform 包含从梯度坐标系到目标坐标系(即 userSpaceOnUse 或 objectBoundingBox)的可选附加变换的定义。这允许诸如倾斜梯度之类的事情。

它是为了实现倾斜效果而设计的。

如果您仍然好奇为什么这是不可能的,我做了一个简单的例子,如下图所示。

解释倾斜效应的示例

在左侧,我们将水平线性渐变应用于正方形。如果我们将 X 轴上的渐变倾斜 20 度,效果将呈现为 2 个形状的组合:

  • 左侧的三角形,其填充为纯色
  • 相同的正方形填充相同的渐变,但正方形本身倾斜 20 度,然后剪裁为其原始形式。

现在你不能简单地用一条线来描述渐变,这就是为什么我们必须使用gradientTransform属性。