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

如何在react-konva中将画布内容以JSON形式上传至服务器并加载

React-Konva 画布JSON的保存与还原实现

一、将画布JSON保存到服务器

给Stage添加ref,调用toJSON()获取画布结构数据,再通过接口发送到服务器存储即可。

代码示例

import { useState, useRef } from 'react';
import { Stage, Layer, Text, Image } from 'react-konva';

export default function Canvas() {
  const stageRef = useRef(null);

  // 保存画布数据到服务器
  const saveCanvas = async () => {
    // 获取画布JSON,默认包含所有节点的关键属性(位置、内容、类型等)
    const canvasJSON = stageRef.current.toJSON();
    try {
      await fetch('/api/save-canvas', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ canvasData: canvasJSON })
      });
      console.log('画布数据已保存');
    } catch (err) {
      console.error('保存失败:', err);
    }
  };

  return (
    <div>
      <button onClick={saveCanvas}>保存画布</button>
      <Stage ref={stageRef} width={800} height={600}>
        <Layer>
          {/* 你的文本、贴纸组件示例 */}
          <Text text="自定义文本" x={50} y={50} fontSize={28} fill="#333" />
          <Image x={150} y={100} width={120} height={120} image={yourStickerImage} />
        </Layer>
      </Stage>
    </div>
  );
}

二、从服务器加载JSON并还原画布

从服务器获取保存的JSON后,根据JSON中节点的className字段(如Text、Image),映射到对应的React-Konva组件,动态渲染节点即可还原画布。

代码示例

import { useState, useRef, useEffect } from 'react';
import { Stage, Layer, Text, Image } from 'react-konva';

// 节点类型映射表:将JSON中的类名对应到React-Konva组件
const NodeComponentMap = {
  Text,
  Image,
  // 若使用了其他组件(如Rect、Circle),在此添加映射
};

export default function Canvas() {
  const stageRef = useRef(null);
  const [savedCanvasData, setSavedCanvasData] = useState(null);

  // 从服务器加载画布数据
  const loadCanvas = async () => {
    try {
      const res = await fetch('/api/get-canvas');
      const data = await res.json();
      setSavedCanvasData(data.canvasData);
      console.log('画布数据已加载');
    } catch (err) {
      console.error('加载失败:', err);
    }
  };

  // 动态渲染画布节点
  const renderCanvasNodes = () => {
    if (!savedCanvasData) return null;
    // 取第一个Layer下的所有子节点(根据你的画布结构调整)
    const nodes = savedCanvasData.layers[0].children;
    return nodes.map((node, idx) => {
      const Component = NodeComponentMap[node.className];
      if (!Component) return null;
      
      // 处理Image组件的图片资源:JSON中存的是图片src,需转为Image对象
      const nodeProps = { ...node, key: idx };
      if (node.className === 'Image') {
        const img = new Image();
        img.src = node.image.src;
        nodeProps.image = img;
      }
      
      return <Component {...nodeProps} />;
    });
  };

  return (
    <div>
      <button onClick={loadCanvas}>加载画布</button>
      <Stage ref={stageRef} width={800} height={600}>
        <Layer>
          {savedCanvasData ? renderCanvasNodes() : (
            <Text text="点击加载已保存的画布" x={50} y={50} fontSize={24} />
          )}
        </Layer>
      </Stage>
    </div>
  );
}

关键注意事项

  • 贴纸图片优化:如果贴纸是本地图片,toJSON()会将其转为base64导致JSON体积变大,建议先将贴纸图片上传到服务器,JSON中只存储图片URL,还原时直接加载该URL。
  • 自定义组件支持:若使用了自定义Konva组件,只需在NodeComponentMap中添加对应的类名-组件映射即可。
  • 服务器端处理:服务器只需将接收到的JSON数据存储到数据库(如MongoDB、MySQL),加载时直接返回该JSON即可,无需额外处理。

内容的提问来源于stack exchange,提问作者반가우면반갑다고해

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 21:45:00