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

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/

Related

How do I make an animation start on scroll down?

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>

React Native Wave Animation: Convert CSS style to JS style

I am trying to achieve something like this for my React Native project.
I have tried using css-to-react-native-transform library to convert CSS to JS but it's been unsuccessful so far.
So any help regarding this issue would be greatly appreciated as I am fairly new with this.
Here is the CSS code:
<style>
.waves {
position: absolute;
bottom: 4.5vh;
width: 100%;
height:15vh;
margin-bottom:-7px; Fix for safari gap
min-height:130px;
max-height:180px;
}
/* Animation */
.parallax > use {
animation: move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite;
}
.parallax > use:nth-child(1) {
animation-delay: -2s;
animation-duration: 7s;
}
.parallax > use:nth-child(2) {
animation-delay: -3s;
animation-duration: 10s;
}
.parallax > use:nth-child(3) {
animation-delay: -4s;
animation-duration: 13s;
}
.parallax > use:nth-child(4) {
animation-delay: -5s;
animation-duration: 20s;
}
#keyframes move-forever {
0% {
transform: translate3d(-90px,0,0);
}
100% {
transform: translate3d(85px,0,0);
}
}
/Shrinking for mobile/
#media (max-width: 768px) {
.waves {
height:70px;
min-height:70px;
}
}
</style>
<!--Waves Container-->
<div>
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(255,255,255,0.7" />
<use xlink:href="#gentle-wave" x="48" y="3" fill="#89c2ee" />
<use xlink:href="#gentle-wave" x="48" y="5" fill="#0379ff" />
<use xlink:href="#gentle-wave" x="48" y="7" fill="#fff" />
</g>
</svg>
</div>
<!--Waves end-->
Here is what I have tried so far on my React Native:
import React from 'react';
import { View, Image, StyleSheet, ImageBackground, Text } from 'react-native';
import { useTheme } from 'react-native-paper';
import { SCREEN_INFO } from './constants';
import transform from "css-to-react-native-transform";
const color = transform(`
.waves {
position: absolute;
bottom: 4.5vh;
width: 100%;
height:15vh;
margin-bottom:-7px;
min-height:130px;
max-height:180px;
}
.parallax > use {
animation: move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite;
}
.parallax > use:nth-child(1) {
animation-delay: -2s;
animation-duration: 7s;
}
.parallax > use:nth-child(2) {
animation-delay: -3s;
animation-duration: 10s;
}
.parallax > use:nth-child(3) {
animation-delay: -4s;
animation-duration: 13s;
}
.parallax > use:nth-child(4) {
animation-delay: -5s;
animation-duration: 20s;
}
#keyframes move-forever {
0% {
transform: translate3d(-90px,0,0);
}
100% {
transform: translate3d(85px,0,0);
}
}
#media (max-width: 768px) {
.waves {
height:70px;
min-height:70px;
}
}
`);
export default function Welcome({ navigation, route }) {
const { colors } = useTheme();
return (
<View
style={styles.flex}
>
<View style={{borderWidth: 2, borderColor: 'red'}}>
<View style={[styles.waves]}/>
<View style={styles.parallax}/>
<Text style={{fontSize: 20, color:'black'}}>Hello</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
flex: {
flex: 1,
},
center: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
}
});

Onclick button to pause and run CSS animation with nested nth-child

I have a working css animation. I meant it to loop through each child changing the background color with keyframes.
I'm attempting to create a button to pause and run the animation on click. What I have so far works only for the parent. I can only run and pause the parent. I can't make it work for the nested nth-child.
I've tried document.querySelector('.animation1 animation1:nth-child(16n +1) animation1:nth-child(16n + 2))', document.querySelectorAll() but to no avail.
I've also attempted document.getElementsByClassName('animation1').classList.add("animation-run");.
var button = document.getElementById('button-ani');
var test_ani = document.getElementsByClassName('animation1');
button.onclick = function() {
test_ani[0].classList.toggle('playani');
}
/*document.getElementsByClassName('animation1').classList.add("animation-run"); */
.animation1 {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay) paused;
}
/* animation-run
.animation-run {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay);
}
*/
/* Without Paused
.animation1 {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay);
}
*/
.playani {
animation-play-state: running;
}
.animation1:hover {
animation: none;
fill: #666;
}
.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;
}
}
<div id="animation1_wrapper">
<button id="button-ani">Toggle Animation Play State</button>
<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>
<path class="animation1" d="M301.26 37.8001V18.8701C300.92 18.7801 300.58 18.6801 300.24 18.6001C287.1 15.3201 275.8 18.2901 266.73 23.3901V37.8001H301.26Z" fill="#f1f1f1"></path>
<path class="animation1" d="M329.15 37.8001C324.38 30.2101 316.5 23.6801 304.54 19.8201V37.8001H329.15Z" fill="#f1f1f1"></path>
----
----
</g>
</svg>
</div>
You can simply use a forEach loop and querySelectorAll method to do animation on all the classes when you click play OR when you click it again the animation will stop on all svg elements
querySelectorAll method return a node list of same class found in the DOM tree and using forEach we can iterate through it all and apply toggle class on found element with that class name
Live Working Demo:
var button = document.getElementById('button-ani');
var test_ani = document.querySelectorAll('.animation1');
button.onclick = function() {
test_ani.forEach(function(ani) {
ani.classList.toggle('playani');
})
}
.animation1 {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay) paused;
}
/* animation-run
.animation-run {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay);
}
*/
/* Without Paused
.animation1 {
--animation-delay: 0.1s;
animation: ani_keyframes 1.8s linear infinite var(--animation-delay);
}
*/
.playani {
animation-play-state: running;
}
.animation1:hover {
animation: none;
fill: #666;
}
.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;
}
}
<div id="animation1_wrapper">
<button id="button-ani">Toggle Animation Play State</button>
<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>
<path class="animation1" d="M301.26 37.8001V18.8701C300.92 18.7801 300.58 18.6801 300.24 18.6001C287.1 15.3201 275.8 18.2901 266.73 23.3901V37.8001H301.26Z" fill="#f1f1f1"></path>
<path class="animation1" d="M329.15 37.8001C324.38 30.2101 316.5 23.6801 304.54 19.8201V37.8001H329.15Z" fill="#f1f1f1"></path>
----
----
</g>
</svg>
</div>

How to add transition from one function to another in JavaScript?

I want to add some smooth transition or animation from the mouse enter event to the mouse leave.
JS :
/* mudar cor do logo maior */
var myImage = document.querySelector('img#logo-maior');
myImage.onmouseenter = function() {
var mySrc = myImage.getAttribute('src');
myImage.setAttribute ('src','images/type-logo-coral.png');
}
myImage.onmouseleave = function() {
var mySrc = myImage.getAttribute('src');
myImage.setAttribute ('src','images/type-logo.png');
}
HTML :
<div class="display">
<img id="modelos" src="images/modelos/1.png">
<img id="logo-maior" src="images/type-logo.png" alt="TYPE logo">
<!--
<button type="button" onclick="displayPreviousImage()">Previous</button>
<button type="button" onclick="displayNextImage()">Next</button>
-->
</div>
Use CSS Animation. Add class for each function that will trigger the animation
Try this code
css
.transition1{
animation: fadeIn1 1.5s;
-webkit-animation: fadeIn1 1.5s; ;
opacity: 1;
}
#keyframes fadeIn1{
from{
opacity: 0;
}
to{
opacity: 1;
}
}
#-webkit-keyframeskeyframes fadeIn1{
from{
opacity: 0;
}
to{
opacity: 1;
}
}
.transition2{
animation: fadeIn2 1.5s;
-webkit-animation: fadeIn2 1.5s; ;
opacity: 1;
}
#-webkit-keyframeskeyframes fadeIn2{
from{
opacity: 0;
}
to{
opacity: 1;
}
}
javascript
var myImage = document.querySelector("img#logo-maior");
myImage.onmouseenter = function() {
myImage.classList.remove("transition2");
myImage.setAttribute("class", "transition1");
myImage.setAttribute("src", "../image2.jpg");
};
myImage.onmouseleave = function() {
myImage.classList.remove("transition1");
myImage.setAttribute("class", "transition2");
myImage.setAttribute("src","../image1.jpg"
);
};
html
<div class="display">
<img
id="logo-maior"
src="../img1.jpg"
alt="TYPE logo"
/>
</div>
In your CSS code:
img:hover {
(whatever styles you want for the hovering effect)
transition: all 0.5s ease-out;
}
For more information on transitions visit: https://developer.mozilla.org/en-US/docs/Web/CSS/transition

How to make the clock appear on the screen after the regressive disappears

I'm trying to make this clock that appears along with the beginning of the countdown only start after the element "GO!" to vanish. I already tried doing it starting after a setInterval of 6 seconds but I did not obtain result.
Please, if there is any way to debug this error even with css I thank you.
var tempo = new Number();
tempo = 180;
function start(){
var number = document.getElementById("number");
number.innerHTML = `<div id="cinco">5</div>
<div id="quatro">4</div>
<div id="tres">3</div>
<div id="dois">2</div>
<div id="um">1</div>
<div id="go">GO!</div>
`
ContagemRegressiva();
}
function ContagemRegressiva(){
if(tempo >= 0){
var minutos = parseInt(tempo / 60);
minutos = (minutos % 60);
var segundos = (tempo % 60);
if(minutos < 10){
minutos = '0' + minutos;
minutos = minutos.substr(0,2); //-->
}
if(segundos < 10){
segundos = '0' + segundos;
}
setTimeout('ContagemRegressiva()',1000);
tempo--;
regressivo.innerHTML = minutos + '<font color=black>:</font>' + segundos;
if((minutos == 00) && (segundos == 00)){
regressivo.innerHTML = minutos + '<font color=black>:</font>' + segundos + '<black></font>';
}
}
}
.container {
text-align: center;
margin: 0 auto;
}
#cinco,
#quatro,
#tres,
#dois,
#um,
#go {
font-size: 0;
animation: .5s ease-in-out 2 forwards alternate zoom;
}
#quatro {
animation-delay: 1s;
}
#tres {
animation-delay: 2s;
}
#dois {
animation-delay: 3s;
}
#um {
animation-delay: 4s;
}
#go {
animation-delay: 5s;
animation-iteration-count: 1;
}
#keyframes zoom {
0% {
font-size: 0;
}
100% {
font-size: 150px;
}
}
#keyframes some {
to {
transform: scale(0);
transform-origin: center top;
}
}
#number {
animation: 0.5s some linear forwards;
animation-delay: 6s;
}
.clock{
position: absolute;
top: 12%;
left: 92%;
transform: translate(-50%, -50%);
font-size: 25px;
color:black;
}
<body onload="start()">
<div id="number" class="container" />
<div class="clock">
<b style="font-size: 10"></b><span id="regressivo"></span></b><br>
</div>
</body>
You can use setTimeout function to call your ContagemRegressiva function.
function start() {
var number = document.getElementById("number");
number.innerHTML = `
<div id="cinco">5</div>
<div id="quatro">4</div>
<div id="tres">3</div>
<div id="dois">2</div>
<div id="um">1</div>
<div id="go">GO!</div>
`;
setTimeout(ContagemRegressiva, 6000);
}
You just need to find the amount of seconds to wait before running the function. I used 6000ms here.
Second way: you can add 'animationend' event to your #go element. When the animation on it ends, 'animationend' event will be fired.
So, you can do this with this code:
function start() {
var number = document.getElementById("number");
number.innerHTML = `
<div id="cinco">5</div>
<div id="quatro">4</div>
<div id="tres">3</div>
<div id="dois">2</div>
<div id="um">1</div>
<div id="go">GO!</div>
`;
var goElem = document.getElementById('go');
goElem.addEventListener('animationend', ContagemRegressiva);
}

Categories