KonvaJS设置默认旋转值后形状跳转原点,如何实现中心旋转?
KonvaJS图形旋转跳转到原点的解决方法
问题描述
用KonvaJS在Canvas中绘制图形,设置默认旋转值45度后,预期图形绕自身中心旋转,但实际图形直接跳到了原点。
相关代码
const [points, setPoints] = useState([ [50, 100], [150, 100], [150, 200], [50, 200] ]); return ( <Fragment> <Line ref={shapRef} points={flatPoints(points)} stroke="#E90000" strokeWidth={1} closed strokeScaleEnabled={false} draggable={true} onDragEnd={handleDragEnd} onTransformEnd={handleTransformEnd} rotation={45} /> </Fragment>
问题图示
解决方法
Konva默认以节点的(0,0)点为旋转中心,直接设置rotation会让图形绕原点旋转。要实现绕自身中心旋转,需手动设置旋转原点(offsetX和offsetY),同时调整图形位置避免偏移。
通用实现代码
import { useEffect, useState, useRef } from 'react'; import { Line, Stage, Layer, Fragment } from 'react-konva'; const flatPoints = (points) => points.flat(); const RotatableShape = () => { const [points, setPoints] = useState([ [50, 100], [150, 100], [150, 200], [50, 200] ]); const shapeRef = useRef(null); useEffect(() => { const shape = shapeRef.current; if (!shape) return; // 获取图形的边界矩形,包含位置和尺寸信息 const rect = shape.getClientRect(); // 计算图形中心相对于自身左上角的偏移量 const centerOffsetX = rect.width / 2; const centerOffsetY = rect.height / 2; // 设置旋转原点为图形中心 shape.offsetX(centerOffsetX); shape.offsetY(centerOffsetY); // 调整图形位置,确保中心与原位置一致 shape.x(rect.x + centerOffsetX); shape.y(rect.y + centerOffsetY); // 强制更新图层渲染 shape.getLayer().batchDraw(); }, [points]); const handleDragEnd = (e) => { // 自定义拖拽结束逻辑 }; const handleTransformEnd = (e) => { // 自定义变换结束逻辑 }; return ( <Fragment> <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> <Line ref={shapeRef} points={flatPoints(points)} stroke="#E90000" strokeWidth={1} closed strokeScaleEnabled={false} draggable={true} onDragEnd={handleDragEnd} onTransformEnd={handleTransformEnd} rotation={45} /> </Layer> </Stage> </Fragment> ); }; export default RotatableShape;
关键逻辑说明
- 获取图形边界:通过
getClientRect()获取图形在画布上的实际位置和尺寸,适用于任意形状的Line节点。 - 设置旋转原点:将
offsetX和offsetY设为图形宽高的一半,让旋转中心落在图形自身中心。 - 调整位置补偿:设置偏移后图形的位置基准会改变,需将
x和y调整为原中心坐标,保证图形不会移位。 - 动态更新:将
points作为useEffect的依赖项,确保图形的点变化后,旋转中心能重新计算适配。
固定形状的简化实现
如果是固定尺寸的矩形,也可以手动计算偏移值,无需依赖getClientRect():
<Line ref={shapeRef} points={flatPoints(points)} stroke="#E90000" strokeWidth={1} closed strokeScaleEnabled={false} draggable={true} onDragEnd={handleDragEnd} onTransformEnd={handleTransformEnd} rotation={45} offsetX={50} // 矩形宽度的一半(150-50=100,100/2=50) offsetY={50} // 矩形高度的一半(200-100=100,100/2=50) x={100} // 原左上角x + offsetX(50+50) y={150} // 原左上角y + offsetY(100+50) />
内容的提问来源于stack exchange,提问作者BachKhoa
相关产品推荐
相关产品推荐



