I'm trying to draw an SVG logo using Keyframes. It works fine stand alone when I open the SVG file by itself in the browser, but it doesn't work when I try to use it in my React project.
For mu react project, I am using image-webpack-loader to load SVG images and I have made the following alterations to webpack config file:
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
hash: 'sha512',
digest: 'hex',
name: '[hash].[ext]',
}
},
{
loader:'image-webpack-loader',
options:{
bypassOnDebug:true,
},
}
],
}
Here's my React JS file code:
import React from 'react';
import '../stylesheets/Atom.css'
import Atom from '../Assets/images/atom.svg';
const AtomSpinner = props => {
return (
<div className='atomWrapper'>
<img className='atom' src={Atom}/>
</div>
);
};
export default AtomSpinner;
This is the CSS that I am using for this React Component as well as the SVG file. Even if I am putting all styles for the SVG and React in the same stylesheet, the SVG animation works fine when I use it in the browser. Here's the stylesheet:
.atomWrapper{
text-align: center;
}
.atom{
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
max-height:256px ;
max-width: 256px;
}
svg {
max-width: 256px;
max-height: 256px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
path {
fill-opacity:0;
stroke: #000;
stroke-width: 3;
stroke-dasharray: 351.0306396484375em;
stroke-dashoffset:351em ;
-webkit-animation-name: draw;
-webkit-animation-duration: 10s;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: 2;
-webkit-animation-timing-function: ease;
}
circle {
fill-opacity:0;
stroke: #000;
stroke-width: 3;
stroke-dasharray: 304em;
stroke-dashoffset:303.5em ;
-webkit-animation-name: draw;
-webkit-animation-duration: 3s;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
}
#-webkit-keyframes draw {
to {
stroke-dashoffset: 0.8;
}
to{
fill-opacity: 1;
}
}
#keyframes draw {
to {
stroke-dashoffset: 0.8;
}
to{
fill-opacity: 1;
}
}
Here's a jsFiddle with the SVG and styles in it:
https://jsfiddle.net/nxxu1Lob/1/
Related
I am encountering a problem where an animation that is set to run on click is happening instantly when it should have a delay, when I change the state from false to true manually I can see the transition working fine, however when implementing the onClick feature and clicking the element it does not have the animation-duration being applied.
does anyone know a work around or a best practise to getting this working?
Main.js
import React, { useState } from "react";
export default function Main() {
const [isToggled, setIsToggled] = useState(false)
function handleToggle() {
setIsToggled(!isToggled)
}
return (
<div className="menu"
onClick={handleToggle}
>
<img src={require("../resources/menu-dropdown.png")}
className={isToggled ? "menu--dropdown top--tile motion" : "menu--dropdown top--tile reverse--motion"}
/>
<img src={require("../resources/menu-dropdown.png")}
className={isToggled ? "menu--dropdown bottom--tile motion" : "menu--dropdown bottom--tile reverse--motion"}
/>
</div>
)
}
styles.css
.menu--dropdown {
width: 15%;
position: absolute;
}
.top--tile {
top: -10%;
right: -95%;
}
#keyframes top--motion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
transform-origin: 30% 70%;
}
}
.top--tile.motion {
animation-name: top--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.top--tile.reverse--motion {
animation-direction: reverse;
animation-name: top--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
#keyframes bottom--motion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-45deg);
transform-origin: 40% 60%;
}
}
.bottom--tile {
top: -7.5%;
right: -95%;
}
.bottom--tile.motion {
animation-name: bottom--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.bottom--tile.reverse--motion {
animation-direction: reverse;
animation-name: bottom--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
Hello All^^ I have created a slide animation for an SVG logo that I have designed. Sliding the image to the left with a key frame animation on screen size using media queries was not difficult. However, I am unable to get the SVG to slide back to center (original position), via animation or transition delay, etc. Upon changing back to smaller media query sizes, the SVG simply jumps to its original position(main logo on the page).
I have not been able to find a way to resolve this. However, a link to a codepen is below. If you think you may be able to help, I would sincerely appreciate it. Thanks.
https://codepen.io/shaunbolak/pen/RwWmgVK
/* ============================================= */
/* SVG Keyframes */
/* ============================================= */
#keyframes offset {
100% {
stroke-dashoffset: 0;
}
}
#keyframes mobile-path-fill {
100% {
fill: $logo-main-path-color;
}
}
#keyframes fill-desktop {
100% {
fill: $logo-alternate-path-color;
}
}
#keyframes move-left {
100% {
transform: translateX(-118%);
}
}
/* ============================================= */
/* Main logo */
/* ============================================= */
#logo {
padding-top: 15px;
height: 150px;
width: 350px;
#include for-size(desktop-up) {
animation: move-left 2s forwards;
padding-top: 20px;
height: 120px;
width: 300px;
transition: width 1s;
}
#include for-size(larger-desktop-up) {
width: 350px;
transition: width 1s;
}
#include for-size(big-desktop-up) {
width: 400px;
transition: width 1s;
}
}
#logoFill {
fill: $logo-main-fill;
stroke: $logo-main-fill;
#include for-size(desktop-up) {
animation: fill-desktop 1.5s 1.2s forwards;
}
}
.logo-stroke {
stroke: $logo-main-path-color;
stroke-width: 1;
stroke-dasharray: 325;
stroke-dashoffset: 325;
animation: offset 3s linear forwards, mobile-path-fill 1.2s 3s forwards;
}
Add:
#keyframes move-right {
from {
transform: translateX(-118%);
} to {
transform: translateX(0);
}
}
And then:
#media (max-width: 1200px) {
#logo {
animation: move-right 2s;
padding-top: 20px;
height: 120px;
width: 300px;
transition: width 1s;
}
}
I've checked that and it works well...
I'm trying to create a visual transition between content changes in a toy SPA I'm writing. To that end, I define a simple class for animating the opacity of an element.
.fade {
transition: opacity 1.5s;
}
In my render function, I now change the opacity of my outlet div after content changes like so:
function render(content) {
var outlet = document.getElementById("outlet");
outlet.classList.remove("fade");
outlet.style.opacity = 0;
outlet.innerHTML = content;
outlet.classList.add("fade");
outlet.style.opacity = 1;
}
Unfortunately, the animation never fires. When I delay changing the opacity to 1 via setTimeout for 10ms, say, it works sometimes if I don't change the content again while the animation is still running, indicating a timing issue/race condition.
I used a similar approach in the past to fade out messages, but there I intentionally delayed changing the opacity by a few seconds so users could read the message before it starts fading out.
Pure CSS animation fadeIn
li {
position: absolute;
top: 50%;
left: 50%;
margin-top: -75px;
}
.logo {
width: 300px;
height: 150px;
background: red;
margin-left: -150px;
z-index: 30;
-webkit-animation: fade-in-slogan 4s .2s ease-in forwards;
-moz-animation: fade-in-slogan 4s .2s ease-in forwards;
animation: fade-in-slogan 4s .2s ease-in forwards;
}
.menu {
width: 600px;
height: 150px;
background: blue;
margin-left: -300px;
opacity: 0;
-webkit-animation: fade-in-menu 3s 4s ease-out forwards;
-moz-animation: fade-in-menu 3s 4s ease-out forwards;
animation: fade-in-menu 3s 4s ease-out forwards;
}
#-webkit-keyframes fade-in-slogan {
0% { opacity: 0; }
30% { opacity: 1; }
50% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; }
}
#-webkit-keyframes fade-in-menu {
0% { display: block; opacity: 0; }
30% { display: block; opacity: .3; }
60% { display: block; opacity: .6; }
80% { display: block; opacity: .8; }
100% { display: block; opacity: 1; }
}
<ul class"main">
<li class="logo"></li>
<li class="menu"></li>
</ul>
Try this, I hope this will solve the issue
.fade{
animation-name: example;
animation-duration: 4s;}
#keyframes example {
from {opacity:1}
to {opacity:0;}
}
div{
width:200px;
height:200px;
background:#000;
}
<html>
<head>
</head>
<body>
<div class="fade"></div>
</body>
</html>
I've solved it now inspired by Muhammad's answer. I defined the fade class as follows:
.fade {
animation-name: fadein;
animation-duration: 1.25s;
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
Then in the render function, I do
function render(content) {
outlet.classList.remove("fade");
outlet.innerHTML = "";
setTimeout(() => {
outlet.classList.add("fade");
outlet.appendChild(content);
}, 100);
}
Even though this adds an additional delay before the new content actually starts to fade in, it seems the most elegant and concise solution to me.
$(function() {
$('.text1').delay(1000).fadeIn(1500);
$('.text1').delay(600).fadeOut(1500);
$('.text2').delay(5000).fadeIn(1500);
$('.text2').delay(600).fadeOut(1500);
$('.text3').delay(10000).fadeIn(1500);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="text1">Lorem Ipsem</div>
<div class="text2">Lorem Ipsem</div>
<div class="text3">Lorem Ipsem</div>
Above is my simple jQuery animation; simple delay -> fadeIn -> delay -> fadeOut. However I find when trying to create a loop, for my animations to run continuously my code becomes way to large and bulky. I am wondering if it's at all possible to rewrite what I have above with CSS3 only, and then using the infinite option CSS allows.
I've gotten close with CSS below code however, I need to completely hide or fadeOut each line of text before new text shows.
#-webkit-keyframes slider {
0% { opacity: 0.4; }
100% { opacity: 1; }
}
#-moz-keyframes slider {
0% { opacity: 0.4; }
100% { opacity: 1; }
}
#-ms-keyframes slider {
0% { opacity: 0.4; }
100% { opacity: 1; }
}
.slider {
-webkit-animation: slider 1s alternate infinite;
-moz-animation: slider 1s alternate infinite;
-ms-animation: slider 1s alternate infinite;
}
<div class="slider">Lorem Ipsum</div>
As stated in other answers you can not achieve what you are asking using pure CSS solutions.
You can a solution like to an extensible approach (in case you want have many more child elements).
$("#fadeinout div").on("animationend", function() {
_this = jQuery(this);
// remove animation class
_this.removeClass("animate");
// If there is no next element then go to first one otherwise choose next element
var next = (_this.next().length < 1) ? _this.prevAll(':first-child') : _this.next();
// Add class to the new element
next.addClass("animate");
});
#fadeinout div {
width: 100px;
height: 100px;
background: red;
opacity: 0;
margin: 5px;
}
.animate {
animation-name: fadeinout;
animation-duration: 4s;
animation-delay: 0s;
}
#keyframes fadeinout {
50% {
opacity: 1;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fadeinout">
<div class='animate'></div>
<div></div>
<div></div>
<div></div>
</div>
This is the same example with many child elements animated: https://jsfiddle.net/j4zdgopr/1/
You can't really time the animation of multiple elements in css only. Well you could probably fake it with something like:
div {
width: 50px;
height: 50px;
background: #f00;
opacity: 0;
}
#d1 {
animation: d1 10s infinite;
}
#d2 {
animation: d2 10s infinite;
}
#d3 {
animation: d3 10s infinite;
}
#d4 {
animation: d4 10s infinite;
}
#keyframes d1 {
0% { opacity: 0; }
5% { opacity: 1; }
20% { opacity: 1; }
25% { opacity: 0; }
}
#keyframes d2 {
25% { opacity: 0; }
30% { opacity: 1; }
45% { opacity: 1; }
50% { opacity: 0; }
}
#keyframes d3 {
50% { opacity: 0; }
55% { opacity: 1; }
70% { opacity: 1; }
75% { opacity: 0; }
}
#keyframes d4 {
75% { opacity: 0; }
80% { opacity: 1; }
95% { opacity: 1; }
100% { opacity: 0; }
}
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
...but I would recommend against it. First of all I don't think the timing will be reliable - ie. it will get out of sync. Second your code will most likely be even more bulky than what you have.
So I would recommend a combination of simple CSS transitions and JS like this:
var curslide = 0;
var slides = $("#slider div");
var nextslide = function() {
slides.removeClass('shown');
if (curslide >= slides.length) curslide = 0;
slides.eq(curslide).addClass('shown');
curslide++;
setTimeout(nextslide, 3000);
}
nextslide();
#slider div {
width: 50px;
height: 50px;
background: #f00;
opacity: 0;
transition: opacity .5s linear;
}
#slider div.shown {
opacity: 1;
transition: opacity .5s .5s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="slider">
<div id="d1"></div>
<div id="d2"></div>
<div id="d3"></div>
<div id="d4"></div>
</div>
With this solution you can add as many frames as needed without modifying the css or js.
I'd try playing with animation-delay, but I think it only applies to the first time the animation is run. After that, unless you write one animation for each .text element, they'll all fade in/out with the same frequency.
Would:
setInterval(function(){
$('.text1').delay(5000).fadeIn(1500);
$('.text2').delay(5000).fadeIn(1500);
$('.text3').delay(5000).fadeIn(1500);
$('.text1').delay(1000).fadeOut(1500);
$('.text2').delay(5000).fadeOut(1500);
}, 11500);
get you somewhere close?
I have created an animation for SVG using css3 which is working perfectly in Chrome and Firefox. It is partially working in Safari but not working in Internet Explorer (IE9+ which support css animations)
See Demo
CSS:
#-webkit-keyframes dash {
70%,80% {
stroke-dashoffset: 0;
fill-opacity: 0;
}
85% {
fill-opacity: 0;
stroke-opacity: 1;
}
95% {
stroke: #17739D;
stroke-dashoffset: -301;
stroke-opacity: 0;
}
100% {
fill-opacity: 1;
stroke-dashoffset: -301;
}
}
#-ms-keyframes dash {
70%,80% {
stroke-dashoffset: 0;
fill-opacity: 0;
}
85% {
fill-opacity: 0;
stroke-opacity: 1;
}
95% {
stroke: #17739D;
stroke-dashoffset: -301;
stroke-opacity: 0;
}
100% {
fill-opacity: 1;
stroke-dashoffset: -301;
}
}
#-moz-keyframes dash {
70%,80% {
stroke-dashoffset: 0;
fill-opacity: 0;
}
85% {
fill-opacity: 0;
stroke-opacity: 1;
}
95% {
stroke: #17739D;
stroke-dashoffset: -301;
stroke-opacity: 0;
}
100% {
fill-opacity: 1;
stroke-dashoffset: -301;
}
}
#keyframes dash {
70%,80% {
stroke-dashoffset: 0;
fill-opacity: 0;
}
85% {
fill-opacity: 0;
stroke-opacity: 1;
}
95% {
stroke: #17739D;
stroke-dashoffset: -301;
stroke-opacity: 0;
}
100% {
fill-opacity: 1;
stroke-dashoffset: -301;
}
}
#Layer_1 {
margin-left: auto;
margin-right : auto;
top: 50%;
position: absolute;
left: 50%;
margin-left: -65px;
margin-top: -35px;
}
svg {
background: #fff;
display: block;
}
svg * {
stroke: #666;
#stroke: #17739D;
stroke-width: 1;
fill-opacity: 0;
stroke-dasharray: 350;
stroke-dashoffset: 440;
}
svg #bp_svg * {
-webkit-animation-name : dash;
-moz-animation-name : dash;
-ms-animation-name : dash;
animation-name : dash;
-webkit-animation-duration: 4s;
-moz-animation-duration: 4s;
-ms-animation-duration: 4s;
animation-duration: 4s;
-webkit-animation-timing-function : linear;
-moz-animation-timing-function : linear;
-ms-animation-timing-function : linear;
animation-timing-function : linear;
-webkit-animation-fill-mode : forwards;
-moz-animation-fill-mode : forwards;
-ms-animation-fill-mode : forwards;
animation-fill-mode : forwards;
}
Can anyone help me to sort out what to do to make it work properly in Safari and IE also?
While CSS3 animations are supported in IE9, SVG animations are not even supported in IE11 and it's hard to tell whether they will ever be. You probably have to either rely on animated HTML elements or use JavaScript which will not benefit from the hardware acceleration used to render CSS animations but still might be a viable solution.
Another idea would be to prerender it and deploy it as a gif, either every time or only in IE.
Source: http://caniuse.com/#feat=svg-smil
CSS3 animations are not supported in IE9, which explains why it doesn't work in IE9. The same will apply for Safari,it may help to also give the versions of each browser. Please refer to this list of supported features: http://caniuse.com/css-animation
I would suggest using raphaeljs javascript library. It has great capability in animating svg.
Raphael currently supports Chrome 5.0+ Firefox 3.0+, Safari 3.0+,
Opera 9.5+ and Internet Explorer 6.0+
http://raphaeljs.com/
http://raphaeljs.com/playground.html - quick preview.