在 React 项目中实现小球动画
效果大概是这样的
实现思路
总体思路
将小球封装成一个组件,这个组件有半径、移动速度、颜色等属性
然后再随机生成一堆小球
实际的代码
单个小球
这是一个类组件
Ball.js
1 2 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
1 2 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}</>; } }
|
这个里面用到的工具类就是一个获取随机数函数
1 2 3
| export function getRandomNumber(min, max) { return Math.floor(Math.random() * (max + 1 - min) + min); }
|