I am trying to find out the optimal model for 4-way gradient filling. My latest model is this fiddle:
<svg height="360" width="400" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<clipPath id="C">
<path d="M 100 200 L 300 58 L 400 250 L 300 341 Z" />
</clipPath>
<radialGradient id="G1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(128,128,64); stop-opacity:0" />
</radialGradient>
<radialGradient id="G2" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(0,255,0); stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(128,128,64); stop-opacity:0" />
</radialGradient>
<radialGradient id="G3" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(0,0,255); stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(128,128,64); stop-opacity:0" />
</radialGradient>
<radialGradient id="G4" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,0); stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(128,128,64); stop-opacity:0" />
</radialGradient>
</defs>
<ellipse cx="100" cy="200" rx="200" ry="200" clip-path="url(#C)" fill="url(#G1)" />
<ellipse cx="300" cy="58" rx="200" ry="200" clip-path="url(#C)" fill="url(#G2)" />
<ellipse cx="400" cy="250" rx="200" ry="200" clip-path="url(#C)" fill="url(#G3)" />
<ellipse cx="300" cy="341" rx="200" ry="200" clip-path="url(#C)" fill="url(#G4)" />
</svg>
which comes with result:
But when I change order of <ellipse>
elements (see this fiddle):
<ellipse cx="100" cy="200" rx="200" ry="200" clip-path="url(#C)" fill="url(#G1)" />
<ellipse cx="300" cy="58" rx="200" ry="200" clip-path="url(#C)" fill="url(#G2)" />
<ellipse cx="300" cy="341" rx="200" ry="200" clip-path="url(#C)" fill="url(#G4)" />
<ellipse cx="400" cy="250" rx="200" ry="200" clip-path="url(#C)" fill="url(#G3)" />
result changes to:
Which means transparency is not calculated same way. I would like to have transparency calculated always with same results, regardless of order of the elements. What is a solution for this issue?
At any given point on that surface, the final color is computed by taking into account all the elements that cover that point, in their stacking order. There is always a stacking order in SVG, you can't have all the gradients taken as a whole.
A true 4-way gradient must have at each point a color that mixes in an amount of each color equal to the percentage of the distance from the color source to the shape edge at that specific point. But that can't be obtained with stacked layers, and here's why:
Assuming that you have layers with a uniform transition from color to transparency, and that the layer order is red, green, blue, yellow, with red at the bottom and yellow on top, then a point right in the middle will have roughly
50% yellow + 50% of the color below
which becomes
(50% yellow + 50%(50% blue + 50% of the color below))
->
(50% yellow + 50%(50% blue + 50%(50%green + 50%(50% red +50% background))))
->
(50%yellow + 25%blue + 12.5%green + 6.25%red)
which is far from a 50% of everything mix.
You could try to adjust how abruptly each layer becomes transparent, knowing that the final transparency isn't given by that layer's transparency alone, but also by how opaque the layers above it are. So, if you want to obtain 25% of each layer in the middle, then you'd have to solve the equation:
(y% yellow + (100-y)%(b% blue + (100-b)%(g% green + (100-g)%(r% red))))
=
(25% yellow + 25% blue + 25% green + 25% red)
While this equation is fairly simple to solve (y=25, b=33.3, g=50, r=100), the equation must stand at each point on the surface, and I doubt that you can get a valid answer with simple radial or linear gradients.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With