【问题标题】:How do I apply a linearGradient to an SVG <use> element that respects gradientUnits="userSpaceOnUse"?如何将 linearGradient 应用于尊重 gradientUnits="userSpaceOnUse" 的 SVG <use> 元素?
【发布时间】:2022-01-06 18:12:56
【问题描述】:

下面是定义的polygon,然后是used,同时应用了相同的linearGradientline

  • polygonused,因为会有很多类似的行。
  • 箭头使用渐变填充的原因是因为它会在绘制线条时沿着line 的路径进行动画处理,因此希望它的填充随着gradientUnits="userSpaceOnUse" 的移动而改变。 (我打算使用this excellent technique的派生。)

line 实际上是一个更复杂的多角度polyline,但这段代码简化了事情。)

This codepen 展示了带有一些变体和注释的视觉结果。

.line {
  fill: none;
  stroke-width: 60px;
  stroke: url(#grad);
}

.head-grad {
  fill: url(#grad);
}
<svg viewBox="0 0 1600 200">
  <defs>
    <polygon id="head" points="0 0, 42 0, 92 50, 42 100, 0 100, 50 50, 0 0"/>
    <linearGradient id="grad" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#901500"/>
      <stop offset="0.9" stop-color="#eb7500"/>
    </linearGradient>
  </defs>
  <line class="line" x1="1540" y1="100" y2="100"/>
  <use href="#head" class="head-grad" x="1490" y="50"/>
</svg>

谁能解释我哪里出错了,或者是否有另一种方法更适合让箭头的填充匹配它在线上的相对位置?

【问题讨论】:

    标签: animation svg linear-gradients


    【解决方案1】:

    在这个例子中,我将直线和箭头组合在一个蒙版中。两个元素都是白色的,所以 100% 透明。蒙版用于具有渐变的&lt;rect&gt;。我不知道这是否适用于您的情况?简单的线可以替换为任何其他形状,例如您所说的折线。

    动画可以应用于蒙版。在the excellent technique 中,我可以看到线和箭头之间有一个抓取。戴上口罩就可以避免这种情况。

    <svg viewBox="0 0 1600 200">
      <defs>
        <polygon id="head" points="0 0, 42 0, 92 50, 42 100, 0 100, 50 50, 0 0"/>
        <linearGradient id="grad" gradientUnits="userSpaceOnUse">
          <stop offset="0" stop-color="#901500"/>
          <stop offset="0.9" stop-color="#eb7500"/>
        </linearGradient>
        <mask id="m1">
          <line x1="1540" y1="100" y2="100" stroke="white" stroke-width="60"/>
          <use href="#head" x="1490" y="50" fill="white"/>
        </mask>
      </defs>
      <rect width="1600" height="200" mask="url(#m1)" fill="url(#grad)"/>
    </svg>

    更新

    在下一个示例中,我使用上述蒙版并为其设置动画。将箭头的运动路径与路径上的 stroke-dasharray 动画相结合。

    <svg viewBox="0 0 180 180" height="500" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <linearGradient id="grad" gradientUnits="userSpaceOnUse">
          <stop offset="0" stop-color="#901500" />
          <stop offset="0.9" stop-color="#eb7500" />
        </linearGradient>
        <path id="curve" d="M 20 130 L 40 80 L 60 90 L 80 60 L 100 80 L 120 30 L 140 40 L 160 10" fill="none" pathLength="100" />
        <mask id="m1">
          <use href="#curve" stroke-dasharray="0 0" stroke="white" stroke-width="3">
            <animate attributeName="stroke-dasharray" values="0 100;100 100" dur="6s" fill="freeze" />
          </use>
          <path d="M -3 -3 L -0.5 -3 L 3 0 L -0.5 3 L -3 3 L 0 0 Z" fill="white">
            <animateMotion dur="6s" fill="freeze" rotate="auto">
              <mpath href="#curve" />
            </animateMotion>
          </path>
        </mask>
      </defs>
      <rect width="100%" height="100%" fill="url(#grad)" mask="url(#m1)" />
    </svg>

    【讨论】:

    • 这很聪明。我在设计中有几个重叠的箭头,这可能是一个问题,但我肯定会试一试。非常感谢。
    • 我喜欢遮罩技术,可能还需要它,但我有一种预感,an approach suggested on Twitter that I've replied to 会更适合我的多个叠加箭头。将在适当的时候在这里确认。
    • @JonathanSchofield 我添加了第二个示例。也许这越来越接近您正在搜索的内容?
    • 感谢@chrwahl 提供的技术。我在 Twitter works for me 上找到了 gradientTransform 的建议。
    【解决方案2】:

    @chrwahl 提供了一些答案,但随着我的箭头随着 translate(x,y) 的路径发生变化,我最终将 gradientTransform="translate(-x,0)" 部署在专用于每个箭头的 linearGradient 上。

    结果是shown in this codepen

    代码摘录,不附带 JS,来自那支笔:

    .rarr__line {
      fill: none;
      stroke-width: 60px;
    }
    
    .rarr-bg {
      fill: #901600;
    }
    
    .rarr-3 .rarr__line {
      stroke: url(#rgrad-3l);
    }
        
    .rarr-3 .rarr__head {
      fill: url(#rgrad-3h);
    }
    <svg viewBox="0 0 1600 900">
      <defs>
        <symbol id="rarr" viewbox="0 0 92 100">
          <polygon points="0 0, 42 0, 92 50, 42 100, 0 100, 50 50, 0 0" />
        </symbol>
    
        <linearGradient id="rgrad-3l" y1="380" x2="1540" y2="380" gradientUnits="userSpaceOnUse">
          <stop offset="0" stop-color="#901500"/>
          <stop offset="1" stop-color="#eb7500"/>
        </linearGradient>
    
        <linearGradient id="rgrad-3h" y1="380" x2="1540" y2="380" gradientUnits="userSpaceOnUse" gradientTransform="translate(-1490,0)">
          <stop offset="0" stop-color="#901500"/>
          <stop offset="1" stop-color="#eb7500"/>
        </linearGradient>
      </defs>
    
      <rect class="rarr-bg" width="1600" height="900"/>
    
      <g class="rarr-3 major">
        <polyline class="rarr__line" points="0 430, 1000 430, 1100 330, 1540 330" />
        <use href="#rarr" viewbox="0 0 92 100" width="92" height="100" class="rarr__head" x="1490" y="280" data-grad="rgrad-3h" />
      </g>
    </svg>

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 2020-11-08
      • 1970-01-01
      • 2018-05-23
      • 1970-01-01
      • 1970-01-01
      • 2019-11-27
      • 2013-07-02
      • 2012-11-20
      相关资源
      最近更新 更多