Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interpolate hue with svg gradient?

I'd like an svg shape with a gradient that runs from hsl(0, 100%, 50%) to hsl(360, 100%, 50%), where the hue runs smoothly from 0 -> 360, to create something like:

Smooth gradient through hue

When I make a gradient with these stop colours:

<linearGradient id="Gradient1">
  <stop offset="0%" stop-color="hsl(0, 100%, 50%)"/>
  <stop offset="100%" stop-color="hsl(360, 100%, 50%)"/>
</linearGradient>

…it results in a fully red gradient

I've managed to hack around it slightly by adding more stops:

<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>

Though is seems pretty ugly.

Is there a better way of doing this?

like image 310
benjaminbenben Avatar asked Dec 12 '15 15:12

benjaminbenben


2 Answers

Color interpolation in SVG is done using the sRGB color space (although you should be able to specify linearRGB but I don't think it's well supported), so you can't do what you want - those HSL colors are converted to sRGB before they're interpolated.

(And technically HSL colors aren't supported in SVG 1.1 - so while this works in Chrome, don't be surprised if it doesn't work everywhere)

like image 193
Michael Mullany Avatar answered Nov 09 '22 03:11

Michael Mullany


Full hsl gradient 0 - 360

By setting the stops colors at 10% i get a shape close to the image: 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>

If you want to see how stops colors at 1% are here is a fiddle created by Harry:
Fiddle

Included with comparison to the 10% stops.

If you think that there are to many stop colors then you could use javascript to add each stop element. But i think that just adding them manually is a better aproach in general.

like image 41
Persijn Avatar answered Nov 09 '22 03:11

Persijn