How to create an responsive animated SVG donut with CSS? - javascript

How to create an cross browser (Mozilla, Chrome, Safari), animated SVG donut?
Currently I got this: https://jsfiddle.net/odnmhvm6/1/
This seems to be fine and exactly what I want (macOS, Chrome) but some problems appear: (ordered by priority)
Its oversized r="3200" to fit mostly all resolutions, how to make it responsive? -> Later I would add content in the inner-circle (solved by viewBox attribute )
Do not work on mobile (iPhone 6, Safari & Chrome) (done by using fixed values instead of calc())
Without the CSS Offset of .circle > stroke-dashoffset > -50 it laggs at start
I'm not that comfortable with SVG and that's the best result I reached so far, maybe I made it completly wrong for my purpose?
It should be responsive, fill out the complete screen always and work well with the common browsers. JS would be fine too, but is it necessary to reach it?
.item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
svg {
width: 100%;
height: 100%;
}
.circle {
stroke-dasharray: 20106.192982975;
stroke-dashoffset: 20106.192982975;
-webkit-animation: circle-in 3s ease-in-out forwards, fade-in 0.5s ease-out forwards;
}
#-webkit-keyframes circle-in {
to {
stroke-dashoffset: 0;
}
}
<div class="item">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<g>
<circle id="circle" class="circle" r="3200" cy="50%" cx="50%" stroke-width="6200" stroke="#000000" fill="none"/>
</g>
</svg>
</div>

Related

CSS Animation on SVG Element on iOS Safari 11 Not Working

I have a simple SVG that animates when it comes into viewport (via added class in Javascript). It's a simple bar chart that is supposed to animate the height of 2 rect elements.
It works fine everywhere except iPad Safari 11.1.2 (and maybe below)
When I remove the animation the SVG displays fine. The class is being added via javascript and webkit vendor prefixes are added for browser support.
<style type="text/css">
#keyframes draw {
from {
height: 0;
}
to {
height: 110px;
}
}
#keyframes drawBig {
from {
height: 0;
}
to {
height: 360px;
}
}
#-webkit-keyframes draw {
from {
height: 0;
}
to {
height: 110px;
}
}
#-webkit-keyframes drawBig {
from {
height: 0;
}
to {
height: 360px;
}
}
.animate-bar {
animation: draw 1s linear forwards;
animation-play-state: paused;
-webkit-animation: draw 1s linear forwards;
-webkit-animation-play-state: paused;
}
.animate-bar.bar-large {
animation-name: drawBig;
-webkit-animation-name: drawBig;
}
.play .animate-bar {
animation-play-state: running;
-webkit-animation-play-state: running;
}
</style>
<svg id="diagram" viewBox="0 0 290 472" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="svg" stroke="none" stroke-width="1" fill="#000000" fill-rule="evenodd">
<g id="left">
<rect class="animate-bar" x="0" y="283" width="132" height="107" rx="3" transform="scale(1,-1) translate(0,-676)">
</rect>
<text font-weight="bold">
<tspan x="47.384" y="263">1129</tspan>
</text>
</g>
<g id="right" transform="translate(152,0)">
<rect class="animate-bar bar-large" fill="#EEE6E2" x="0" y="33" width="132" height="360" rx="3" transform="scale(1,-1) translate(0,-426)">
</rect>
<text font-weight="bold">
<tspan x="36.56" y="17">4000</tspan>
</text>
</g>
</g>
</svg>
The CSS is just manipulating the height of the bars in the animation (which is paused until the class is added).
On iOS 11 though the bars just never animate so both heights appear to be 0 and you can't see either.
When I look in dev tools I can see the <rect> elements flashing in the DOM indicating something is happening to them (even though the only thing that should manipulate them is the CSS animation) but they are flashing very fast so I can't see what.
I'm at a loss of what else to try.
Here is a fiddle of the code:
http://jsfiddle.net/peuzdL2n/7/
Works in everything except iOS Safari 11 and below as far as I can see

CSS transitions 'spazing' some elements randomly on Firefox

First of all, it is working 100% fine for me on Chrome, but works just as title described when on Firefox
I'm trying to make a simple animation (using transitions) to run indefinitely when mouseover and to slowly go back to initial position when mouseout
The problem is that it is not behaving the same way in Firefox
As requested, here's a minimized and simplified code that reproduces my current issue:
var arcs = $("#logoSec");
var greenarc = $(".greenarc");
var garcMs = 2100; // In ms
var arcsAnimBool = false; // If false, stops the anim loop
greenarc.css({
transition: "transform " + (garcMs * 1) + "ms ease-in-out"
});
function greenArcNormal() {
if (!arcsAnimBool) return;
greenarc.css("transform", "rotate(70deg)");
setTimeout(greenArcRevert, garcMs); // Call the reverse rotation after garcMs ms
}
function greenArcRevert() {
if (!arcsAnimBool) return;
greenarc.css("transform", "rotate(-70deg)");
setTimeout(greenArcNormal, garcMs); // Call the normal rotation after garcMs ms
}
arcs.hover(
function() { // On mouseover
arcsAnimBool = true;
greenarc.css({
transition: "transform " + (garcMs * 1) + "ms ease-in-out"
});
greenArcNormal();
},
function() { // On mouseout
arcsAnimBool = false; // Set to false to stop the infinite loop of greenArcRevert/Normal
greenarc.css("transform", "rotate(0deg)"); // Revert arc back to initial position
greenarc.css({
transition: "transform " + (garcMs * 0.5) + "ms ease-in-out"
});
}
);
#ArcsLogo {
height: 550px;
}
#logoSec {
display: flex;
background-color: #fdfdfd;
}
<div id="logoSec">
<svg class="arcs" version="1.1" id="ArcsLogo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-12 30 383.4 407.5" style="enable-background:new 0 0 383.4 407.5;" xml:space="preserve">
<style type="text/css">
.greenarc {
fill: #00ff00;
transform-origin: 50% 50%;
}
.graycircle {
fill: #5d5d5d;
transform-origin: 50% 50%;
}
.redarc {
fill: #ff0000;
transform-origin: 50% 50%;
}
</style>
<path id="GreenArc" class="greenarc" d="M201.1,62.7c-3.2,0-6.3,0.1-9.4,0.3c77.7,5.5,136.2,72.9,130.7,150.6
c-4.9,70-60.7,125.8-130.7,130.7c3.1,0.2,6.3,0.4,9.4,0.4c77.9,0,141-63.1,141-141S279,62.7,201.1,62.7L201.1,62.7z" />
<circle id="GrayCircle" class="graycircle" cx="191.7" cy="203.7" r="21.2" />
<path id="RedArc" class="redarc" d="M60.2,203.7c0-84.6,65.9-154.6,150.4-159.6c-3.1-0.2-6.3-0.3-9.5-0.3
C112.8,43.2,40.7,114.2,40,202.5c-0.7,88.3,70.3,160.4,158.6,161.1c0.8,0,1.7,0,2.5,0c3.2,0,6.3-0.1,9.5-0.3
C126.2,358.3,60.2,288.3,60.2,203.7z" />
</svg>
</div>
(Simplified code in jsfiddle)
https://jsfiddle.net/Ferdam/htxcwanu/28/
(Old full code: https://jsfiddle.net/Ferdam/9kz52e6h/3/)
I have little experience with HTML/JS/JQuery/CSS so I might be missing something basic, I don't know.
Any help is appreciated. Thanks!
Edit:
Quoting directly what I answered to nivoli:
I forgot to mention that I tried using keyframes before, but the
problem is that I couldn't get it to work like the code I provided
because whenever I hoverout the elements just 'teleport' back to
initial position, which is why I started using css transitions.
I just couldn't find a way to animate the elements back to initial position
using keyframes
No javascript necessary; just use css animations. I only did the green one for you:
#ArcsLogo {
height: 550px;
}
#logoSec {
background-color: #fefefe;
}
.greenarc {
fill: #00ff00;
transform-origin: 50% 50%;
transform: rotate(70deg);
animation: myRotate 4200ms alternate infinite ease-in-out;
}
.graycircle {
fill: #5d5d5d;
transform-origin: 50% 50%;
}
.redarc {
fill: #ff0000;
transform-origin: 50% 50%;
}
#keyframes myRotate {
0% {
transform: rotate(70deg);
}
100% {
transform: rotate(-70deg);
}
}
<div id="logoSec">
<svg class="arcs" version="1.1" id="ArcsLogo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-12 30 383.4 407.5" style="enable-background:new 0 0 383.4 407.5;" xml:space="preserve">
<path id="GreenArc" class="greenarc" d="M201.1,62.7c-3.2,0-6.3,0.1-9.4,0.3c77.7,5.5,136.2,72.9,130.7,150.6
c-4.9,70-60.7,125.8-130.7,130.7c3.1,0.2,6.3,0.4,9.4,0.4c77.9,0,141-63.1,141-141S279,62.7,201.1,62.7L201.1,62.7z" />
<circle id="GrayCircle" class="graycircle" cx="191.7" cy="203.7" r="21.2" />
<path id="RedArc" class="redarc" d="M60.2,203.7c0-84.6,65.9-154.6,150.4-159.6c-3.1-0.2-6.3-0.3-9.5-0.3
C112.8,43.2,40.7,114.2,40,202.5c-0.7,88.3,70.3,160.4,158.6,161.1c0.8,0,1.7,0,2.5,0c3.2,0,6.3-0.1,9.5-0.3
C126.2,358.3,60.2,288.3,60.2,203.7z" />
</svg>
</div>
They key is to define the keyframes, which I just copied from the transform declarations you were making in javascript. Then by adding the animation rule to the greenarc class, we tell it to
use the keyframes myRotate (change the name to whatever you want)
take 4200ms to move from 0% to 100%. I doubled it because I think your logic took 2100ms to move from rotate(0) to rotate(70).
alternate the direction of the animation so that it goes back-and-forth rather than moving in one direction, then snapping back to where it started.
repeat the animation infinitely
use ease-in-out as you were doing in javascript to slow down as it gets closer to the ends.
See the animation documentation for more details and examples.

SVG Line Animation - Squishy Effect

***Update - solution listed below
I’ve got an svg animation bug I could use some expert help on.
I’m trying to create a similar animation that you can see here (http://springsummer.dk/) when you hover over some of their work (maybe half way down the page) — a line comes in and up and then kind of squishes to the right height.
I recreated this effect in a simple code pen that can be seen here: https://codepen.io/callmegoon/pen/EQRMjG (see code below).
However, in my testing, I came to learn that Safari does not support the negative stroke-dashoffset that I’m using in the animation.
Soooo, I’m trying to figure out a new solution - any ideas? Totally open to a completely different way to accomplish this (maybe a js solution?), but everything I’m doing hasn’t been working. My biggest issue has been the squish part at the end where the back/bottom of the line comes up - I haven’t figured out another way to accomplish that without the negative stroke-dashoffset.
Thanks!
/* Draw Line Animations */
#keyframes drawLine {
0% {
stroke-dasharray: 170;
stroke-dashoffset: 170;
}
100% {
stroke-dasharray: 170;
stroke-dashoffset: -50;
}
}
#keyframes unDrawLine {
0% {
stroke-dasharray: 170;
stroke-dashoffset: -50;
}
100% {
stroke-dasharray: 170;
stroke-dashoffset: 170;
}
}
.box {
background: red;
width: 500px;
height: 500px;
position: relative;
}
.box:hover .line {
animation: drawLine .6s cubic-bezier(.67,.02,.27,.95) forwards;
}
.line {
width: 4px;
height: 170px;
fill: none;
stroke: #fff;
stroke-width: 4px;
transform: rotate(195deg);
display: block;
position: absolute;
left: 50px;
bottom: 50px;
stroke-dasharray: 170;
stroke-dashoffset: 170;
animation: unDrawLine .6s cubic-bezier(.67,.02,.27,.95) forwards;
}
<div class="box">
<svg class="line" viewBox="0 0 4 170" xmlns="http://www.w3.org/2000/svg">
<line x1="0" y1="0" x2="0" y2="170" />
</svg>
</div>
Solution (uses GreenSock)
I was able to find a solution that perfectly matched the effect I was going for while also working in Safari - it just required GSAP and the draw plugin.
Solution demo here...
https://codepen.io/anon/pen/MQqwdo
Solution explanation...
The hack/fix/trick is just slightly animating one of the coordinates of the points in the line - not noticeable to users.

Circular timer sgv html js css, when making it bigger, the lines don't match up to the size

I have a circular timer done with js, css and html using svg. When i make the timer bigger, the lines don't match up with the timer so there is always a gap in the circular timer. How do i make the line that is drawn bigger to complete a full circle?
HTML
<div id="timer" style="height: 44px">
<div class="item html">
<h2 style="left: 0px; top: 28px">1200</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#be1e2d" fill="none"/>
</g>
</svg>
</div>
</div>
Javascript
var mins = 20;
var seconds = mins * 60; /* how long the timer runs for */
var initialOffset = '440';
var i = -1200;
var interval = setInterval(
function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset-(i*(initialOffset/seconds)));
$('h2').text(Math.abs(i));
if (i == 0) {
clearInterval(interval);
}
i++;
}, 1000);
CSS
.item h2 {
text-align: center;
position: absolute;
line-height: 125px;
width: 100%;
color: #FFFFFF;
left: 31px;
top: 24px;
height: 98px;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
Leave the circle radius alone, add a viewBox attribute to the <svg> element viewBox="0 0 160 160" then you can change the svg height/width as you wish and the circle will automatically scale without changing the radius at all.

CSS animation for SVG in IE10/IE11

I have this code:
<svg height="100" width="100">
<style>
.svg-circle {
-webkit-transform-origin: 50% 0;
transform-origin: 50% 0;
-webkit-transform: rotateY(0);
transform: rotateY(0);
}
.svg-circle:hover {
-webkit-transform: rotateY(360deg);
transform: rotateY(360deg);
-webkit-transition: all 0.7s;
transition: all 0.7s;
}
</style>
<circle class="svg-circle" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
It works well in modern browsers. Can I make it works in IE10/IE11? Or I need to use only Javascript?
After long researching I came to the conclusion the best way for cross-browser support — put image in <div> as background-image and apply CSS to it.
JSFiddle
.circle {
width: 100px;
height: 100px;
background: url(http://imgh.us/circle_5.svg) no-repeat;
background-size: 100px 100px;
-webkit-transform: rotateY(0);
transform: rotateY(0);
}
.circle:hover {
-webkit-transform: rotateY(360deg);
transform: rotateY(360deg);
-webkit-transition: all 0.7s;
transition: all 0.7s;
}
<div class="circle"></div>
Well, is it force on rotating the <circle/>?
Because you can easily rotate <svg></svg> in all browsers!
If yes, so you are in big trouble because in IE your problem is not only CSS3 support, you going to have some problem with JS, and that's because of rotateX or rotateY!
And even worst, you going to have some problem with animating it in jQuery!
So I used VELOCITY.JS to animating it and you can see this [ SAMPLE ] on IE and change rotateZ by rotateY! (to see rotateY is not working on SVG childs like path, circle, etc)
It seems you have to change your plan!
Hope to help! And by the way! by puting transition on hover state, you don't have it on hover-back!

Categories

Resources