使用 React 和 Konva 实现一个在线画板组件

news2025/5/12 6:48:09

文章目录

  • 一、前言
  • 二、Konva.js 介绍
  • 三、创建 React 画板项目
    • 3.1 安装依赖
    • 3.2 创建 `CanvasBoard` 组件
  • 四、增加画布控制功能
    • 4.1 清空画布
    • 4.2 撤销 & 重做功能
  • 五、增加颜色和画笔大小选择
    • 5.1 选择颜色
    • 5.2 选择画笔大小
  • 六、最终效果
  • 七、总结

一、前言

在线画板是许多应用(如白板协作工具、手写笔记、绘图软件)中的重要组件。我们可以使用 React + Konva.js 结合 react-konva 来实现一个功能丰富的画板。

本教程将带你实现一个支持 自由绘制、清空画布、撤销/重做 的 React 画板组件。


二、Konva.js 介绍

Konva.js 是一个基于 Canvas API 的 2D 图形库,支持高性能的绘图操作,如路径、形状、文本、图片等。它具有以下优点:

  • 更高性能:相比 DOM 操作,Canvas 渲染更加流畅;
  • 提供丰富的图形 API(直线、多边形、贝塞尔曲线等);
  • 支持事件监听,如 clickdragtouch 等。

react-konva 是 Konva.js 的 React 封装库,使其可以在 React 中更方便地使用。


三、创建 React 画板项目

3.1 安装依赖

在 React 项目中,安装 react-konvakonva

{bash}
npm install react-konva konva
{bash}


3.2 创建 CanvasBoard 组件

新建 CanvasBoard.js,并使用 react-konva 组件创建一个可绘制的 Canvas。

// CanvasBoard.js
import React, { useRef, useState } from "react";
import { Stage, Layer, Line } from "react-konva";

const CanvasBoard = () => {
  const [lines, setLines] = useState([]);
  const [isDrawing, setIsDrawing] = useState(false);
  const stageRef = useRef(null);

  // 开始绘制
  const handleMouseDown = (event) => {
    setIsDrawing(true);
    const { x, y } = event.target.getStage().getPointerPosition();
    setLines([...lines, { points: [x, y] }]);
  };

  // 画线
  const handleMouseMove = (event) => {
    if (!isDrawing) return;
    const { x, y } = event.target.getStage().getPointerPosition();
    const newLines = [...lines];
    newLines[newLines.length - 1].points.push(x, y);
    setLines(newLines);
  };

  // 结束绘制
  const handleMouseUp = () => {
    setIsDrawing(false);
  };

  return (
    <div>
      <Stage
        width={800}
        height={500}
        ref={stageRef}
        onMouseDown={handleMouseDown}
        onMousemove={handleMouseMove}
        onMouseup={handleMouseUp}
        style={{ border: "1px solid #ccc", background: "#fff" }}
      >
        <Layer>
          {lines.map((line, index) => (
            <Line key={index} points={line.points} stroke="black" strokeWidth={3} tension={0.5} lineCap="round" />
          ))}
        </Layer>
      </Stage>
    </div>
  );
};

export default CanvasBoard;

四、增加画布控制功能

4.1 清空画布

我们可以添加一个“清空”按钮,点击后清除所有线条。

const handleClearCanvas = () => {
  setLines([]);
};
{javascript}

并在 `CanvasBoard` 组件中添加按钮:

{javascript}
<button onClick={handleClearCanvas}>清空画布</button>

4.2 撤销 & 重做功能

为了实现 撤销/重做,我们需要一个状态栈来存储历史操作。

修改 CanvasBoard.js

const [history, setHistory] = useState([]);
const [redoStack, setRedoStack] = useState([]);

const handleUndo = () => {
  if (lines.length > 0) {
    setRedoStack([...redoStack, lines[lines.length - 1]]);
    setLines(lines.slice(0, -1));
  }
};

const handleRedo = () => {
  if (redoStack.length > 0) {
    setLines([...lines, redoStack[redoStack.length - 1]]);
    setRedoStack(redoStack.slice(0, -1));
  }
};

并在 CanvasBoard 组件中添加按钮:

<button onClick={handleUndo}>撤销</button>
<button onClick={handleRedo}>重做</button>

五、增加颜色和画笔大小选择

我们可以添加选择颜色和画笔大小的功能,使画板更丰富。

5.1 选择颜色

CanvasBoard.js 中添加颜色选择器:

const [color, setColor] = useState("black");

<input type="color" value={color} onChange={(e) => setColor(e.target.value)} />

并修改 Line 组件,让它支持动态颜色:

<Line key={index} points={line.points} stroke={line.color || "black"} strokeWidth={3} />
{javascript}

当鼠标按下时,将颜色存入 `lines`{javascript}
setLines([...lines, { points: [x, y], color }]);

5.2 选择画笔大小

CanvasBoard.js 添加画笔大小选择器:

const [strokeWidth, setStrokeWidth] = useState(3);

<input type="range" min="1" max="10" value={strokeWidth} onChange={(e) => setStrokeWidth(e.target.value)} />
{javascript}

修改 `Line` 组件,让它支持动态画笔大小:

{javascript}
<Line key={index} points={line.points} stroke={line.color || "black"} strokeWidth={line.strokeWidth || 3} />

当鼠标按下时,将 strokeWidth 存入 lines

setLines([...lines, { points: [x, y], color, strokeWidth }]);

六、最终效果

最终,我们的在线画板具备以下功能:
✅ 支持自由绘制
✅ 支持清空画布
✅ 支持撤销/重做
✅ 支持颜色选择
✅ 支持画笔大小调整

你可以将 CanvasBoard 组件导入 App.js 进行测试:

// App.js
import React from "react";
import CanvasBoard from "./CanvasBoard";

function App() {
  return (
    <div className="App">
      <h1>React 画板</h1>
      <CanvasBoard />
    </div>
  );
}

export default App;

七、总结

本篇文章介绍了如何使用 React + Konva 实现一个 在线画板组件,并添加了 撤销/重做、颜色选择、画笔大小调整 等功能。Konva 提供了高效的 Canvas API,使得 React 处理复杂的绘图操作变得更加轻松。

你可以在此基础上继续扩展,比如:

  • 添加橡皮擦功能
  • 支持图像导入与导出
  • 多人协作(结合 WebSocket)

到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2328879.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NVR接入录像回放平台EasyCVR视频系统守护舌尖上的安全,打造“明厨亮灶”云监管平台

一、方案背景 近年来&#xff0c;餐饮行业食品安全和卫生等问题频发&#xff0c;比如后厨卫生脏乱差等&#xff0c;持续引发关注&#xff0c;这些事情导致连锁反应&#xff0c;使其收益遭受损失。同时&#xff0c;给消费者造成了心理和生理上的伤害。 加强餐饮行业的监管成为…

Cribl 导入文件来检查pipeline 的设定规则(eval 等)

Cribl 导入文件来检查pipeline 的设定规则(eval 等) 从这个页面先下载,或者copy 内容来创建pipeline: Reducing Windows XML Events | Cribl Docs

一周学会Pandas2 Python数据处理与分析-Jupyter Notebook安装

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Jupyter (Project Jupyter | Home&#xff09;项目是一个非营利性开源项目&#xff0c;于2014年由IPython项目中诞生…

deepseek v3-0324 Markdown 编辑器 HTML

Markdown 编辑器 HTML 以下是一个美观的 Markdown 编辑器 HTML 页面&#xff0c;支持多种主题切换和实时预览功能&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&q…

视频设备轨迹回放平台EasyCVR如何搭建公共娱乐场所远程视频监控系统

一、背景介绍 由于KTV、酒吧、足疗店等服务场所人员流动频繁、环境复杂&#xff0c;一直是治安管理的重点区域。为有效打击 “黄赌毒”、打架斗殴、寻衅滋事等违法犯罪的活动&#xff0c;打造安全有序的娱乐消费环境&#xff0c;我国相关部门将加大对这类场所的清查与管控力度…

网络安全基础知识总结

什么是网络安全 采取必要措施&#xff0c;来防范对网络的攻击&#xff0c;侵入&#xff0c;干扰&#xff0c;破坏和非法使用&#xff0c;以及防范一些意外事故&#xff0c;使得网络处于稳定可靠运行的状态&#xff0c;保障网络数据的完整性、保密性、可用性的能力(CIA)。 举例…

【工具】在 Visual Studio 中使用 Dotfuscator 对“C# 类库(DLL)或应用程序(EXE)”进行混淆

在 Visual Studio 中使用 Dotfuscator 进行混淆 Dotfuscator 是 Visual Studio 自带的混淆工具&#xff08;Dotfuscator Community Edition&#xff0c;简称 CE&#xff09;。它可以混淆 C# 类库&#xff08;DLL&#xff09;或应用程序&#xff08;EXE&#xff09;&#xff0c…

积分赛——获取环境温度

设计要求 从DS18B20温度传感器上获取环境温度&#xff0c;并将其温度值显示到数码管上&#xff08;保留两位小数&#xff09;。 当“S4”定义为发送按键&#xff0c;按键S4按下时&#xff0c;串口向PC端发送当前采集的温度值&#xff1b; 串口发送格式&#xff1a; Temp:26.…

Xilinx系列FPGA实现HDMI2.1视频收发,支持8K@60Hz分辨率,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我已有的4K/8K视频处理解决方案我已有的FPGA图像处理方案 3、详细设计方案设计框图硬件设计架构本HDMI2.1性能参数8K视频输入源Video PHY ControllerHDMI 2.1 Receive…

如何把网页文章转为pdf保存

fnF12调出右边网页端的控制台 在下面输入代码 1、转CSDN上的文章 (function(){ use strict;var articleBox $("div.article_content");articleBox.removeAttr("style");var head_str ""; var foot_str ""; var olde…

自然语言处理|如何用少样本技术提升低资源语言处理?

一、引言 在全球化的背景下&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术取得了显著进展&#xff0c;为人们的生活和工作提供了便利。然而&#xff0c;大多数 NLP 研究和应用集中在少数高资源语言上&#xff0c;如英语和中文。据统计&#xff0c;全球存在超过 700…

系统安全——文件监控-FileMonitor

namespace FileSystemWatcherDemo {public partial class Form1 : Form{ public Form1(){InitializeComponent();UsingFileSystemWatcher();} /// <summary>/// 使用FileSystemWatcher方法/// </summary>void UsingFileSystemWatcher(){//6.2//FileSystemWa…

07-01-自考数据结构(20331)- 排序-内部排序知识点

内部排序算法是数据结构核心内容,主要包括插入类(直接插入、希尔)、交换类(冒泡、快速)、选择类(简单选择、堆)、归并和基数五大类排序方法。 知识拓扑 知识点介绍 直接插入排序 定义:将每个待排序元素插入到已排序序列的适当位置 算法步骤: 从第二个元素开始遍历…

【AI学习】MCP的简单快速理解

最近&#xff0c;AI界最火热的恐怕就是MCP了。作为一个新的知识点&#xff0c;学习的开始&#xff0c;先摘录一些信息&#xff0c;从发展历程、通俗介绍到具体案例&#xff0c;这样可以快速理解MCP。 MCP发展历程 来自i陆三金 Anthropic 开发者关系负责人 Alex Albert&#…

单机快速部署开源、免费的分布式任务调度系统——DolphinScheduler

看了DolphinScheduler的介绍&#xff0c;不知道有没有引起你的兴趣&#xff0c;有没有想要上手体验一番呢。本文则主要为大家介绍DolphinScheduler的单机部署方式&#xff0c;方便大家快速体验。 环境准备 需要Java环境&#xff0c;这是一个老生常谈的问题&#xff0c;关于Ja…

【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器

今天我们将使用FastAPI来构建 MCP 服务器&#xff0c;Anthropic 推出的这个MCP 协议&#xff0c;目的是让 AI 代理和你的应用程序之间的对话变得更顺畅、更清晰。FastAPI 基于 Starlette 和 Uvicorn&#xff0c;采用异步编程模型&#xff0c;可轻松处理高并发请求&#xff0c;尤…

springcloud configClient获取configServer信息失败导致启动configClient注入失败报错解决

目录 一、问题现象 二、解决方案 三、运行结果 四、代码地址 一、问题现象 springcloud configClient获取configServer信息失败导致启动configClient注入失败 报错堆栈信息 org.springframework.beans.factory.BeanCreationException: Error creating bean with name scop…

HarmonyOS-ArkUI Rcp模块类关系梳理

前言 本文重点解决的是&#xff0c;按照官网学习路径学习Tcp模块内容时&#xff0c;越看越混乱的问题。仿照官网案例&#xff0c;书写代码时&#xff0c;产生的各种疑惑。比如&#xff0c;类与类之间的关系&#xff0c;各种配置信息究竟有多少&#xff0c;为什么越写越混乱。那…

26考研——线性表_ 线性表的链式表示_双循环链表(2)

408答疑 文章目录 三、 线性表的链式表示双循环链表单链表与双链表的比较单链表的特点双链表的特点 双链表上基本操作的实现双链表的插入操作双链表的删除操作 双链表的代码实操定义结点创建一个结点带头结点的双链表初始化创建双链表打印双链表查找结点插入结点在指定节点后插…

基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 这些年随着Internet的迅速发展&#xff0c;我们国家和世界都已经进入了互联网大数据时代&#xff0c;计算机网络已经成为了整个社会以及经济发展的巨大动能&#xff0c;考研成绩查询管理事务现在已经成为社会关注的重要内容&#xff0c;因此运用互联网技术来提高考研成绩…