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

在React JS中如何使用react-konva通过onClick事件绘制图形?

React-Konva 鼠标交互绘制图形实现方案

核心实现逻辑

基于Konva画布的鼠标生命周期事件,配合React状态管理记录绘制过程中的坐标数据,实时更新临时图形的渲染参数,拖拽结束后将最终图形存入已完成列表即可。

具体实现步骤

  • 初始化状态:声明四个核心状态:isDrawing(布尔值,标记是否处于拖拽绘制状态)、startPoint(记录鼠标按下时的画布坐标)、currentShape(存储正在绘制的临时图形参数)、shapes(存储所有已完成绘制的图形数据列表)
  • 监听Stage画布的三个核心鼠标事件:
    1. onMouseDown:鼠标按下时触发,将isDrawing设为true,记录当前画布坐标为起始点,初始化临时图形的基础参数
    2. onMouseMove:鼠标移动时触发,仅当isDrawing为true时执行逻辑,计算当前坐标和起始坐标的差值,动态更新临时图形的尺寸、位置参数
    3. onMouseUp/onMouseLeave:鼠标抬起或移出画布时触发,将临时图形参数存入已完成图形列表,重置所有绘制状态
  • 渲染图形:遍历shapes数组渲染所有已完成的图形,额外单独渲染currentShape临时图形,实现拖拽过程中的实时预览效果
    注意要调用Stage实例的getPointerPosition()方法获取坐标,不要直接使用浏览器原生事件的clientX/clientY,避免画布存在偏移、缩放时坐标计算错误

矩形绘制参考代码

import { useState } from 'react';
import { Stage, Layer, Rect } from 'react-konva';

function DrawApp() {
  const [isDrawing, setIsDrawing] = useState(false);
  const [startPoint, setStartPoint] = useState({ x: 0, y: 0 });
  const [currentRect, setCurrentRect] = useState(null);
  const [rects, setRects] = useState([]);

  const handleMouseDown = (e) => {
    setIsDrawing(true);
    const { x, y } = e.target.getStage().getPointerPosition();
    setStartPoint({ x, y });
    setCurrentRect({ x, y, width: 0, height: 0 });
  };

  const handleMouseMove = (e) => {
    if (!isDrawing) return;
    const { x, y } = e.target.getStage().getPointerPosition();
    // 处理拖拽方向为左上时的坐标翻转问题
    setCurrentRect({
      x: Math.min(startPoint.x, x),
      y: Math.min(startPoint.y, y),
      width: Math.abs(x - startPoint.x),
      height: Math.abs(y - startPoint.y),
    });
  };

  const handleMouseUp = () => {
    if (!isDrawing) return;
    setRects([...rects, currentRect]);
    setIsDrawing(false);
    setCurrentRect(null);
  };

  return (
    <Stage
      width={window.innerWidth}
      height={window.innerHeight}
      onMouseDown={handleMouseDown}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
      onMouseLeave={handleMouseUp}
    >
      <Layer>
        {/* 渲染所有已完成的矩形 */}
        {rects.map((rect, i) => (
          <Rect key={i} {...rect} fill="transparent" stroke="black" strokeWidth={2} />
        ))}
        {/* 渲染正在绘制的临时矩形 */}
        {currentRect && <Rect {...currentRect} fill="transparent" stroke="black" strokeWidth={2} />}
      </Layer>
    </Stage>
  );
}

export default DrawApp;

扩展说明

  • 如果需要绘制圆形、直线、多边形等其他图形,仅需修改状态存储的图形参数,以及对应渲染的Konva组件即可,整体交互逻辑和矩形绘制完全一致
  • 如果需要支持选中、编辑已绘制的图形,可以给每个图形绑定onTransform等事件配合Transformer组件实现

内容的提问来源于stack exchange,提问作者Namya LG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 22:54:03