You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题图示

  • 未旋转的形状
  • 旋转45度后的形状

解决方法

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;

关键逻辑说明

  1. 获取图形边界:通过getClientRect()获取图形在画布上的实际位置和尺寸,适用于任意形状的Line节点。
  2. 设置旋转原点:将offsetX和offsetY设为图形宽高的一半,让旋转中心落在图形自身中心。
  3. 调整位置补偿:设置偏移后图形的位置基准会改变,需将x和y调整为原中心坐标,保证图形不会移位。
  4. 动态更新:将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:43:21