Centering CSS transform:scale on grouped objects [duplicate] - html

I'm having issues with the transform-origin while attempting to scale sub-elements.
While attempting to scale animate a box within a larger svg, it uses the transform origin (0,0) from the overall svg, rather than the center of the element I am trying to scale.
This makes it appear like it is "flying in from the top left" which is not what I am looking for. I am looking to make it scale from the elements center.
How do I get the transform-origin to be set relative to the specific element I am animating, without having to hardcode the (x,y) position of the sub-element itself.
Here is a simple example of the issue I'm dealing
#keyframes scaleBox {
from {transform: scale(0);}
to {transform: scale(1);}
}
#animated-box {
animation: scaleBox 2s infinite;
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="
width: 195px;
"><defs>
<style>.cls-1{fill:#7f7777;}.cls-2{fill:#fff;}</style>
</defs>
<rect class="cls-1" x="0.5" y="0.5" width="99" height="99"></rect>
<path d="M99,1V99H1V1H99m1-1H0V100H100V0Z"></path>
<rect id="animated-box" class="cls-2" x="10.5" y="8.5" width="22" height="6"></rect></svg>

You need transform-box: fill-box;
#keyframes scaleBox {
from {transform: scale(0);}
to {transform: scale(1);}
}
#animated-box {
transform-box: fill-box;
animation: scaleBox 2s infinite;
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="
width: 195px;
"><defs>
<style>.cls-1{fill:#7f7777;}.cls-2{fill:#fff;}</style>
</defs>
<rect class="cls-1" x="0.5" y="0.5" width="99" height="99"></rect>
<path d="M99,1V99H1V1H99m1-1H0V100H100V0Z"></path>
<rect id="animated-box" class="cls-2" x="10.5" y="8.5" width="22" height="6"></rect></svg>

Related

Unable to apply line drawing and filling it animation in svg

I want a line drawing animation and I tried to follow some youtube tutorials and I want something like this https://codepen.io/shshaw/pen/Hjyio which first draw the logo then fills it. Till now I tried this but failed miserably. I searched every other question on stack overflow question everyone tell about only line drawing animation but I want to fill it also.
Also I don't draw any line animation.
Any suggestion of where I am wrong and also adding px unit don't help at all ?
<!DOCTYPE html>
<html>
<head>
<title>SVG</title>
<style>
path {
stroke:#000;
stroke-dasharray: 2500;
stroke-width:3;
animation: my_animation 100s;
}
#keyframes my_animation{
0%{
stroke-dashoffset: 0;
}
50%{
stroke-dashoffset: 2500;
}
100%{
stroke-dashoffset: 0;
}
}
</style>
</head>
<body>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M479 320L639 0L318.99 0L-1 0L158.98 320L318.99 640L479 320Z" id="aLRf203Rm"></path><path d="M301.47 203.41L401.95 0L200.97 0L0 0L100.48 203.41L200.97 406.83L301.47 203.41Z" id="a1ManYbeyy"></path></defs><g><g><use xlink:href="#aLRf203Rm" opacity="1" fill="#ff0043" fill-opacity="1"></use><g><use xlink:href="#aLRf203Rm" opacity="1" fill-opacity="0" stroke="#ff0043" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#a1ManYbeyy" opacity="1" fill="#00ffda" fill-opacity="1"></use><g><use xlink:href="#a1ManYbeyy" opacity="1" fill-opacity="0" stroke="#00ffda" stroke-width="1" stroke-opacity="1"></use></g></g></g></svg>
</body>
</html>
Just use your keyframes. In this example, I have made the stroke animation run from time 0% to 80%. Then I make the fill fade in using fill-opacity from time 80% to 100%.
path {
stroke:#000;
stroke-dasharray: 2072;
stroke-width:3;
animation: my_animation 4s;
animation-fill-mode: forwards;
fill: red;
}
#keyframes my_animation{
0%{
stroke-dashoffset: 2072;
fill-opacity: 0;
}
80%{
stroke-dashoffset: 0;
fill-opacity: 0;
}
100%{
fill-opacity: 1;
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M479 320L639 0L318.99 0L-1 0L158.98 320L318.99 640L479 320Z" id="aLRf203Rm"></path><path d="M301.47 203.41L401.95 0L200.97 0L0 0L100.48 203.41L200.97 406.83L301.47 203.41Z" id="a1ManYbeyy"></path></defs><g><g><use xlink:href="#aLRf203Rm" opacity="1" fill="#ff0043" fill-opacity="1"></use><g><use xlink:href="#aLRf203Rm" opacity="1" fill-opacity="0" stroke="#ff0043" stroke-width="1" stroke-opacity="1"></use></g></g><g><use xlink:href="#a1ManYbeyy" opacity="1" fill="#00ffda" fill-opacity="1"></use><g><use xlink:href="#a1ManYbeyy" opacity="1" fill-opacity="0" stroke="#00ffda" stroke-width="1" stroke-opacity="1"></use></g></g></g></svg>

SVG straight line animation CSS

I am trying to achieve this (the picture below) in using SVG path for animation in a website. I saw this https://css-tricks.com/svg-line-animation-works/ and wanted to try it. But i am not sure how do i create the path out and the animation. Please do help me! Thanks
You can use svg code for animation. You can use CSS animation on svg paths.
.st0{
fill:none;
stroke:#000000;
stroke-miterlimit:10;
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
-webkit-animation: draw1 4s linear forwards;
animation: draw1 4s linear forwards;
}
.st1{
fill:none;
stroke:#000000;
stroke-miterlimit:10;
stroke-dasharray: 200;
stroke-dashoffset: 200;
-webkit-animation: draw2 3s linear 2s forwards;
animation: draw2 3s linear 2s forwards;
}
#-webkit-keyframes draw1{
to {stroke-dashoffset: 0;}
}
#keyframes draw1{
to {stroke-dashoffset: 0;}
}
#-webkit-keyframes draw2{
to {stroke-dashoffset: 0;}
}
#keyframes draw2{
to {stroke-dashoffset: 0;}
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 614 53" style="enable-background:new 0 0 614 53;" xml:space="preserve">
<polyline class="st0" points="0.5,53 0.5,20.7 613.5,20.7 613.5,53 "/>
<line class="st1" x1="307" y1="53" x2="307" y2="0"/>
</svg>
SVG solution
The animation uses the attribute <stroke-dashoffset> - the indent from the beginning of the line. At the maximum value of <stroke-dashoffset> the visible line is zero.
With the value of <stroke-dashoffset ="0"> the line acquires the maximum size.
It is necessary to accurately calculate the length of the line to avoid unpredictable effects in the animation.
In this example, the length of <line> is 53px, for <polyline> is 680px.
<style>
.st0{fill:none;stroke:#000000;stroke-miterlimit:10; stroke-dasharray: 680; stroke-dashoffset: 680;}
.st1{fill:none;stroke:#000000;stroke-miterlimit:10; stroke-dasharray: 53; stroke-dashoffset: 53;}
</style>
<svg version="1.1" viewBox="0 0 614 53" >
<polyline class="st0" points="0.5,53 0.5,20.7 613.5,20.7 613.5,53 " >
<animate
attributeName="stroke-dashoffset"
from="680"
to="0"
dur="2s"
fill="freeze" />
</polyline>
<line class="st1" x1="307" y1="53" x2="307" y2="0">
<animate
attributeName="stroke-dashoffset"
from="53"
to="0"
dur="2s"
fill="freeze" />
</line>
</svg>

CSS animation do not work for svg in <img>

I am trying to animate an SVG in image/object tag but it is not working
svg {
width: 100%;
height: 200px;
}
.rotate-45 {
transform-origin: center;
transform: rotate(45deg);
}
.rotate {
transform-origin: center;
animation: rotate 1s ease-in-out infinite;
}
.rotate-back {
transform-origin: center;
animation: rotate 1s ease-in-out infinite;
animation-direction: alternate;
}
.left {
animation: move 1s ease-in-out infinite;
}
.right {
animation: move 1s ease-in-out infinite;
}
#keyframes rotate {
100% {
transform: rotate(calc(90deg + 45deg));
}
}
#keyframes move {
50% {
transform: translate(-30px, -30px);
}
}
<svg width="100%" height="100%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(500,500)">
<rect class="rotate-45 rotate-back" x="-5" y="-5" width="10" height="10" stroke="#00a99d" stroke-width="20" fill="none" />
<rect class="rotate-45 rotate" x="-50" y="-50" width="100" height="100" stroke="#00a99d" stroke-width="20" stroke-linejoin="bevel" fill="none" />
<g transform="translate(-50,0) rotate(-45)">
<polyline class="left" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none" />
</g>
<g transform="translate(50,0) rotate(135)">
<polyline class="right" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none" />
</g>
<text y="-140" text-anchor="middle" font-weight="bold" font-size="3em" font-family="sans-serif">loading data...</text>
</g>
</svg>
How to animate the SVG inside the image tag along side with CSS
Here is a plunker for that code https://plnkr.co/edit/TdfR7cpVaQArtcUs0Hro?p=preview
You can't animate the internals of an <img> from the outside. Even if it is an SVG. There are two reasons for this:
CSS doesn't apply across document boundaries, and
Images referenced via an <img> must be self contained.
Animations should work if you put the CSS inside the external SVG (in a <style> element as normal).
Note also that you will need to change the way you do transform-origin. The way it works in Chrome is convenient, but it is wrong according to the current spec. It won't work on other browsers like Firefox.
<svg width="100%" height="100%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
.rotate-45 {
transform-origin: 0px 0px;
transform: rotate(45deg);
}
.rotate {
transform-origin: 0px 0px;
animation: rotate 1s ease-in-out infinite;
}
.rotate-back {
transform-origin: 0px 0px;
animation: rotate 1s ease-in-out infinite;
animation-direction: alternate;
}
.left {
animation: move 1s ease-in-out infinite;
}
.right {
animation: move 1s ease-in-out infinite;
}
#keyframes rotate {
100% {
transform: rotate(135deg);
}
}
#keyframes move {
50% {
transform: translate(-30px, -30px);
}
}
</style>
<g transform="translate(500,500)">
<rect class="rotate-45 rotate-back" x="-5" y="-5" width="10" height="10" stroke="#00a99d" stroke-width="20" fill="none"/>
<rect class="rotate-45 rotate" x="-50" y="-50" width="100" height="100" stroke="#00a99d" stroke-width="20" stroke-linejoin="bevel" fill="none"/>
<g transform="translate(-50,0) rotate(-45)"><polyline class="left" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none"/></g>
<g transform="translate(50,0) rotate(135)"><polyline class="right" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none"/></g>
<text y="-140" text-anchor="middle" font-weight="bold" font-size="3em" font-family="sans-serif">loading data...</text>
</g>
</svg>
You can use <?xml-stylesheet href="style.css" type="text/css"?> if you dont want to have to embed it for img tags to work. The above code will work in an object tag
If you want img tags to work do what Kaiido suggested and embed it.
If you're working with pure JavaScript or some other environment that doesn't automatically include SVG's inline in your HTML output (eg like create-react-app does), here's a solution that might come in handy for you:
<img id="logo" src="logo.svg" />
<script>
// load logo inline for animation on hover
const loadLogo = async () => {
// get logo, parse source text, and insert text into doc
document.write(await (await fetch("logo.svg")).text());
// remove fallback img logo
document.querySelector("img#logo").remove();
};
loadLogo();
</script>
All this does is attempt to load an image at a given url/path, then insert its text contents right into the document, in place. Then you can style it from other style sheets, manipulate sub-elements with javascript, have user interaction animations, and etc. If it fails to load for any reason, there is an <img> there as a backup.
This could be written to be more general too, but this was just a quick solution I used once.
Another solution is to just embed the SVG using <object> as explained here, though that could have some limitations depending on what you want to do.

strokes above an SVG for some reason

I have an SVG I made, now it has a couple of blocks that move in a straight line.
sometimes when the blocks move it just adds a stroke above them, although I have stroke disabled.
NOTE: if you look closer you can see the orange strokes above the blocks
here's what it looks like.
#keyframes move {
0% {
transform: translate3d(250px , 0px , 0px);
}
50% {
transform: translate3d(-200px , 0px , 0px);
}
100% {
transform: translate3d(250px , 0px , 0px);
}
}
#loading_bar .cls-2 {
stroke: none;
transition: transform 2s ease-in-out;
animation: move 4s infinite forwards;
}
<svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080">
<defs>
<style>
.cls-1{fill:#64b2c1;}
.cls-2{fill:orange;}
.cls-3{fill:transparent;stroke-miterlimit:10;}
.cls-4{fill:#191919;}
</style>
</defs>
<g id="background">
<rect class="cls-1" width="1920" height="1080"/>
<rect class="cls-2" x="871" y="769" width="90" height="84"/>
</g>
<g id="loading_bar">
<rect class="cls-4" x="545" y="769" width="792" height="84"/>
<rect class="cls-2" x="789" y="789" width="40" height="40"/>
<rect class="cls-2" x="988" y="789" width="40" height="40"/>
<rect class="cls-2" x="888" y="789" width="40" height="40"/></g></svg>

Animating a SVG with CSS transform and transition

I need help in this SVG animation I'm doing.
It features a doughnut chart animating. The maroon-colored part is supposed to rotate and fill up the space, similar to a infographic.
The problem is, the maroon-colored part is only half of the chart and it is hidden under the main chart, which then rotate to 'fill up' the chart but it cannot go any further than 50% of the chart because it then gets hidden again.
You'll understand more when playing with the rotation of the svg.
Any advice/solution to how I can alter my codes/SVG in Illustrator? (I have zero knowledge on XML so I wouldn't know what the XML codes mean.)
<figure>
<path id="right" class="st0" d="M196.8,0l-0.4,55.7c74.6,0.5,134.9,61.1,134.9,135.8c0,75-60.8,135.8-135.8,135.8
c-0.3,0-0.6,0-0.9,0l-0.4,55.7c0.4,0,0.8,0,1.2,0C301.3,383,387,297.3,387,191.5C387,86.2,302,0.7,196.8,0z"/>
<path id="left-bottom" d="M59.7,191.5c0-75,60.8-135.8,135.8-135.8c0.3,0,0.6,0,0.9,0L196.8,0c-0.4,0-0.9,0-1.3,0
C89.8,0,4,85.7,4,191.5C4,296.9,89.1,382.3,194.3,383l0.4-55.7C120.1,326.9,59.7,266.2,59.7,191.5z"/>
<path id="left-top" class="st0" d="M59.7,191.5c0-75,60.8-135.8,135.8-135.8c0.3,0,0.6,0,0.9,0L196.8,0c-0.4,0-0.9,0-1.3,0 C89.8,0,4,85.7,4,191.5C4,296.9,89.1,382.3,194.3,383l0.4-55.7C120.1,326.9,59.7,266.2,59.7,191.5z"/>
</svg>
Tryout: http://codepen.io/anon/pen/QdMrBY
Something like this?
#ring
{
width: 20%;
}
#right
{
}
#left-top
{
}
#left-bottom
{
fill: maroon;
transform: rotate(180deg);
transform-origin: 100% 50%;
transition: 1s;
}
#ring {
animation: spin infinite 10s linear;
}
#keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
<figure>
<svg version="1.1" id="ring" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 390.5 383" style="enable-background:new 0 0 390.5 383;" xml:space="preserve">
<path id="right" class="st0" d="M196.8,0l-0.4,55.7c74.6,0.5,134.9,61.1,134.9,135.8c0,75-60.8,135.8-135.8,135.8
c-0.3,0-0.6,0-0.9,0l-0.4,55.7c0.4,0,0.8,0,1.2,0C301.3,383,387,297.3,387,191.5C387,86.2,302,0.7,196.8,0z"/>
<path id="left-bottom" d="M59.7,191.5c0-75,60.8-135.8,135.8-135.8c0.3,0,0.6,0,0.9,0L196.8,0c-0.4,0-0.9,0-1.3,0
C89.8,0,4,85.7,4,191.5C4,296.9,89.1,382.3,194.3,383l0.4-55.7C120.1,326.9,59.7,266.2,59.7,191.5z"/>
<path id="left-top" class="st0" d="M59.7,191.5c0-75,60.8-135.8,135.8-135.8c0.3,0,0.6,0,0.9,0L196.8,0c-0.4,0-0.9,0-1.3,0 C89.8,0,4,85.7,4,191.5C4,296.9,89.1,382.3,194.3,383l0.4-55.7C120.1,326.9,59.7,266.2,59.7,191.5z"/>
</svg>
</figure>