Reputation: 3767
I understand that fill
is applied after transform
, but I don't understand why. I've looked in the spec and cannot find information about why this might be.
I'd like to know if there is a way to have the fill
applied to a group of elements, some using transform: rotate
in a consistent manner. To illustrate the problem see the example code below:
<svg width='38' height='18' viewBox='0 0 38 18' xmlns='http://www.w3.org/2000/svg'>
<defs>
<linearGradient id='gradientFill' x2='0' y2='100%' gradientUnits='userSpaceOnUse'>
<stop stop-color='hsl(0, 0%, 0%)' />
<stop offset='100%' stop-color='hsl(0, 0%, 100%)' />
</linearGradient>
<path id='shape' d='M0,0m9,0c-3.92,0,-7.24,2.51,-8.48,6h3.29c0.83,-1.92,2.8,-3.56,5.19,-3c2.52,0.59,3,3.55,3,6c0,3.6,-0.6,6,-3,6s-3,-2.4,-3,-6h-6c0,4.97,4.03,9,9,9c4.97,0,9,-4.03,9,-9s-4.03,-9,-9,-9z'/>
<g id='test'>
<use xlink:href='#shape'></use>
<use transform='translate(20,0) rotate(180,9,9)' xlink:href='#shape'></use>
</g>
</defs>
<use class='logo' xlink:href='#test' fill="url(#gradientFill)"></use>
</svg>
As you see, on the non-rotated element the gradient runs top to bottom, as expected. However on the rotated element the gradient is also rotated so that it runs from bottom to top. This seems inconsistent to me, as the fill
is applied to a group and not the individual objects.
My ultimate desire is to have the linear gradient flow from top to bottom on both shapes, but I'd like to continue using the use
and transform
method, if possible.
Can someone point me in the right direction in regards to the spec, and also suggest a solution to accomplish my goal?
Upvotes: 1
Views: 1625
Reputation: 31715
You should define your shape as a clip-path and then apply it to a rect that is filled with the gradient you want. You could also do it with a filter, although that's a little more complicated.
Upvotes: 1
Reputation: 123995
That you apply transforms first is stated in the SVG specification for gradients when it talks about gradientUnits...
If gradientUnits="userSpaceOnUse", ‘x1’, ‘y1’, ‘x2’ and ‘y2’ represent values in the coordinate system that results from taking the current user coordinate system in place at the time when the gradient element is referenced (i.e., the user coordinate system for the element referencing the gradient element via a ‘fill’ or ‘stroke’ property) and then applying the transform specified by attribute ‘gradientTransform’.
If you apply a transform to the element it changes the element's co-ordinate system and that therefore affects the gradient too.
Upvotes: 1
Reputation: 101800
Attributes like "fill" are not commands that operate on an object, they are properties that are used by the object when rendering and are inherited by an object's children. Just the same as CSS rules.
To achieve the effect you want, use Michael's solution, or create a second gradient that has it's x,y and x2,y2 flipped to match the 180 degree rotation.
Upvotes: 1