我正在编写一个React应用程序,其中有一个使用CSS的带有延迟的顺序动画。我正在为SVG中的<path />
元素设置动画。
在手机上[em>(功能不如台式机) ,动画手柄是(似乎)异步附加的。因此,不能保证动画能够完全按预期执行。
/* Elements.pcss file */
.element {
opacity: 0.1;
animation-duration: 1.7s;
animation-iteration-count: infinite;
}
.isAnimated {
@for $i from 1 through $animatedItems {
.element:nth-child($i) {
animation-delay: calc(500ms - ($i * 100ms - 100ms)); /* <--- adding delay */
animation-name: glow$i; /* <--- attaching animation */
}
}
}
以下是我的代码结构的抽象:
Parent.tsx
<Parent>
<Elements /> {/* Renders all animating elements */}
</Parent>
Elements.tsx
import * as styles from "./Elements.pcss";
// ...
export class Elements extends React.PureComponent<{}, { isLoaded: boolean; }> {
public state = {
isLoaded: false,
};
public componentDidMount() {
// The following is a hack to make it work.
// This is not a reliable solution. Thus, I want suggestions
// from smarter people.
setTimeout(() => {
this.setState({
isLoaded: true,
});
}, 2000);
}
public render() {
return (
<div className={{ [styles.isAnimated]: this.state.isLoaded }}>
<div className={styles.element} />
<div className={styles.element} />
<div className={styles.element} />
<div className={styles.element} />
<div className={styles.element} />
<div className={styles.element} />
</div>
);
}
}
答案 0 :(得分:0)
您也许可以使用一个动画和一个元素来组合它。
这是一个主意:
.box {
height:250px;
width:50px;
background:
/*Gradient that we will animate*/
linear-gradient(to bottom,
red 0px,red 30px,
transparent 30px,transparent 50px,
rgba(255,0,0,0.5) 50px, rgba(255,0,0,0.5) 80px,
transparent 80px,transparent 100px,
rgba(255,0,0,0.2) 100px, rgba(255,0,0,0.2) 0)
0 0/100% 130px no-repeat,
/*Bottom gradient*/
repeating-linear-gradient(to bottom,
rgba(255,0,0,0.3) 0px,rgba(255,0,0,0.3) 30px,
transparent 30px,transparent 50px);
animation:change 1s infinite steps(10);
}
@keyframes change {
from {
background-position:0 250px,0 0
}
to {
background-position:0 -250px,0 0;
}
}
<div class="box">
</div>
答案 1 :(得分:0)
Ok, so if anyone stumbles upon this and has a similar problem then the solution for me was completely different from the ones mentioned:
const canvas = document.querySelector("canvas");
const cHeight = 249;
const cWidth = 72;
canvas.height = cHeight;
canvas.width = cWidth;
const ctx = canvas.getContext("2d");
const bW = 72;
const bH = 48;
const fps = 120;
const duration = 1700;
const frameTime = 1000 / fps;
const elementCount = 6;
const startTime = Date.now();
let previousFrame = startTime;
const timings = {
0: [0.1, 0.1, 0.1, 0.1, 0.1, 1.0, 1.0, 1.0, 1.0, 0.5, 0.1],
1: [0.1, 0.1, 0.1, 0.1, 1.0, 0.9, 0.8, 0.5, 0.5, 0.1, 0.1],
2: [0.1, 0.1, 0.1, 1.0, 0.8, 0.7, 0.6, 0.3, 0.1, 0.1, 0.1],
3: [0.1, 0.1, 1.0, 0.6, 0.4, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
4: [0.1, 1.0, 0.5, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
5: [1.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
};
const timingFunction = (animationTime, animationLength, timing) => {
// How many steps there are in timing definition, we count spaces not steps
const positions = timing.length - 1;
const stepSize = animationLength / positions; // How long time is for each step
// For which step to take values
const animationStep = Math.floor(animationTime / stepSize);
// How much time is elapsed in step
const minMaxTimingDelta = timing[animationStep + 1] - timing[animationStep];
const timingAddition = timing[animationStep];
const timeInStep = animationTime % stepSize;
// Coificient to multiply max value with
const coefficient = timeInStep / stepSize;
const timingCoefficient = coefficient * minMaxTimingDelta;
return timingAddition + timingCoefficient;
};
function drawElement(animationTime) {
ctx.clearRect(0, 0, cWidth, cHeight)
const min = 0;
const max = 1;
const delay = 700;
const inDelay = animationTime < delay;
const newAnimTime = duration - delay;
for (let i = 0; i < elementCount; i++) {
const alpha = inDelay ? 0.1 : timingFunction(
animationTime - delay,
newAnimTime,
timings[i],
min,
max,
)
ctx.globalAlpha = alpha;
ctx.fillStyle = 'green';
ctx.fillRect(0, i * (bH + 3), bW, bH);
}
}
const animate = () => {
if (Date.now() - previousFrame > frameTime) {
previousFrame = Date.now();
drawElement((previousFrame - startTime) % duration);
}
requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
body {
height: 100%;
width: 100%;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
.1 {
opacity: .9;
background-color: blue;
width: 50px;
height: 50px;
border: 1px solid red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<canvas />
</body>
</html>
Adding CSS animations with or without delays don't guarantee that all animations will initialise at the same time and thus be "synchronous".