React Konva如何实现矩形围绕中心物体的旋转/公转动画
实现思路
- 先计算中心矩形的中心点坐标:Konva 中 Rect 的
x/y属性默认为左上角坐标,因此中心点为中心Rect.x + 中心Rect.width/2、中心Rect.y + 中心Rect.height/2 - 基于极坐标公式计算公转矩形的实时位置:以中心矩形的中心点为原点,根据当前旋转角度、公转轨道半径,换算为直角坐标系坐标,再减去公转矩形自身宽高的一半,保证公转矩形的中心点落在轨道上
- 用
requestAnimationFrame实现流畅的帧动画,每帧累加角度值触发重渲染,即可实现公转效果
完整实现代码
import { useState, useRef, useEffect } from 'react'; import { Stage, Layer, Rect } from 'react-konva'; // 这里的Button根据你项目用的UI库替换即可,原生的话直接用<button> import { Button } from 'antd'; export default function OrbitDemo() { // 中心矩形的基础参数 const centerRectConfig = { x: 20, y: 20, width: 50, height: 100, strokeWidth: 2, stroke: "red", fill: "blue" }; // 公转矩形的基础参数 const orbitRectConfig = { width: 50, height: 100, strokeWidth: 2, stroke: "black", fill: "black" }; // 计算中心点坐标 const centerX = centerRectConfig.x + centerRectConfig.width / 2; const centerY = centerRectConfig.y + centerRectConfig.height / 2; // 公转轨道半径,可自行调整 const orbitRadius = 120; const [angle, setAngle] = useState(0); const [isRotating, setIsRotating] = useState(false); const animationRef = useRef(null); const handleRotate = () => { setIsRotating(prev => !prev); }; useEffect(() => { if (isRotating) { const animate = () => { setAngle(prev => { // 每帧角度增量,数值越大公转速度越快,单位为弧度 const newAngle = prev + 0.03; // 超过2π重置为0,避免数值过大 return newAngle >= Math.PI * 2 ? 0 : newAngle; }); animationRef.current = requestAnimationFrame(animate); }; animationRef.current = requestAnimationFrame(animate); } else { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } } // 组件卸载时清除动画避免内存泄漏 return () => { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } }; }, [isRotating]); // 计算公转矩形的实时位置 const orbitX = centerX + orbitRadius * Math.cos(angle) - orbitRectConfig.width / 2; const orbitY = centerY + orbitRadius * Math.sin(angle) - orbitRectConfig.height / 2; // 可选:如果需要公转矩形自身也跟随旋转、始终朝向中心,给下面的Rect加上rotation属性:rotation={angle * 180 / Math.PI} return ( <div> <Stage width={500} height={500}> <Layer> <Rect {...centerRectConfig} opacity={1} /> <Rect {...orbitRectConfig} x={orbitX} y={orbitY} opacity={1} /> </Layer> </Stage> <Button onClick={handleRotate}>{isRotating ? '暂停旋转' : '开始旋转'}</Button> </div> ); }
自定义调整说明
- 修改
orbitRadius的数值可以调整公转轨道的大小 - 修改
animate函数中newAngle = prev + 0.03的增量值可以调整公转速度,数值越大速度越快 - 如果中心矩形位置会动态变化,只要更新
centerRectConfig的x/y值,中心点会自动重新计算,公转轨道也会同步跟随
内容的提问来源于stack exchange,提问作者tanmya
相关产品推荐
相关产品推荐

