如何在SVG渐变中插值色相?

7
我需要一个带有渐变的svg形状,颜色从hsl(0, 100%, 50%)hsl(360, 100%, 50%)渐变,色相平滑地从0-360变化,就像下面这个图一样:Smooth gradient through hue。当我使用这些停止颜色创建渐变时:
<linearGradient id="Gradient1">
  <stop offset="0%" stop-color="hsl(0, 100%, 50%)"/>
  <stop offset="100%" stop-color="hsl(360, 100%, 50%)"/>
</linearGradient>

...它会产生一个完全红色的渐变效果

我通过添加更多的渐变停止点,成功地解决了这个问题

<linearGradient id="Gradient2">
  <stop offset="0%" stop-color="hsl(0, 100%, 50%)"/>
  <stop offset="1%" stop-color="hsl(3, 100%, 50%)"/>
  <stop offset="2%" stop-color="hsl(7, 100%, 50%)"/>
  <!-- Lots more -->
  <stop offset="98%" stop-color="hsl(352, 100%, 50%)"/>
  <stop offset="99%" stop-color="hsl(356, 100%, 50%)"/>
</linearGradient>

虽然看起来相当丑陋。 有更好的方法吗?
3个回答

5

在SVG中,颜色插值是使用sRGB色彩空间完成的(虽然您应该能够指定linearRGB,但我认为它得到的支持不太好),因此您不能做您想要的事情 - 在这些HSL颜色进行插值之前,它们被转换为sRGB。

(严格来说,在SVG 1.1中不支持HSL颜色 - 因此尽管在Chrome中可以运行,但不要惊讶如果不是所有地方都有效)


5

每60度一个梯度停止点!

由于hsl和rgb的相互作用方式, 在色相上每60度设置梯度停止点会获得最佳效果。在其他位置添加更多的停止点会使结果变差。

在网页浏览器中,使用十六进制、HTML颜色名称、RGB或HSL定义渐变应该都会产生相同的结果,因为最终都会转换为RGB。我不确定HSL SVG在Web浏览器之外的兼容性,为了保险起见,在大多数情况下最好使用RGB或十六进制。

<svg width=100%>
  <rect width=100%           height="1em" fill="url(#hslGradient)"/>
  <rect width=100% y="1.5em" height="1em" fill="url(#nameGradient)"/>
  <rect width=100% y="3em"   height="1em" fill="url(#rgbGradient)"/>
  <rect width=100% y="4.5em" height="1em" fill="url(#hexGradient)"/>
  <defs>
    <linearGradient id="hslGradient">
      <stop offset=0%   stop-color="hsl(  0, 100%, 50%)" />
      <stop offset=16%  stop-color="hsl( 60, 100%, 50%)" />
      <stop offset=33%  stop-color="hsl(120, 100%, 50%)" />
      <stop offset=50%  stop-color="hsl(180, 100%, 50%)" />
      <stop offset=66%  stop-color="hsl(240, 100%, 50%)" />
      <stop offset=83%  stop-color="hsl(300, 100%, 50%)" />
      <stop offset=100% stop-color="hsl(360, 100%, 50%)" />
    </linearGradient>
    <linearGradient id="nameGradient">
      <stop offset=0%   stop-color="red"    />
      <stop offset=16%  stop-color="yellow" />
      <stop offset=33%  stop-color="lime"   />
      <stop offset=50%  stop-color="cyan"   />
      <stop offset=66%  stop-color="blue"   />
      <stop offset=83%  stop-color="magenta"/>
      <stop offset=100% stop-color="red"    />
    </linearGradient>
    <linearGradient id=rgbGradient>
      <stop offset=0%   stop-color="rgb(255,  0,  0)"/>
      <stop offset=16%  stop-color="rgb(255,255,  0)"/>
      <stop offset=33%  stop-color="rgb(  0,255,  0)"/>
      <stop offset=50%  stop-color="rgb(  0,255,255)"/>
      <stop offset=66%  stop-color="rgb(  0,  0,255)"/>
      <stop offset=83%  stop-color="rgb(255,  0,255)"/>
      <stop offset=100% stop-color="rgb(255,  0,  0)"/>
    </linearGradient>
  <linearGradient id=hexGradient>
      <stop offset=0%   stop-color="#f00"/>
      <stop offset=16%  stop-color="#ff0"/>
      <stop offset=33%  stop-color="#0f0"/>
      <stop offset=50%  stop-color="#0ff"/>
      <stop offset=66%  stop-color="#00f"/>
      <stop offset=83%  stop-color="#f0f"/>
      <stop offset=100% stop-color="#f00"/>
    </linearGradient>
  </defs>
</svg>

If we are talking about the web, I would personaly just use a css gradient.

html {
  background: linear-gradient(to right,
    #f00,
    #ff0,
    #0f0,
    #0ff,
    #00f,
    #f0f,
    #f00)
}


4

全色相HSL渐变0-360

将停止颜色设置为10%,我得到了一个接近图像的形状: enter image description here

<svg height="100%" viewBox="0 0 100 20">
  <defs>
    <linearGradient id="Gradient2">
      <stop offset="0%" stop-color="hsl(0, 100%, 50%)" />
      <stop offset="10%" stop-color="hsl(36, 100%, 50%)" />
      <stop offset="20%" stop-color="hsl(72, 100%, 50%)" />
      <stop offset="30%" stop-color="hsl(108, 100%, 50%)" />
      <stop offset="40%" stop-color="hsl(144, 100%, 50%)" />
      <stop offset="50%" stop-color="hsl(180, 100%, 50%)" />
      <stop offset="60%" stop-color="hsl(252, 100%, 50%)" />
      <stop offset="70%" stop-color="hsl(236, 100%, 50%)" />
      <stop offset="80%" stop-color="hsl(288, 100%, 50%)" />
      <stop offset="90%" stop-color="hsl(324, 100%, 50%)" />
      <stop offset="100%" stop-color="hsl(360, 100%, 50%)" />
    </linearGradient>
  </defs>
  <line stroke-width="16" stroke-linecap="round" stroke="url(#Gradient2)" x1="10" y1="10" y2="10.1" x2="90" />
</svg>

如果你想查看1%停止颜色的情况,这里有一个由Harry创建的演示:
Fiddle

与10%的停止进行比较。

如果你认为停止颜色太多了,那么你可以使用JavaScript添加每个停止元素。但我认为手动添加它们通常是更好的方法。


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - benjaminbenben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接