简体   繁体   中英

Convert Javascript animation to CSS animation

Background

The below code adds to a DIV an animation of different sized floating circles.

The animation works well on desktop browsers, however, on an iPad tablet, all it shows is a static image, no animation.


Question

What is preventing the code from animating on tablet compared with desktop?

How do I convert the animation in Java Script to an equivalent CSS animation?


 const colors = ["#000000"]; const numCircles = 50; const circles = []; for (let i = 0; i < numCircles; i++) { let circle = document.createElement("div"); circle.classList.add("circle"); circle.style.background = colors[Math.floor(Math.random() * colors.length)]; circle.style.left = `${Math.floor(Math.random() * 100)}vw`; circle.style.top = `${Math.floor(Math.random() * 100)}vh`; circle.style.transform = `scale(${Math.random()})`; circle.style.width = `${Math.random()}em`; circle.style.height = circle.style.width; circles.push(circle); document.body.append(circle); } circles.forEach((el, i, ra) => { let to = { x: Math.random() * (i % 10 === 0? -10: 10), y: Math.random() * 10 }; let anim = el.animate( [ { transform: "translate(0, 0)" }, { transform: `translate(${to.x}rem, ${to.y}rem)` } ], { duration: (Math.random() + 1) * 2000, direction: "alternate", fill: "both", iterations: Infinity, easing: "ease-in-out" } ); });
 .circle { position: absolute; border-radius: 100%; }.box { height: 500px; width: 500px; border: 5px outset red; text-align: center; }
 <h1>Heading 1</h1> <div class="box"> <h2>Heading 2</h2> <p>This is some text inside a div element.</p> </div> <p>This is some text outside the div element.</p>


Image

在此处输入图像描述

What is preventing the code from animating on tablet compared with desktop?

Your JavaScript code is using Element.animate() which is not currently widely supported by Safari for macOS or Safari for iOS (the minimum version is iOS 13.4, which was only released 2 weeks ago).

How do I convert the animation in Java Script to an equivalent CSS animation?

You'll still need the script to create all of the <div> elements at random positions, but the animate() your code uses can be converted to a declarative CSS animation, like so:

You can run this snippet:

Note that I needed add px and s units to the --to-x , --to-y , and duration values, and I had to disable the circle.style.transform = 'scale' CSSOM rule because they were overriding the declarative CSS (the transform: scale() isn't needed anyway because the circle.style.width / height are also randomized.

 const colors = ["#000000"]; function createCircles( count ) { const circles = []; for (let i = 0; i < count; i++) { const circle = document.createElement("div"); circle.classList.add("circle"); circle.style.background = colors[Math.floor(Math.random() * colors.length)]; circle.style.left = `${Math.floor(Math.random() * 100)}vw`; circle.style.top = `${Math.floor(Math.random() * 100)}vh`; /* circle.style.transform = `scale(${Math.random()})`; <-- This is now disabled */ circle.style.width = `${Math.random()}em`; circle.style.height = circle.style.width; const toX = Math.random() * (i % 10 === 0? -100: 100); const toY = Math.random() * 100; const dur = (Math.random() + 1) * 2; circle.style.setProperty( '--to-x', toX.toFixed(0) + 'px' ); circle.style.setProperty( '--to-y', toY.toFixed(0) + 'px' ); circle.style.setProperty( '--duration', dur.toFixed(2) + 's' ); circles.push(circle); } return circles; } window.addEventListener( 'DOMContentLoaded', setup ); function setup() { const circles = createCircles(50); for( const circle of circles ) { document.body.append( circle ); } }
 .circle { position: absolute; border-radius: 100%; animation-name: myAnimation; animation-duration: var(--duration); animation-direction: alternate; animation-fill-mode: both; animation-iteration-count: infinite; animation-timing-function: ease-in-out; }.box { height: 500px; width: 500px; border: 5px outset red; text-align: center; } @keyframes myAnimation { from { transform: translate( 0, 0 ); } to { transform: translate( var(--to-x), var(--to-y) ); } }
 <h1>Heading 1</h1> <div class="box"> <h2>Heading 2</h2> <p>This is some text inside a div element.</p> </div> <p>This is some text outside the div element.</p>

This also works without any JavaScript if you render the random initial circles into your HTML directly (eg using PHP):

<html>
<head>
</head>
<body>
    <h1>Heading 1</h1>
    <div class="box">
        <h2>Heading 2</h2>
        <p>This is some text inside a div element.</p>
    </div>
    <p>This is some text outside the div element.</p>

<?php for( $i = 0; $i < 50; $i++ ) { ?>
    <div class="circle" style="left: <?= rand( 0, 100 ) ?>px; top: <?= rand( 0, 100 ) ?>px; width: <?= rand( 0, 50 ) ?>px; height: <?= rand( 0, 50 ) ?>px; --to-x: <?= rand( 0, 50 ) ?>px; --to-y: <?= rand( 0, 50 ) ?>px; --duration: <?= rand( 0, 5 ) ?>s;"></div>
<?php endfor; ?>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM