在 React 项目中实现小球动画
效果大概是这样的

实现思路
总体思路
将小球封装成一个组件,这个组件有半径、移动速度、颜色等属性
然后再随机生成一堆小球
实际的代码
单个小球
这是一个类组件
Ball.js
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 
 | import React, { Component } from "react";import "./Ball.css";
 export default class Ball extends Component {
 constructor(props) {
 super(props);
 this.state = {
 radius: props.radius || 100,
 left: props.left || 0,
 top: props.top || 0,
 xSpeed: props.xSpeed,
 ySpeed: props.ySpeed,
 bg: props.bg || "#f307",
 };
 const duration = 16;
 
 setInterval(() => {
 
 const xDis = (this.state.xSpeed * duration) / 1000;
 const yDis = (this.state.ySpeed * duration) / 1000;
 let newLeft = this.state.left + xDis;
 let newTop = this.state.top + yDis;
 
 if (newLeft <= 0) {
 newLeft = 0;
 this.setState({
 xSpeed: -this.state.xSpeed,
 });
 
 } else if (
 newLeft >=
 document.documentElement.clientWidth - this.state.radius
 ) {
 newLeft = document.documentElement.clientWidth - this.state.radius;
 this.setState({
 xSpeed: -this.state.xSpeed,
 });
 }
 
 if (newTop <= 0) {
 newTop = 0;
 this.setState({
 ySpeed: -this.state.ySpeed,
 });
 
 } else if (
 newTop >=
 document.documentElement.clientHeight - this.state.radius
 ) {
 newTop = document.documentElement.clientHeight - this.state.radius;
 this.setState({
 ySpeed: -this.state.ySpeed,
 });
 }
 this.setState({
 left: newLeft,
 top: newTop,
 });
 }, duration);
 
 }
 render() {
 return (
 <div
 className="ball"
 style={{
 width: this.state.radius + "px",
 height: this.state.radius + "px",
 left: this.state.left + "px",
 top: this.state.top + "px",
 backgroundColor: this.state.bg,
 }}
 ></div>
 );
 }
 }
 
 | 
ps:这里 css 只加了 fixed 定位和圆角样式
这样就实现了一个小球在视口之内跳动

最重要的这步完成了,然后就是生成一堆的小球了
这边也封装成了一个 List 类组件
BallList.js
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 
 | import React, { Component } from "react";import Ball from "./Ball";
 import { getRandomNumber } from "../utils/Random";
 export default class BallList extends Component {
 constructor(props) {
 super(props);
 this.state = {
 ballInfos: [],
 };
 const interval = 1000;
 const timer = setInterval(() => {
 const info = {
 radius: getRandomNumber(50, 200),
 left: getRandomNumber(
 0,
 document.documentElement.clientWidth - this.radius
 ),
 top: getRandomNumber(
 0,
 document.documentElement.clientHeight - this.radius
 ),
 xSpeed: getRandomNumber(50, 500),
 ySpeed: getRandomNumber(50, 500),
 bg: `rgb(
 ${getRandomNumber(0, 255)},
 ${getRandomNumber(0, 255)},
 ${getRandomNumber(0, 255)})`,
 };
 this.setState({
 ballInfos: [...this.state.ballInfos, info],
 });
 console.log(this.state.ballInfos.length);
 if (this.state.ballInfos.length >= 15) clearInterval(timer);
 }, interval);
 }
 render() {
 const balls = this.state.ballInfos.map((item, i) => (
 <Ball key={i} {...item} />
 ));
 return <>{balls}</>;
 }
 }
 
 | 
这个里面用到的工具类就是一个获取随机数函数
| 12
 3
 
 | export function getRandomNumber(min, max) {return Math.floor(Math.random() * (max + 1 - min) + min);
 }
 
 |