How do I make an animation start on scroll down? - javascript

I made an animation inside a section on a page, but it starts when I reload the page. How do I make it start only when I scroll down to that section?
I want something like
if (scrolls to skills)
start animation
.o1 {
fill: none;
stroke: rgb(94, 217, 250);
stroke-width: 20px;
stroke-dasharray: 472;
stroke-dashoffset: 472;
animation: anim 2s linear forwards;
}
#keyframes anim {
100% {
stroke-dashoffset: 70;
}
}
<section id="skills">
<div class="skill">
<div class="outer">
<div class="inner">
<div id="number">
</div>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="160px" `height="160px">
<circle class="o1" cx="80" cy="80" r="70" stroke-linecap="round" />
</svg>
</div>
<script>
let number = document.getElementById("number");
let counter = 0;
setInterval(() => {
if (counter == 95) {
clearInterval();
} else {
counter += 1;
number.innerHTML = counter + "%";
}
}, 20)
</script>
</section>

Related

how to write #keyframes CSS, in Javascript [duplicate]

This question already has answers here:
Passing parameters to css animation
(3 answers)
Closed 2 years ago.
i have this svg with the respective css which animates the path.
HTML
<div>
<svg version="1.1" baseProfile="full" width="400" height="300" xmlns="http://www.w3.org/2000/svg">
<path class="grey" fill="none" stroke="#B7C4D2" stroke-width="10" d="M 136 277 A 100 100 0 1 1 264 277"></path>
<path class="blue" fill="none" stroke="#30A7F4" stroke-width="10" d="M 136 277 A 100 100 0 1 1 264 277"></path>
</svg>
</div>
CSS
.blue {
stroke-dasharray: 490;
stroke-dashoffset: 490;
animation: draw 2s linear forwards;
}
#keyframes draw {
to {
stroke-dashoffset: 260;
}
}
i want to make the "stroke-dashoffset: 260" value dynamic, any way to do that via JS?
One performant way of changing CSS with JS is using CSS variables.
you'd then have:
.blue {
stroke-dasharray: 490;
stroke-dashoffset: 490;
animation: draw 2s linear forwards;
}
#keyframes draw {
to {
stroke-dashoffset: var(--stroke-dashoffset);
}
}
and in your JS:
const theBlue = document.querySelectorAll('svg .blue')[0]
theBlue.style.setProperty('--stroke-dashoffset', 260)
you can inject internal style and you can send offest value to setAnimationOffest(120) dynamically.
function addAnimation(name, body) {
if (!dynamicStyles) {
dynamicStyles = document.createElement('style');
dynamicStyles.type = 'text/css';
document.head.appendChild(dynamicStyles);
}
dynamicStyles.sheet.insertRule(`#keyframes ${ name } {
${ body }
}`, dynamicStyles.length);
}
let dynamicStyles = null;
function addAnimation(name, body) {
if (!dynamicStyles) {
dynamicStyles = document.createElement('style');
dynamicStyles.type = 'text/css';
document.head.appendChild(dynamicStyles);
}
dynamicStyles.sheet.insertRule(`#keyframes ${ name } {
${ body }
}`, dynamicStyles.length);
}
function setAnimationOffest(offest){
addAnimation('draw', `
to { stroke-dashoffset: ${offest}; }
`);
};
setAnimationOffest(120);
.blue {
stroke-dasharray: 490;
stroke-dashoffset: 490;
animation: draw 2s linear forwards;
}
#keyframes draw {
to {
stroke-dashoffset: 260;
}
}
<div>
<svg version="1.1" baseProfile="full" width="400" height="300" xmlns="http://www.w3.org/2000/svg">
<path class="grey" fill="none" stroke="#B7C4D2" stroke-width="10" d="M 136 277 A 100 100 0 1 1 264 277"></path>
<path class="blue" fill="none" stroke="#30A7F4" stroke-width="10" d="M 136 277 A 100 100 0 1 1 264 277"></path>
</svg>
</div>

How to delay html/css load until item is in viewport

I have an animation on a chart but I want the CSS animation to load once it becomes into the users viewport. Currently it loads on the page load but this means that once the user has scrolled to the section the animation has already occurred.
The HTML & CSS can be seen below:
.chart[data-percent='100'] .outer {
stroke-dashoffset: 0;
-webkit-animation: show100 2s;
animation: show100 2s;
}
.chart[data-percent='96'] .outer {
stroke-dashoffset: 22;
-webkit-animation: show96 2s;
animation: show96 2s;
}
.chart[data-percent='77'] .outer {
stroke-dashoffset: 123;
-webkit-animation: show75 2s;
animation: show75 2s;
}
.chart[data-percent='75'] .outer {
stroke-dashoffset: 133;
-webkit-animation: show75 2s;
animation: show75 2s;
}
.chart[data-percent='52'] .outer {
stroke-dashoffset: 257;
-webkit-animation: show52 2s;
animation: show52 2s;
}
.chart[data-percent='50'] .outer {
stroke-dashoffset: 267;
-webkit-animation: show50 2s;
animation: show50 2s;
}
.chart[data-percent='25'] .outer {
stroke-dashoffset: 401;
-webkit-animation: show25 2s;
animation: show25 2s;
}
#-webkit-keyframes show100 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 0;
}
}
#keyframes show96 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 22;
}
}
#keyframes show75 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 124;
}
}
#-webkit-keyframes show52 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 257;
}
}
#-webkit-keyframes show50 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 267;
}
}
#keyframes show25 {
from {
stroke-dashoffset: 537;
}
to {
stroke-dashoffset: 401;
}
}
<div class="row stat-wheel">
<div class="col-sm-4">
<p class="stat-figure">52%</p>
<figure class="chart" data-percent="52">
<svg width="200" height="200">
<circle class="outer" cx="95" cy="95" r="85" transform="rotate(-90, 95, 95)"/>
</svg>
</figure>
<p class="white center">increase in sales generated through campaigns</p>
</div>
<div class="col-sm-4">
<p class="stat-figure">77%</p>
<figure class="chart" data-percent="77">
<svg width="200" height="200">
<circle class="outer" cx="95" cy="95" r="85" transform="rotate(-90, 95, 95)"/>
</svg>
</figure>
<p class="white center">return on investment in the first 2 months</p>
</div>
<div class="col-sm-4">
<p class="stat-figure">96%</p>
<figure class="chart" data-percent="96">
<svg width="200" height="200">
<circle class="outer" cx="95" cy="95" r="85" transform="rotate(-90, 95, 95)"/>
</svg>
</figure>
<p class="white center">increase in the quality of sales leads generated</p>
</div>
</div>
You can checkout the intersection observer api, it tells you when an element becomes visible in your viewport. You can listen to it and then start your animation.
A very clean way would be using vanilla JS.
Link with explanation
// (c) 2017 Chris Ferdinandi
var isInViewport = function (elem) {
var distance = elem.getBoundingClientRect();
return (
distance.top >= 0 &&
distance.left >= 0 &&
distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
distance.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
var findMe = document.querySelector('.row stat-wheel');
window.addEventListener('scroll', function (event) {
if (isInViewport(findMe)) {
console.log('In viewport!');
} else {
console.log('Nope...');
}
}, false);
JavaScript library to animate elements as they scroll into view.
https://scrollrevealjs.org/

Circular countdown JavaScript from 10 to Zero

I have been trying to reverse the countdown in this demo from 10 down to zero Without luck.
I have tried reversing the countdown by doing this:
(1*(initialOffset/time))-initialOffset )
It did reverse the animated circle but not the countdown.
Any ideas?
Thanks
var time = 10;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h2').text(i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</svg>
</div>
Here is also a codepen copy:
https://codepen.io/kaolay/pen/LRVxKd
Try $('h2').text(time - i); instead of $('h2').text(i);
I also added $('h2').text(time); as the 4th line to draw 10 at the beginning
Also, the first part of the circle is not animated in your code, so I changed this line:
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
To this block:
$('.circle_animation').css('stroke-dashoffset', initialOffset);
setTimeout(() => {
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
})
var time = 10;
var initialOffset = '440';
var i = 1;
$('h2').text(time); // adding 10 at the beginning if needed
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset);
setTimeout(() => {
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
})
var interval = setInterval(function() {
$('h2').text(time - i); // here is the clue
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</svg>
</div>
If you update this line $('h2').text(time - i); then you'll get the numeric countdown. I also initalize i = 0 so that the starting number is 10:
var time = 10;
var initialOffset = '440';
var i = 0
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h2').text(time - i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</svg>
</div>
What exactly are you asking here?
"It did reverse the animated circle but not the countdown."
you are just trying to countdown?
why not set i = 10 and then do i--
If you want to invert the animation just invert all states of initial values and change i to (time-i). So it goes like this:
<div class="item">
<h2>10</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#6fdb6f" fill="none"/>
</svg>
</div>
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 0;
transition: all 1s linear;
}
var time = 10;
var initialOffset = 440;
var i = 0
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', 0);
var interval = setInterval(function() {
$('h2').text(time-i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset*i/time);
i++;
}, 1000);
Code pen:
https://codepen.io/anon/pen/Xybpge

Repeat a function infinite times

How can I repeat the animate function below infinite times? What is the best way to do it?
function animate(count) {
if (count == 0) {
$('.path').css({
'animation': 'draw2 4s'
});
}
if (count == 1) {
$('.path').css({
'animation': 'draw1 4s'
});
}
if (count == 2) {
$('.path').css({
'animation': 'draw3 4s'
});
}
if (count > 0) $('.path:first').one("animationend", function () {
animate(count - 1)
});
}
I think your function can be built in infinitely, Also use switch and cache of jQuery selection:
function animate(count) {
var path = $('.path');
while (true) {
switch (count) {
case 0 :
path.css({
'animation': 'draw2 4s'
});
break;
case 1:
path.css({
'animation': 'draw1 4s'
});
break;
case 2:
path.css({
'animation': 'draw3 4s'
});
break;
default:
path.first().one("animationend", function () {
animate(count - 1)
});
}
}
}
You can do it by using setInterval() function, you need to pass 2 parameters a function and time in Miliseconds to repeat that function,example:
var funcRepeat = animate("something");
var interval = setInterval(funcRepeat,1000);
//This will repeat your function once per second,
// with 500 as value will be twice per second, 250 > 4, etc
If you want to clear the interval, (thats why I stored it in a variable):
clearInterval(interval);
You could also make the funcion inside it:
var interval = setInterval(function(){
// code
},1000);
UPDATE
Looking at your comments, you could simply use recursivity with setTimeout() function:
$(document).ready(function () {
function animate() {
// launch the first animation
$('.path').css({'animation': 'draw2 4s' });
// wait 4s
setTimeout(function(){
// Launch the second animation
$('.path').css({'animation': 'draw1 4s'});
// wait another 4s
setTimeout(function(){
//launch the last one
$('.path').css({'animation': 'draw3 4s'});
// finnaly wait 4s for the last one to complete
// and start again the function using recursivity
setTimeout(animate(),4000);
},4000);
},4000);
}
animate();
});
background-color: #fff;
}
.crosshair {
cursor: crosshair;
}
.bg {
width: 40%;
margin-left: auto;
margin-right: auto;
}
.path {
animation-fill-mode: forwards;
animation-iteration-count: 3;
}
#keyframes draw1 {
0% {
stroke: green;
}
25% {
stroke: green;
}
50% {
stroke: green;
}
75% {
stroke: green;
}
100% {
stroke: green;
fill: none;
stroke-dashoffset: 100;
}
}
#keyframes draw2 {
0% {
stroke: red;
}
25% {
stroke: red;
}
50% {
stroke: red;
}
75% {
stroke: red;
}
100% {
stroke: red;
fill: none;
stroke-dashoffset: 100;
}
}
#keyframes draw3 {
0% {
stroke: blue;
}
25% {
stroke: blue;
}
50% {
stroke: blue;
}
75% {
stroke: blue;
}
100% {
stroke: blue;
fill: none;
stroke-dashoffset: 100;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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" width="612px" height="792px" viewbox="0 0 612 792" enable-background="new 0 0 612 792"
xml:space="preserve">
<path class="path" fill="none" stroke-width="1" stroke-dasharray="550" stroke-dashoffset="550" d="M240,260c0,6.627-5.373,12-12,12h-76c-6.627,0-12-5.373-12-12v-76
c0-6.627,5.373-12,12-12h76c6.627,0,12,5.373,12,12V260z"/>
<path class="path" fill="none" stroke-width="1" stroke-dasharray="550" stroke-dashoffset="550" d="M271,296c0,6.627-5.373,12-12,12h-76c-6.627,0-12-5.373-12-12v-76
c0-6.627,5.373-12,12-12h76c6.627,0,12,5.373,12,12V296z"/>
<path class="path" fill="none" stroke-width="1" stroke-dasharray="550" stroke-dashoffset="550" d="M306,346c0,6.627-5.373,12-12,12h-76c-6.627,0-12-5.373-12-12v-76
c0-6.627,5.373-12,12-12h76c6.627,0,12,5.373,12,12V346z"/>
</svg>
I can do that with an else condition
$('.path:first').one("animationend", function () {
if (count > 0)
animate(count - 1)
else
animate(iterationcount - 1)
})
}

css animation loader to homepage

i'm new to making web stuff so sorry in advance for my newbyness... anyways
Ive created a SVG animation with css,
<svg version="1.1" id="logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 271.25 232.5" style="enable-background:new 0 0 271.25 232.5;" xml:space="preserve">
<defs>
<style type="text/css">
.st0{fill:#fff;stroke:#000000;stroke-width:8;stroke-miterlimit:5;}
.st0 {
stroke-dasharray: 800;
stroke-dashoffset: 0;
-webkit-animation: dash 2s linear forwards;
-o-animation: dash 2s linear forwards;
-moz-animation: dash 2s linear forwards;
animation: dash 2s linear forwards;
}
#logo {
cursor:pointer;
}
#logo:hover .st0{
fill:#000;
transition: .8s;
}
#logo.clickit .st0 {
fill: grey;
stroke: grey;
}
#-webkit-keyframes dash {
from {
stroke-dashoffset: 800;
}
to {
stroke-dashoffset: 0;
}
}
#-moz-keyframes dash {
from {
stroke-dashoffset: 800;
}
to {
stroke-dashoffset: 0;
}
}
#-o-keyframes dash {
from {
stroke-dashoffset: 800;
}
to {
stroke-dashoffset: 0;
}
}
</style>
<script type="text/javascript">
var clicker = document.querySelector('#logo');
clicker.addEventListener('click', function (){
this.classList.toggle('clickit');
});
</script>
</defs>
<path class="st0" d="M14.872,26.016c0.347,1.109,0.539,1.82,0.79,2.511c12.477,34.228,24.958,68.452,37.44,102.679
c10.294,28.223,20.59,56.445,30.883,84.67c0.501,1.373,0.697,2.684,2.854,2.678c30.238-0.082,60.478-0.068,90.716-0.02
c1.515,0.002,2.172-0.516,2.715-1.867c3.9-9.707,7.819-19.406,11.884-29.045c0.846-2.006,0.83-3.67,0.09-5.686
c-18.811-51.182-37.568-102.383-56.285-153.598c-0.636-1.74-1.439-2.373-3.355- 2.369C94.2,26.031,55.798,26.016,17.396,26.016
C16.652,26.016,15.908,26.016,14.872,26.016z M202.77,162.303c18.564-45.643,36.941-90.824,55.349- 136.08
c-35.402,0-70.482,0-105.825,0C169.125,71.6,185.857,116.709,202.77,162.303z"/>
</svg>
Id like to be able to run this animation while my website loads/refreshes but instead the animation plays through and stays onto the page not redirecting to some basic three.js code i was testing...
the index file looks like this...
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<title>TEST</title>
<script src="../build/three.min.js"></script>
<script src="../build/jquery-1.9.0.js"></script>
<meta charset="UTF-8">
<meta name="description" content="coolstuff">
<meta name="keywords" content="Keywords, blah">
<meta name="author" content="My name">
<style>
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div style="text-align:center;padding:150px 0;">
<object>
<embed src="vlogo.svg" width="30%" height="30%">
</object>
</div>
<div id="WebGL-output">
</div>
<script type="text/javascript">
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth /window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
sphereGeometry = new THREE.SphereGeometry(10, 20, 20);
sphereMaterial = new THREE.MeshLambertMaterial({wireframe: true, color: 0x000000});
sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 20;
sphere.position.y = 4;
sphere.position.z = 2;
scene.add(sphere);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = -30;
camera.lookAt(scene.position);
$("#Webgl-output").append(renderer.domElement);
render();
function render(){
sphere.rotation.x += 0.02;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
});
</script>
</body>
</html>
All help is needed - thanks in advance!

Categories