Matter.js and SVG animation with CSS - css

I've this wordpress site uses matter.js and SVG animation with CSS. It gets heat up very quickly and sometimes exhausted the browser. The web server will go down once in a while for a few minutes too but I'm not sure if is correlated.
I've included a start/stop button to enable animation only when the user clicks instead of running it concurrently with the page loads. This does help a little.
I upgraded the machine type and it seems to solve the downtime issue however it is very expensive to keep. Considering the website is only using 10% of the resources and Google Cloud's recommender suggested to switch to a lower machine type to save 50% of the cost.
Are there ways I can improve the CSS animation?
<div id="animation1_wrapper">
<svg id="animation1" width="100%" height="100%" viewBox="0 0 418 255" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="ani_graphic">
<path class="animation1" d="M263.46 25.3801C257.63 29.2001 252.88 33.7801 249.33 37.8001H263.46V25.3801Z" fill="#000"></path>
.....
.....
.....
</g>
</svg>
</div>
<button id="button-ani">Toggle Animation Play State</button>
<script type="text/javascript">
var button = document.getElementsById('button-ani'),
test_ani = document.getElementByClassName('animation1');
button.onclick = function(){
test_ani.classList.toggle('playani');
}
</script>
.animation1:nth-child(16n + 1) {
--animation-delay: 0.2s;
}
.animation1:nth-child(16n + 2) {
--animation-delay: 0.3s;
}
.animation1:nth-child(16n + 3) {
--animation-delay: 0.4s;
}
.animation1:nth-child(16n + 4) {
--animation-delay: 0.5s;
}
.animation1:nth-child(16n + 5) {
--animation-delay: 0.5s;
}
#keyframes ani_keyframes {
0% {
fill: #000;
}
40% {
fill: #FF0;
}
80% {
fill: #330;
}
}

Related

How to close gap at the top of SVG triangle after drawing animation

I am working on a project with a lot of SVG-animation. I have no experience in this. I have Googled extensively without finding the solution to my problem.
The problem is that when animating certain shapes, the animation leaves a gap in the shape. This is most prevalent on shapes with angles, like a triangle.
I have seen this done successfully around the web, I just don't understand how. I have made a simple animation using Vivus Instant that you can see in this CodePen: Link to CodePen
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.89 367.25" class="start" style=""><title>triangeltest</title><path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path><style data-made-with="vivus-instant">.fTJakOHn_0{stroke-dasharray:930 932;stroke-dashoffset:931;}.start .fTJakOHn_0{animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;}#keyframes fTJakOHn_draw{100%{stroke-dashoffset:0;}}#keyframes fTJakOHn_fade{0%{stroke-opacity:1;}94.44444444444444%{stroke-opacity:1;}100%{stroke-opacity:0;}}</style></svg>
Are there any libraries I can use that automatically avoids this problem? Do I have to export the shapes from Illustrator in a specific way?
What I would do is just disable the dash array once the animation completes.
#keyframes fTJakOHn_draw {
99.9% { stroke-dashoffset:0; stroke-dasharray:930 932; }
100% { stroke-dasharray: none; }
}
If the animation needs to be able to restart after the fade animation, you might also need to put the dash pattern back afterwards.
#keyframes fTJakOHn_fade {
0% { stroke-opacity:1; }
94.44444444444444% { stroke-opacity:1; stroke-dasharray: none; }
100% { stroke-opacity:0; stroke-dasharray:930 932; }
}
Example:
.fTJakOHn_0 {
stroke-dasharray:930 932;
stroke-dashoffset:931;
}
.start .fTJakOHn_0 {
animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;
}
#keyframes fTJakOHn_draw {
99.9% { stroke-dashoffset:0; stroke-dasharray:930 932; }
100% { stroke-dasharray: none; }
}
#keyframes fTJakOHn_fade {
0% { stroke-opacity:1; }
94.44444444444444% { stroke-opacity:1; stroke-dasharray: none; }
100% { stroke-opacity:0; stroke-dasharray:930 932; }
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.89 367.25" class="start" style=""><title>triangeltest</title>
<path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path>
</svg>
Not sure if there's any easier way of doing this, the closest solution I found recently was using a clip path on the SVG itself. I've just stuck this on your codepen example as a tester:
svg {
clip-path: polygon(50% 6.4%, 0 100%, 100% 100%);
}
You may want to increase the stroke width if needed? It's not pretty, but it gets the result.
One possible solution would be adding stroke-linecap:round; stroke-linejoin:round; for the triangle:
Layer_1.addEventListener("click",()=>{Layer_1.classList.toggle("start")})
svg{border:1px solid;width:200px;}
<svg id="Layer_1" viewBox="0 0 242.89 367.25" class="start" ><title>triangeltest</title>
<path style="fill:#fff;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:15px" d="M121.44,23.89L10.38,359.75L232.51,359.75L121.44,23.89Z" class="fTJakOHn_0"></path>
<style data-made-with="vivus-instant">
.fTJakOHn_0{
stroke-dasharray:930;
stroke-dashoffset:930;
stroke-linecap:round;
stroke-linejoin:round;
}
.start .fTJakOHn_0{
animation:fTJakOHn_draw 3000ms ease-in 0ms forwards;
}
#keyframes fTJakOHn_draw{
100%{stroke-dashoffset:0;}
}</style>
</svg>

css animation and animation-direction not working in IE11

I am trying to show animated dashed lines in an SVG path.
Path is generated dynamically using d3 and animation can be in both the directions. Its working in all browsers except in IE. Fiddle Link
My issue is similar to SVG animation is not working on IE11 . But I couldn't get the solution from there.
<path id="pathOriginal" class="animation" style="animation-direction:reverse" d="M535,73C33.75,73 33.75,-20 -467.5,-20" stroke="red" stroke-width="1.5px" fill="none">
#keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
#-webkit-keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
.animation {
stroke-dasharray: 4;
stroke-dashoffset: 4;
animation: dash 50s linear infinite;
-webkit-animation: dash 2s linear infinite;
}
Last resort is to use some javascript magic!
var myPath = document.getElementById('pathOriginal');
var i = 1000;
var intervalID = window.setInterval(myCallback, 20);
function myCallback() {
// Your code here
if (i == 0) { i = 1000}
myPath.setAttribute('stroke-dashoffset', i);
--i;
}
<svg width="500" height="500" id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(200,200)">
<path id="pathOriginal" class="animation" style="animation-direction:reverse" d="M535,73C33.75,73 33.75,-20 -467.5,-20" stroke="red" stroke-width="1.5px" fill="none" stroke-dasharray="4">
</path>
</g>
</svg>
IE don't support CSS animations on all SVG elements.
you have to modify the inline attributes of the SVG elements

Transition svg element with css

Problem
I'm trying to simply move an svg element using transform=matrix(a,b,c,d,e,f)
The element is moving fine but when I apply a css transition it has no effect.
Question
Is this possible on svg elements without an external library like d3?
Code I'm trying
html:
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc"
transform="matrix(1,0,0,1,1,1)"
id="blueBox"
/>
</svg>
<button id="boxMover">
Move it
</button>
jQuery
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
if(blueBox.attr('transform')=='matrix(1,0,0,1,1,1)'){
blueBox.attr('transform', 'matrix(1,0,0,1,100,30)');
} else {
blueBox.attr('transform', 'matrix(1,0,0,1,1,1)');
}
})
})
CSS
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
transition: transform .5s ease;
}
Here's a fiddle I created to test it
A simpler solution:
Create the following class:
.boxEase {
transform: matrix(1,0,0,1,100,30);
transition: all .5s ease;
}
Change your jQuery code to just attach the above class to your box when the button is clicked:
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
blueBox.attr('class', 'boxEase');
})
})
Added dynamic case with variable ending (starting) positions
Use the following jQuery code where transform and transition properties are added to the box conditionally. I imagine you can adjust the conditional to something else but I have used your original example for this case:
`$(function(){
$('#boxMover').click(function(){
var startPos = 'matrix(1,0,0,1,1,1)',
endPos = 'matrix(1,0,0,1,100,30)';
var blueBox = $('#blueBox');
if(blueBox.attr('transform') == startPos){
blueBox.attr('transform', endPos);
blueBox.css({'transform': endPos, 'transition': 'all 0.5s ease'});
} else {
blueBox.attr('transform', startPos);
blueBox.css({'transform': startPos, 'transition': 'all 0.5s ease'});
}
})
}); `
There's a horrible grey area between the CSS and SVG namespaces where things like this happen all the time.
However, you can fix your problem as follows:
Move the transform CSS statement out of the #boxMover rules and put it somewhere it can actually affect the behaviour of your #blueBox SVG element.
Changing the transform attributes of the SVG element directly still won't work because you're talking to the SVG namespace, and the CSS rules aren't having any say in the matter. Instead, set up CSS classes containing the required transform attributes, and switch between those instead. There is no class attribute in the SVG namespace, so the CSS rules will come to life.
Also note that you can't use JQuery's addClass() and removeClass() methods to change the class of an SVG element, so use attr('class') instead
This should work:
$(function() {
$('#boxMover').click(function() {
var blueBox = $('#blueBox');
if (blueBox.attr('class') == 'overHere') {
blueBox.attr('class', 'overThere');
} else {
blueBox.attr('class', 'overHere');
}
})
})
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
}
#blueBox {
transition: transform .5s ease;
}
.overHere {
transform: matrix(1, 0, 0, 1, 1, 1);
}
.overThere {
transform: matrix(1, 0, 0, 1, 100, 30);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc" class="overHere" id="blueBox" />
</svg>
<button id="boxMover">
Move it
</button>

Floating ghost CSS animation

I have created an SVG ghost for my website's logo. I have made a CSS animation so when a user hovers the logo, the ghost starts floating.
Everything works okay except that when it is unhovered, the ghost just drops back to it's original position. Is it possible to have it also animated when it returns to translateY(0)? I have tried a solution myself, but it doesn't work.
Here is the example:
#keyframes float {
100% {
transform: translateY(-8px);
}
}
#keyframes bob {
0% {
transform: translateY(-8px);
}
100% {
transform: translateY(0);
}
}
#keyframes sink {
100% {
transform: translateY(0);
}
}
#logo svg {
margin: 20px;
overflow: visible;
}
#logo #ghost {
animation-name: sink;
animation-duration: 0.3s;
animation-timing-function: ease-out;
animation-delay: 0s;
animation-direction: normal;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
#logo:hover #ghost {
animation-name: float, bob;
animation-duration: 0.3s, 0.7s;
animation-timing-function: ease-out, ease-in-out;
animation-delay: 0s, 0.3s;
animation-direction: normal, alternate;
animation-iteration-count: 1, infinite;
animation-fill-mode: forwards;
}
<div id="logo">
<svg width="100" height="100">
<g id="ghost">
<rect fill="red" width="100" height="100" />
</g>
</svg>
</div>
It isn't all that difficult with JQuery.
Here's a function that can be called regularly with a setInterval() timer:
var haunt=function(){
var dy;
ghost_ticks++;
ghost_clock++;
if (ghost_clock>30) ghost_clock=30;
dy = Math.sin(Math.abs(ghost_clock) * Math.PI/60); /* sine wave */
dy *= -40 + 6*Math.cos(ghost_ticks/5); /* ramp */
$("#ghost").css("transform","translate(0,"+dy+"px)");
if (ghost_clock==0) {
clearInterval(ghost_timer);
ghost_timer=ghost_ticks=0;
}
}
This calculates the ghost's position as the sum of two components — a sine-wave hovering motion, and a vertical offset that ramps up and down at the start and end of the animation and also controls the amplitude of the hovering.
This is done with two counter variables: ghost_ticks simply increments at every tick and is used to calculate the hovering position, while ghost_clock controls the ramp by counting up to 30 and then stopping. At the end of the animation, its value is made negative, so it counts back to zero, at which point the animation stops.
You can still use a CSS transition to change the ghost's colour.
var ghost_ticks=0, ghost_clock=0, ghost_timer=0;
var haunt=function(){
var dy;
ghost_ticks++;
ghost_clock++;
if (ghost_clock>30) ghost_clock=30;
dy = Math.sin(Math.abs(ghost_clock) * Math.PI/60);
dy *= -40 + 6*Math.cos(ghost_ticks/5);
$("#ghost").css("transform","translate(0,"+dy+"px)");
if (ghost_clock==0) {
clearInterval(ghost_timer);
ghost_timer=ghost_ticks=0;
}
}
var start_haunting=function(){
if (ghost_clock < 0) ghost_clock = -ghost_clock;
if (!ghost_clock) ghost_timer=setInterval(haunt,25);
};
var stop_haunting=function(){
if (ghost_clock > 0) ghost_clock = -ghost_clock;
};
$(document).ready(function(){
$("#logo").hover(start_haunting,stop_haunting);
});
#logo { background-color:#000; width: 200px; height: 200px; }
#logo #ghost { fill:#333; transition: fill 1s; }
#logo:hover #ghost { fill:#999; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="logo">
<svg width="200" height="200" viewBox="0 0 200 200">
<g id="ghost" stroke="none">
<path d="M60 160V100A40 40 0 0 1 140 100V160l-10-10l-10 10l
-10-10l-10 10l-10-10l-10 10l-10-10ZM73 100a10 10 0
0 0 20 0 10 10 0 0 0 -20 0M107 100a10 10 0 0 0 20
0 10 10 0 0 0 -20 0z" />
</g>
</svg>
</div>

Change direction of SVG animation

I saw this SVG animation and I'm wondering how to alter the direction that the line is erased in; currently the line retracts from the last point it is drawn, however I want the reverse; for the line to erase itself from the point where it first started to draw (so that it looks more like a loading animation).
I see that the animation property on .path has a value of infinite, but I'm not sure how the direction is specified.
The HTML is
<div class="bg">
<svg xmlns="http://www.w3.org/2000/svg" width="670" height="236" viewBox="0 0 670 236">
<path class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="300" stroke-dashoffset="300" fill="none" d="M343.6 75.9v20.3l23.1 21.8-23.1 21.8v20.3l44.6-42.1zM326.4 139.8l-23.1-21.8 23.1-21.8v-20.3l-44.6 42.1 44.6 42.1z"/>
<path class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="500" stroke-dashoffset="500" fill="none" d="M335 38.9c-43.7 0-79.1 35.4-79.1 79.1s35.4 79.1 79.1 79.1 79.1-35.4 79.1-79.1-35.4-79.1-79.1-79.1zM335 182.9c-35.8 0-64.9-29.1-64.9-64.9s29.1-64.9 64.9-64.9 64.9 29.1 64.9 64.9-29.1 64.9-64.9 64.9z"/>
</svg>
</div>
And the CSS is
body {
background-color: #fff;
}
.bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.path {
animation: draw 3.5s infinite;
}
#keyframes draw {
50% {
stroke-dashoffset: 0;
}
}
I like your idea of making this an loading animation:
CODEPEN
Now what i did:
changed the animation start stop point
#keyframes draw {
100% {
stroke-dashoffset: -500;
}
}
Why -500?
Because this is the value of the dash-array.
This is defined in the <svg>: dasharray="500"
Changed this value in the inner most path. It was only 300
I added a linear animation
animation: draw 5s infinite linear;
The default is ease. I found the animation has better consistency with a linear animation.
NOTE
dashoffset=500 <- makes the animation start without the dash/stroke
I used the negative value for stroke-dashoffset that Persijn recommended. This worked great in Chrome and FF, but it didn't work properly in Safari.
I've found that if you open the SVG in Illustrator, you can reverse the direction of the path, by opening the Attributes panel (you might have to click the "show more" in the top right) and literally clicking the "reverse path" button.
stroke-dasharray can be a list of white space separated dashes and gaps, so you could do something like this:
var svgPath = document.getElementById('svgPath');
var pathLength = svgPath.getTotalLength();
var offset = 0;
function offsetPath() {
requestAnimationFrame(offsetPath);
offset += 0.1;
var dasharray = 0 + ' ' + offset + ' ' + (pathLength - offset);
svgPath.setAttribute('stroke-dasharray', dasharray);
}
requestAnimationFrame(offsetPath);
<svg xmlns="http://www.w3.org/2000/svg" width="670" height="236" viewBox="0 0 670 236">
<path id="svgPath" class="path" stroke="#4CADC1" stroke-width="4" stroke-linejoin="round" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="100 100 100" fill="none" d="M343.6 75.9v20.3l23.1 21.8-23.1 21.8v20.3l44.6-42.1zM326.4 139.8l-23.1-21.8 23.1-21.8v-20.3l-44.6 42.1 44.6 42.1z"
/>
</svg>
Changing SVG Line Animation Direction
Add KeyFrames and Classes for Both Directions:
.dash {
stroke-dasharray : 10 5;
animation : dash 4s linear infinite;
}
.dash_reverse {
stroke-dasharray : 10 5;
animation : dash_reverse 4s linear infinite;
}
#keyframes dash {
to {
stroke-dashoffset: 100;
}
}
#keyframes dash_reverse {
to {
stroke-dashoffset: -100;
}
}
Use JavaScript to Toggle Animation:
function animate_line_forward(id) {
$("#" + id).removeClass("dash_reverse");
$("#" + id).addClass("dash");
}
function animate_line_reverse(id) {
$("#" + id).removeClass("dash");
$("#" + id).addClass("dash_reverse");
}
Call functions as needed (pass the SVG line id into the above functions:
Calling animate_line_forward:
Calling animate_line_reverse:

Resources