Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I blend gradients in svg?

Tags:

svg

I would like to fill an SVG shape with two gradients, where one is at a 45 degree angle to the other:

<linearGradient id="wave" x1="0%" x2="100%" y1="0%" y2="0%"
spreadMethod="pad">
    <stop offset="0%"   stop-color="gray" />
    <stop offset="25%"  stop-color="black"/>
    <stop offset="65%"  stop-color="white"/>
    <stop offset="100%" stop-color="gray" />
</linearGradient>
<linearGradient id="red-yellow" x1="0%" x2="100%" y1="0%" y2="100%"
spreadMethod="pad" gradientTransform="rotate(7)">
    <stop offset="0%"   stop-color="gold" />
    <stop offset="30%"  stop-color="gold"/>
    <stop offset="50%"  stop-color="red"/>
    <stop offset="100%" stop-color="red" />
</linearGradient>

Is there a way to blend (multiply) these gradients? The end result should be a rect (or arbitrary shape) that changes from 'gold' on the top left to 'red' on the bottom right, and where the value (as in HSV) changes from medium to low to high to medium from left to right.

like image 231
kai Avatar asked Mar 21 '23 06:03

kai


2 Answers

You can do this with an SVG filter, and do multiply, screen, lighten or darken blending. (Although it will only work completely correctly in Chrome/Safari because they support both object imports into filters with feImage, and correct sizing of feImage imports - if you want this to work in Firefox as well, then use an inline data URI as input for feImage rather than an object reference) Below is an example using multiply blending:

<svg width="600px" height="600px" viewbox="0 0 600 600">
  <defs>
<linearGradient id="wave" x1="0%" x2="100%" y1="0%" y2="0%"
spreadMethod="pad">
    <stop offset="0%"   stop-color="gray" />
    <stop offset="25%"  stop-color="black"/>
    <stop offset="65%"  stop-color="white"/>
    <stop offset="100%" stop-color="gray" />
</linearGradient>
<linearGradient id="red-yellow" x1="0%" x2="100%" y1="0%" y2="100%"
spreadMethod="pad" gradientTransform="rotate(7)">
    <stop offset="0%"   stop-color="gold" />
    <stop offset="30%"  stop-color="gold"/>
    <stop offset="50%"  stop-color="red"/>
    <stop offset="100%" stop-color="red" />
</linearGradient>
     <rect id="wave-rect" x="0" y="0" width="400" height="400" fill="url(#wave)"/>
      <rect id="ry-rect" x="0" y="0" width="400" height="400" fill="url(#red-yellow)"/>
      <filter id="blend-it" x="0%" y="0%" width="100%" height="100%">
        <feImage xlink:href="#wave-rect" result="myWave" x="100" y="100"/>
        <feImage xlink:href="#ry-rect" result="myRY"  x="100" y="100"/>
        <feBlend in="myWave" in2="myRY" mode="multiply" result="blendedGrad"/>
        <feComposite in="blendedGrad" in2="SourceGraphic" operator="in"/>
    </filter>
  </defs>

  <circle filter="url(#blend-it)" cx="300" cy="300" r="200"/>

</svg>

enter image description here

like image 167
Michael Mullany Avatar answered Mar 28 '23 09:03

Michael Mullany


You can place the gray-tints on top, but use transparancy in stead of white. That should merge both.

like image 36
Noctua Avatar answered Mar 28 '23 08:03

Noctua