Reputation: 5357
I'm writing a simple webpage that displays a graph and shows dependencies. I found an unexpected behavior in how path
elements are rendered within svg
.
Here's the full HTML of the example:
<html>
<body>
<svg id="svgConnections" xmlns="http://www.w3.org/2000/svg" style="width: 300px; height: 120px">
<defs>
<linearGradient id="grad1" >
<stop offset="0%" style="stop-color:yellow;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:1" />
</linearGradient>
</defs>
<path d="M40,40 L100,100 Z" stroke="url(#grad1)" strokeWidth="1px" />
<path d="M200,100 L140,40 Z" stroke="url(#grad1)" strokeWidth="1px" />
</svg>
</body>
</html>
The same example is on https://jsfiddle.net/4fLjm0e2/
What bugs me is that the first line, which goes from top left to bottom right corner, looks exactly like the second line, which goes "in reverse": from bottom right corner to the top left.
How do I make the path always start with yellow and end with red?
Upvotes: 4
Views: 437
Reputation: 39322
This is not a bug. This is problem in understanding.
The default behavior of a linear gradient is to transition along a horizontal line from the left side of an object to its right side. It doesn't matter if you draw a path from left to right or from right to left. In both cases gradient will appear as from left to right as per default settings.
Consider the demo below:
<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color:yellow;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:1" />
</linearGradient>
</defs>
<g stroke-width="2">
<path d="M10,40 L110,40 Z" stroke="url(#grad1)" />
<path d="M110,70 L10,70 Z" stroke="url(#grad1)" />
</g>
</svg>
If you wants the transition of colors to occur across a vertical line or a line at an angle, you must specify the line's starting point with the x1
and
y1
attributes and its ending points with the x2
and y2
attributes.
Rather than duplicate the stops into each <linearGradient>
element, we'll use the xlink:href
attribute to refer to the original gradient. The stops will be inherited, but the x- and y-coordinates will be overridden by each individual gradient.
<linearGradient id="grad1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad2" xlink:href="#grad1" x1="1" y1="1" x2="0" y2="0"></linearGradient>
Extending the above example:
<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad2" xlink:href="#grad1" x1="120" y1="0" x2="0" y2="0"></linearGradient>
</defs>
<g stroke-width="2">
<path d="M10,40 L110,40" stroke="url(#grad1)" />
<path d="M110,70 L10,70 Z" stroke="url(#grad2)" />
</g>
</svg>
As in your example, you are using diagonal paths so we need to override x1
, y1
, x2
and y2
attribute of both <linearGradient>
elements.
<linearGradient>
element will override the default left to right settings to produce a diagonal gradient from top left to the right bottom.<linearGradient>
element these values will change the direction of gradient i.e from bottom to top.Now we can apply these gradients to the respective paths.
<svg width="300" height="120" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="grad2" xlink:href="#grad1" x1="1" y1="1" x2="0" y2="0"></linearGradient>
</defs>
<g stroke-width="2">
<path d="M40,40 L100,100 Z" stroke="url(#grad1)" />
<path d="M200,100 L140,40 Z" stroke="url(#grad2)" />
</g>
</svg>
Note: This Question can be useful in context with the current problem.
Upvotes: 4