Excalidraw概述
Excalidraw是一款开源的在线绘图工具,主要用于白板、思维导图、原型草图设计、流程图等场景。它基于Vite + React + TypeScript + Yarn + Husky的技术栈开发,目前开源star数量已经超过86k,深受开发者喜爱。
tips:体验地址 https://excalidraw.com
功能特点
手绘风格:Excalidraw支持手绘风格的草图设计,使得绘制过程更加自然和亲切。
多种图形元素:支持基本的几何形状如方框、圆、菱形等,并可以绘制连接线。
导出功能:支持将图形内容导出为图片或SVG格式,方便在其他设备上导入编辑。
多人协作:支持多人协同工作,可以通过分享链接让其他人加入同一个白板进行创作。
自定义主题:用户可以自定义主题风格,满足不同的业务场景需求。
场景
Excalidraw可以应用于多种场景,包括但不限于:
草图设计:用于绘制手绘风格的草图。
思维导图和流程图:支持创建复杂的思维导图和流程图。
会议白板:适合在会议中使用,支持激光笔标注等功能。
知识管理:在Obsidian笔记应用中嵌入Excalidraw插件,用于组织和表达复杂信息
在Vue项目中使用React组件
1、 安装vuera库
vuera库地址:https://www.npmjs.com/package/vuera
npm i -S vuera
- 安装依赖
由于我们需要在Vue中使用React组件,所以首先需要在项目中安装React,安装指令如下:
npm install --save react react-dom
3、在Vue中,是无法识别jsx语法的,所以需要安装依赖来识别react-jsx语法,安装指令如下:
npm install @babel/plugin-transform-react-jsx
4、安装完成之后,在babel.config.js文件中添加这个插件即可:
module.exports = {
plugins: ["@babel/plugin-transform-react-jsx"]
};
- 项目配置,接下来在项目中以插件的形式来引入并使用vuera库,我们需要在main.js中加入如下代码:
import { VuePlugin } from 'vuera'
Vue.use(VuePlugin)
依赖包版本
"@babel/plugin-transform-react-jsx": "^7.25.9",
"@excalidraw/excalidraw": "^0.17.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"vue": "^2.6.14",
"vuera": "^0.2.7"
项目源码
<template>
<div class="container">
<div class="excalidraw" id="excalidraw"></div>
</div>
</template>
<script>
import React from "react";
import { createRoot } from "react-dom/client";
import { Excalidraw } from "@excalidraw/excalidraw";
let root = null;
let app = null;
export default {
data() {
return {
appState: {
// 默认的 appState 配置
viewBackgroundColor: "#fff", // 画布背景颜色
currentItemStrokeColor: "#000000", // 当前绘画工具颜色
currentItemBackgroundColor: "#ffffff", // 当前工具填充颜色
activeTool: "selection", // 默认工具为选择工具
zoom: 1, // 缩放比例
},
};
},
mounted() {
// 组件挂载时恢复绘画数据和 appState
this.initializeExcalidraw();
},
unmounted() {
// 组件卸载时销毁 Excalidraw 实例
if (root) {
root.unmount();
}
},
methods: {
initializeExcalidraw() {
const savedElements = localStorage.getItem("excalidrawElements");
const initialData = savedElements
? JSON.parse(savedElements)
: { elements: [], appState: this.appState };
const excalidrawElement = React.createElement(Excalidraw, {
initialData: initialData,
onChange: this.handleDrawingChange,
excalidrawAPI: this.excalidrawAPI,
langCode: "zh-CN",
});
root = createRoot(document.getElementById("excalidraw"));
root.render(excalidrawElement);
},
handleDrawingChange(elements) {
let state = app.getAppState();
let { collaborators, ...appState } = state;
console.log(appState, "appState", collaborators, "collaborators");
// 保存绘画数据
localStorage.setItem(
"excalidrawElements",
JSON.stringify({ elements, appState: appState })
);
},
excalidrawAPI(e) {
app = e;
window.app = e;
},
},
};
</script>
<style scoped>
.container {
width: 100%;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
.header {
height: 3rem;
line-height: 3rem;
padding: 0 1rem;
font-size: 1.2rem;
background-color: #038fe5;
color: white;
}
.footer {
height: 2rem;
line-height: 2rem;
text-align: center;
background-color: #038fe5;
color: white;
}
.excalidraw {
flex-grow: 1; /* 占满剩余空间 */
height: 100%;
}
}
</style>