GarethOwen
GarethOwen

Reputation: 6133

Can I define a linear gradient in SVG with a normal/bell-shaped blend?

Consider the following svg snippet:

<linearGradient id="redgradient" x1="0%" x2="0%" y1="0%" y2="100%">
    <stop offset="0%" stop-color="#ffffff"/>
    <stop offset="100%" stop-color="#ff0000"/>
</linearGradient>
<rect x="0" y="0" width="400" height="400" fill="url(#redgradient)"/>

Is there a way of specifying that the colours should be blended together using a bell shaped curve? (Similar to the GDI+ LinearGradientBrush::SetBlendBellShape method)

The two rectangles below show the difference - left is without bell blend, right is with bell blend:

alt text

Or is it left to the SVG renderer to decide how the colors should be blended together?

Upvotes: 1

Views: 898

Answers (2)

Michael Mullany
Michael Mullany

Reputation: 31715

gradientTransform cannot do this kind of transformation. You will need a filter to apply a bell shaped transform to a red/white gradient.

enter image description here.

Original on the left, transformed on the right. The curve isn't very fine grained (only 15 values), so you would probably want to use more terms for a large gradient.

  <svg width="500px" height="500px" viewbox="0 0 800 800">
  <defs>
    <filter id="bellTransform" color-interpolation-filters="sRGB">
    <feComponentTransfer>
       <feFuncG type="table" tableValues=
               "0.0000 0.0059 0.0166 0.0346 0.0628 0.1038 0.1586 0.2259 0.3011 0.3761 0.4406 0.4844 0.5000 0.5156 0.5594 0.6239 0.6989 0.7741 0.8414 0.8962 0.9372 0.9654 0.9834 0.9941 1.0000"/>
       <feFuncB type="table" tableValues=
               "0.0000 0.0059 0.0166 0.0346 0.0628 0.1038 0.1586 0.2259 0.3011 0.3761 0.4406 0.4844 0.5000 0.5156 0.5594 0.6239 0.6989 0.7741 0.8414 0.8962 0.9372 0.9654 0.9834 0.9941 1.0000"/>
      </feComponentTransfer>
      </filter>
  </defs>

  <linearGradient id="redgradient" x1="0%" x2="0%" y1="0%" y2="100%">
    <stop offset="0%" stop-color="#ffffff"/>
    <stop offset="100%" stop-color="#ff0000"/>
</linearGradient>
<rect filter="url(#bellTransform)" x="410" y="0" width="400" height="400" fill="url(#redgradient)"/>

<rect x="0" y="0" width="400" height="400" fill="url(#redgradient)"/>

</svg>

Upvotes: 3

robertc
robertc

Reputation: 75717

You can apply a gradientTransform to a linear gradient. I'm not sure how the available transforms map to your required effect.

If that doesn't work you can use the gradient as the input to a filter and perhaps end up with a similar effect. Here's an article which covers combining filters.

Upvotes: 1

Related Questions