Rotating the stroke but not the filling of a svg circle - css

I've followed this tuto in order to implement a progress ring for my Vue application. I still have an extra requirement: fill the circle with an image. That's the point I've reached to, using a pattern (copy pasted from my browser in order to avoid adding the extra complexity of Vue property evaluations):
HTML
<div>
<svg
height="600"
width="600">
<defs>
<pattern id="service" x="0%" y="0%" height="100%" width="100%"
viewBox="0 0 100 100">
<image x="5" y="5" width="90" height="90" href="https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Selfie_icon.svg/2000px-Selfie_icon.svg.png"></image>
</pattern>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#f6921e"/>
<stop offset="100%" stop-color="#f6921e88"/>
</linearGradient>
</defs>
<circle
stroke="url(#gradient)"
stroke-dasharray="1709.0264035528476 1709.0264035528476"
style="stroke-dashoffset: 512.708;"
stroke-linecap="round"
stroke-width="14"
fill="url(#service)"
r="272"
cx="300"
cy="300"
/>
</svg>
</div>
CSS
circle {
transition: stroke-dashoffset 0.35s;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
However, I find that rotating the circle obviously rotates its filling too.
Is there any way to overcome this problem? Why does the example rotate the entire SVG to make the circle gap be in the upside?
Codepen

You can use another circle in your SVG, one for the border and one for the background, then rotate just the circle with the border:
.circle-border {
transition: stroke-dashoffset 0.35s;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
<!-- begin snippet: js hide: false console: true babel: false -->
<div>
<svg height="600" width="600">
<defs>
<pattern id="service" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 100 100">
<image x="5" y="5" width="90" height="90" href="https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Selfie_icon.svg/2000px-Selfie_icon.svg.png"></image>
</pattern>
<linearGradient id="gradient">
<stop offset="0%" stop-color="#f6921e"/>
<stop offset="100%" stop-color="#f6921e88"/>
</linearGradient>
</defs>
<circle
stroke="url(#gradient)"
stroke-dasharray="1709.0264035528476 1709.0264035528476"
style="stroke-dashoffset: 512.708;"
stroke-linecap="round"
stroke-width="14"
fill="transparent"
class="circle-border"
r="272"
cx="300"
cy="300"
/>
<circle
stroke-width="0"
fill="url(#service)"
class="circle-bg"
r="272"
cx="300"
cy="300"
/>
</svg>
</div>

Related

How to make animated, gradient filled, SVG donut chart

I was trying to find clean simple solution to create SVG kind of donut charts with gradient fill going along the edge of the circle with the possibility to animate it from 0% to x% and I found out that there's no easy way and no ready copy & paste solution. Most solution used one linear gradient, which didn't help in my case or were over complicated.
The kind of (static) result I expected to get was:
So after some research and work I created this solution which I decided to share it with you.
It is based on the prozorov's solution. His circle wasn't 360deg and lacked the needed animation part. It isn't true gradient going with the stroke around the edge of the circle (which is not easy to do with SVG) but rather two linear gradients put together, but for most cases that trick does it.
And here's the complete solution:
.animated {
animation: dash 5s infinite;
}
#keyframes dash {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 1570;
}
100% {
stroke-dashoffset: 0;
}
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="800" width="800">
<defs>
<linearGradient id="Gradient1" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#ff0000"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<linearGradient id="Gradient2" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#0000ff"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width="600" height="600" patternUnits="userSpaceOnUse">
<g transform="rotate(0, 300, 300)">
<rect shape-rendering="crispEdges" x="0" y="0" width="300" height="600" fill="url(#Gradient1)"/>
<rect shape-rendering="crispEdges" x="300" y="0" width="300" height="600" fill="url(#Gradient2)"/>
</g>
</pattern>
</defs>
<path id='arc5' class="animated"
style="stroke: url(#Pattern);" fill='transparent'
stroke-dasharray="1570 1570"
stroke-dashoffset="0"
stroke-width='60'
d='M 300 58 A 250 250 0 1 1 299.99 58'/>
</svg
And link to JS Fiddle

Animating feComposite SVG filter elements

I have two svg shapes, one on top of the other, and I've applied the feComposite filter on both so that the top shape knocks out part of the bottom shape. The code is as follows and works fine.
<svg width="100" height="100">
<defs>
<filter id="myfilter">
<feImage xlink:href="#layer1" result="lay1"/>
<feImage xlink:href="#layer2" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2"/>
</filter>
</defs>
<g filter="url(#myfilter)">
<circle id="layer1" cx="50" cy="50" r="40" stroke-
width="0" fill="green" />
<circle id="layer2" class="small" cx="20" cy="60" r="20" stroke-
width="0" fill="red" />
</g>
</svg>
Now I want to animate the top shape, but when I tried to apply the animation, both shapes animates and I can't figure out why because I've only targeted the second shape with class="small". Here is the css code for the animation.
#keyframes rock {
0% {
transform: rotate(45deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(-45deg);
}
}
.small {
animation-name: rock;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
I am puzzled by this behavior and hope someone can shed some light to this problem. Is it not possible to animate the svg elements individually when filters are applied to them as a group? But that doesn't seem to make sense because the svg elements can be targeted individually.
Here is a link to codepen: https://codepen.io/lanlanonearth/pen/bGbRyVo
Please try this: You put both circles in the <defs> and you <use xlink:href="#layer1". Next you apply the filter to the <use> element.
<svg width="100" height="100">
<defs>
<circle id="layer1" cx="50" cy="50" r="40" stroke-width="0" fill="green" />
<circle id="layer2" class="small" cx="20" cy="60" r="20" stroke-width="0" fill="red" />
<filter id="myfilter">
<feImage xlink:href="#layer1" result="lay1"/>
<feImage xlink:href="#layer2" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2"/>
</filter>
</defs>
<use xlink:href="#layer1" filter="url(#myfilter)"></use>
</svg>
Check it on codepen

unwanted horizontal line from svg mask

I'm rendering a line using an SVG mask and gradient, similar to how Github renders sparklines for their "year of activity" charts that are displayed when viewing and organization's list of repositories.
For some reason when the width of the SVG is a certain value, a horizontal line appears at the top of the lines:
The line appears to correspond to the SVG group element that houses a rectangle which is applied a mask and a gradient fill:
However, resizing the SVG to a different width results in the line not displaying:
Here is the markup for an example SVG:
body {
background: #000;
}
<svg width="281" height="50">
<defs>
<linearGradient id="gradient-36" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#f03b20"></stop>
<stop offset="50%" stop-color="#feb24c"></stop>
<stop offset="100%" stop-color="#ffeda0"></stop>
</linearGradient>
<mask id="mask-36" x="0" y="0" width="281" height="46">
<path fill="none" stroke-width="2" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</mask>
</defs>
<g transform="translate(0, 2)">
<rect x="0" y="-2" width="281" height="46" style="stroke: none; fill: url("#gradient-36"); mask: url("#mask-36");">
</rect>
</g>
</svg>
And here is a link to live code showing the bug:
https://bl.ocks.org/clhenrick/ed231b1ba92c87f82529c153e7c77a4e/4954afeeccc9b2d61547e08bb901a8ae23c32c83
Here is a link to an example using the same technique with no bug, just a different size width for the SVG, mask, rect and different sized path:
https://bl.ocks.org/clhenrick/e0b06bbb361780f818993e956dccc5d8/d1fcd24b4df5571ed7069f4a45ed9932a48d74c2
Furthermore, with the buggy example when I move the path element out of the mask and into the group element, the path looks correct:
https://bl.ocks.org/clhenrick/b1ac9490a5708afbcb3ef7f93bb45b3a/5df5bd70333da98d866e7f59e3dd74060ff87474
I'm not sure why this happens at certain SVG widths or SVG path sizes and not at others.
It's not clear to me why github do their sparklines graphs using that complicated arrangement of rects, masks, and transforms. It appears it may be triggering a bug in Chrome.
Have you considered just simplifying the graph? Just use the sparkline path on its own, and apply the gradient directly to it?
body {
background: #000;
}
<svg width="281" height="50">
<defs>
<linearGradient id="gradient-36" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#f03b20"></stop>
<stop offset="50%" stop-color="#feb24c"></stop>
<stop offset="100%" stop-color="#ffeda0"></stop>
</linearGradient>
</defs>
<path fill="none" stroke-width="2" stroke="url(#gradient-36)" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</svg>
Am not sure what is causing the issue but here is a work around to avoid it. The idea is to hide this line by changing the position of the rect (its y value).
So here is the buggy SVG :
body {
background:black;
}
<svg width="281" height="50">
<defs>
<linearGradient id="gradient-36" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#f03b20"></stop>
<stop offset="50%" stop-color="#feb24c"></stop>
<stop offset="100%" stop-color="#ffeda0"></stop>
</linearGradient>
<mask id="mask-36" x="0" y="0" width="281" height="46">
<path fill="none" stroke-width="2" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</mask>
</defs>
<g transform="translate(0, 2)">
<rect x="0" y="-2" width="281" height="46" style="stroke: none; fill: url("#gradient-36"); mask: url("#mask-36");">
</rect>
</g>
</svg>
And if you change the y from -2 to 34 the line will disappear like this :
body {
background:black;
}
<svg width="281" height="50">
<defs>
<linearGradient id="gradient-36" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#f03b20"></stop>
<stop offset="50%" stop-color="#feb24c"></stop>
<stop offset="100%" stop-color="#ffeda0"></stop>
</linearGradient>
<mask id="mask-36" x="0" y="0" width="281" height="46">
<path fill="none" stroke-width="2" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</mask>
</defs>
<g transform="translate(0, 2)">
<rect x="0" y="34" width="281" height="46" style="stroke: none; fill: url("#gradient-36"); mask: url("#mask-36");">
</rect>
</g>
</svg>
This will of course affect the fill you are applying as it's a linear background. So you may change it to adjust the color as you need.
I made more tests trying to point out what can be the cause of the issue. I tried to eliminate some part of the SVG (like the linear-gradien) and to change some values and here is what i got :
body {
background: black;
}
svg {
display: block;
}
<svg width="281" height="50">
<defs>
<mask id="mask-36" x="0" y="0" width="281" height="46">
<path fill="none" stroke-width="2" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</mask>
</defs>
<g transform="translate(0, 2)">
<rect x="0" y="0" width="281" height="46" style="stroke: none; fill:red; mask: url("#mask-36");">
</rect>
</g>
</svg>
<svg width="281" height="50">
<g transform="translate(0, 2)">
<path fill="none" stroke-width="2" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</g>
</svg>
<svg width="281" height="50">
<defs>
<mask id="mask-35" x="0" y="0" width="281" height="46">
<path fill="none" stroke-width="3" stroke="#ffeda0" d="M0,46C2.7238899312070046,46,5.447779862414009,46,8.171669793621014,46C10.811353450072962,46,13.451037106524913,46,16.09072076297686,46C18.814610694183866,46,21.53850062539087,46,24.262390556597875,46C26.98628048780488,46,29.71017041901188,46,32.434060350218886,46C34.89434803001876,46,37.35463570981863,46,39.81492338961851,46C42.53515217844486,46,45.25538096727121,34.5,47.97560975609756,34.5C50.611632270168855,34.5,53.247654784240154,46,55.88367729831145,46C58.60756722951845,46,61.331457160725456,34.5,64.05534709193246,34.5C66.69136960600376,34.5,69.32739212007505,46,71.96341463414635,46C74.68730456535334,46,77.41119449656036,46,80.13508442776735,46C82.85897435897435,46,85.58286429018136,46,88.30675422138836,46C90.94277673545966,46,93.57879924953095,34.5,96.21482176360225,34.5C98.93871169480926,34.5,101.66260162601625,46,104.38649155722327,46C107.02617521367522,46,109.66585887012717,46,112.30554252657912,46C115.02943245778611,46,117.75332238899313,46,120.47721232020012,46C123.20110225140714,46,125.92499218261413,34.5,128.64888211382114,34.5C131.19703721075672,34.5,133.74519230769232,46,136.2933474046279,46C139.01357619345424,46,141.7338049822806,46,144.45403377110694,46C147.09005628517824,46,149.7260787992495,46,152.3621013133208,46C155.08599124452783,46,157.80988117573483,46,160.53377110694186,46C163.16979362101316,46,165.80581613508443,46,168.44183864915573,46C171.16572858036272,46,173.88961851156972,46,176.61350844277672,46C179.33739837398372,46,182.06128830519074,46,184.78517823639774,46C187.42120075046904,46,190.05722326454034,46,192.69324577861164,46C195.41713570981864,46,198.14102564102564,46,200.86491557223263,46C203.50459922868458,46,206.14428288513653,46,208.78396654158848,46C211.50785647279548,46,214.2317464040025,46,216.9556363352095,46C219.6795262664165,46,222.4034161976235,46,225.1273061288305,46C227.58759380863037,46,230.04788148843028,46,232.50816916823015,46C235.2283979570565,46,237.94862674588282,46,240.66885553470917,46C243.30487804878047,46,245.94090056285177,46,248.57692307692307,46C251.30081300813006,46,254.0247029393371,46,256.7485928705441,46C259.38461538461536,46,262.0206378986867,34.5,264.65666041275796,34.5C267.38055034396496,34.5,270.10444027517195,46,272.82833020637895,46C275.55222013758595,46,278.276110068793,46,281,46">
</path>
</mask>
</defs>
<g transform="translate(0, 2)">
<rect x="0" y="0" width="281" height="46" style="stroke: none; fill:red; mask: url("#mask-35");">
</rect>
</g>
</svg>
The first one is the buggy and when i tried to add the path directly into the SVG it works fine (the second one). In the third one i changed the value of stroke in the path to make it 3 and the line disappeared.
I can conclude that it's because you are using the path as a mask. It can be a bug related to some browser and not a bug with your code. In this case you can simply consider using the path directly as an element (and you have a lot of possiblities to color it using gradient) or use my trick in order to hide the bug.

Animating an SVG Group

I currently have the following SVG:
<svg class="tower owner" height="60" width="60" viewBox="0 0 300 300">
<g transform="translate(75 75)" opacity="1">
<ellipse class="border" cx="0" cy="0" fill="#222" rx="65" ry="65" stroke-width="5"></ellipse>
<g class="rotatable" style="transform: rotate(5.497787143782138rad); transition: transform 2s;">
<rect fill="#aaa" height="50" stroke-width="7" stroke="#181818" width="40" x="-20" y="-80"></rect>
<rect fill="#555" height="58" rx="12" ry="10" width="78" x="-39" y="-25"></rect>
<rect fill="#ffe56d" height="46.4" y="-13.399999999999999" rx="12" ry="12" width="78" x="-39"></rect>
</g>
</g>
</svg>
I am currently animating a rotation on g.rotatable however I would like to use <animateTransform> if possible, and I haven't figured out how.
I have tried placing it at the start of the group, at the bottom of it, and even after it, however none have any affect.
<animateTransform attributeName="transform" attributeType="XML" dur="5s" keyTimes="0;0.4;0.75;1" repeatCount="indefinite" type="rotate" values="315deg;90deg;200deg;315deg" calcMode="linear"></animateTransform>
Since I've never really worked with SVGs or animating them, I'm not sure where I'm going wrong.
svg.tower .rotatable {
animation: tower 5s linear infinite;
}
#keyframes tower {
0% {
transform: rotate(315deg);
}
40% {
transform: rotate(90deg);
}
75% {
transform: rotate(200deg);
}
100% {
transform: rotate(315deg);
}
}
Above is my current CSS animation.
Can anyone tell me where I'm going wrong, so I can fix my mistakes, or if it's even possible, so I can potentially give up this line of action.
Note: You may want to reconsider using SMIL animations instead of CSS animations because Chrome has deprecated support for SMIL animations from v45.
There were two problems in your code and they are as follows:
The rotate transform in SVG just takes the degree number as value and doesn't need the deg suffix to be added to it. In addition a transform origin can also be specified (2nd and 3rd param) but it is not mandatory.
There was a style='transform: rotate(...)' on the .rotatable element. The CSS overrides the animateTransform and so you don't get to see any rotation. Avoid this stylesetting. If there is a need for an initial rotation you could probably use SVG's transform attribute.
Below is a working demo:
<svg class="tower owner" height="60" width="60" viewBox="0 0 300 300">
<g transform="translate(75 75)" opacity="1">
<ellipse class="border" cx="0" cy="0" fill="#222" rx="65" ry="65" stroke-width="5"></ellipse>
<g class="rotatable" transform="rotate(315)">
<rect fill="#aaa" height="50" stroke-width="7" stroke="#181818" width="40" x="-20" y="-80"></rect>
<rect fill="#555" height="58" rx="12" ry="10" width="78" x="-39" y="-25"></rect>
<rect fill="#ffe56d" height="46.4" y="-13.399999999999999" rx="12" ry="12" width="78" x="-39"></rect>
<animateTransform attributeName="transform" attributeType="XML" dur="5s" keyTimes="0;0.4;0.75;1" repeatCount="indefinite" type="rotate" values="315;90;200;315" calcMode="linear"></animateTransform>
</g>
</g>
</svg>

CSS 3D isometric simple rotation transform

I am trying to do a small CSS animation with a door like folding animation. I use a SVG as the base, gave it an isometric transform and now I would like the orange square to fold as if it was a 3D space.
I tried to play with perspective, skewing, transform 3D but failed.
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 0% 50%;
perspective: 1500px;
/*transform-style: preserve-3d;*/
}
#keyframes rect5anim {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(-180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>
The problem is because you are using the perspective property and not applying perspective to the transform (transform: perspective(x)). The perspective property does not affect the rendering of an element. It only creates a 3D space that will be used by its children. You can find more information about this in this CSS Tricks Article.
Another thing that might be worth noting is that percentage values for transform-origin don't seem to work well in Firefox. It requires px based values and that too it should be in reference to the SVG's (0,0). So, for #rect5, setting transform-origin: 801px 100px produces the expected output in FF. This CSS Tricks Article has detailed information about this particular problem.
Below is a snippet which uses transform with a perspective in-order to produce the needed effect.
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 801px 100px;
transform-style: preserve-3d;
}
#keyframes rect5anim {
0% {
transform: perspective(1000px) rotateY(0deg);
}
100% {
transform: perspective(1000px) rotateY(180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>

Resources