如何在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,提问作者반가우면반갑다고해
相关产品推荐
相关产品推荐

