Excalidraw手写体画图工具
Excalidraw手写体画图工具
cmyang1. Excalidraw
一款开源的虚拟手绘风格白板。
- Github:https://github.com/excalidraw/excalidraw
- 在线画图:https://excalidraw.com/
- plus版本:https://plus.excalidraw.com/
2. 特点
- 💯 免费且开源。
- 🎨 无限的、基于画布的白板。
- ✍️类似手绘的风格。
- 🌓 黑暗模式。
- 🏗️可定制。
- 📷 图片支持。
- 😀 形状库支持。
- 👅 本地化(i18n)支持。
- 🖼️ 导出为 PNG、SVG 和剪贴板。
- 💾 开放格式 - 将图纸导出为
.excalidraw
json 文件。 - ⚒️ 多种工具 - 矩形、圆形、菱形、箭头、线条、自由绘制、橡皮擦…
- ➡️ 箭头绑定和标记箭头。
- 🔙 撤消/重做。
- 🔍 缩放和平移支持。
3. 自定义字体-单字体
Excalidraw本身只支持英文的手写体,画图中的中文不是手写体的格式。
所以中文手写体需要二次处理查阅资料,一般有两种方式。一种直接改代码加入字体,自己部署服务,例外一种直接访问官方的画图地址,通过工具拦截修改请求的方式来加载中文字体。各有各的优势,第一种部署自己的服务安全,字体可以任意加多种,用户不需要额外的操作成本,第二种简单,适合自己使用,这里以第一种修改代码的方式
为什么要这样设置单字体
之前写笔记都是用云笔记,后来使用typora,但是都有各种局限性,最近使用找到一个md的编辑器Obsidian,试用后比较好用,准备以后用这个
Obsidian有强大的插件功能,其中就有Excalidraw的插件obsidian-excalidraw-plugin,可以自定义字体
目前这个字体只能设置一个,通过导出文件,查看文件的配置,该字体字体配置的fontFamily字段值为4,所以想要在excalidraw官网和Obsidian插件中自定义中文字体同时生效,就需要设置一样
3.1 下载字体
经过实际测试比较,发现沐瑶软笔手写体比较好用
3.2 修改源代码
从github拉去源码:https://github.com/excalidraw/excalidraw
涉及修改的文件
- Muyao-Softbrush.ttf
- public/fonts/fonts.css
- packages/excalidraw/constants.ts
- packages/excalidraw/actions/actionProperties.tsx
实施步骤
Muyao-Softbrush.ttf复制字体到
public/fonts/
修改
public/fonts/fonts.css
1
2
3
4
5@font-face {
font-family: "Muyao";
src: url("Muyao-Softbrush.ttf");
font-display: swap;
}修改
packages/excalidraw/constants.ts
1
2
3
4
5
6
7export const FONT_FAMILY = {
Virgil: 1,
Helvetica: 2,
Cascadia: 3,
Assistant: 0,
Muyao: 4,
};修改
packages/excalidraw/actions/actionProperties.tsx
1
2
3
4
5
6{
value: FONT_FAMILY.Muyao,
text: "沐瑶软笔",
icon: FreedrawIcon,
testId: "font-family-virgil",
},
4. 自定义字体-多字体
此方法适用于想要设置多个中文自定义手写体
4.1 下载字体
猫啃是一个专注于免费商用字体的网站,包含了几百字免费中文字体,从该网站下载自己喜欢的字体。这里下载两个字体,云峰寒蝉体,云峰飞云体
下载完字体后,文件中文名改为英文名称,云峰寒蝉体.ttf
g改为YunFengHanChanTi.ttf
,云峰飞云体.ttf
改为YunFengFeiYunTi.ttf
4.2 修改代码
从github拉去源码:https://github.com/excalidraw/excalidraw
涉及修改的文件
- public/fonts/fonts.css
- packages/excalidraw/index-node.ts
- excalidraw-app/index.html
- packages/excalidraw/constants.ts
- packages/excalidraw/actions/actionProperties.tsx
具体步骤
- 复制字体到
public/fonts/
修改fonts.css
1
2
3
4
5
6
7
8
9
10@font-face {
font-family: "YunFengHanChanTi";
src: url("YunFengHanChanTi.ttf");
font-display: swap;
}
@font-face {
font-family: "YunFengFeiYunTi";
src: url("YunFengFeiYunTi.ttf");
font-display: swap;
}修改index-node.ts
1
2registerFont("./public/fonts/YunFengHanChanTi.ttf", { family: "YunFengHanChanTi" });
registerFont("./public/fonts/YunFengFeiYunTi.ttf", { family: "SlidexiaxingRegular" });修改index.html,预加载字体,提高启动速度
1
2
3
4
5
6
7
8
9
10
11
12
13
14<link
rel="preload"
href="/fonts/YunFengHanChanTi.ttf"
as="font"
type="font/ttf"
crossorigin="anonymous"
/>
<link
rel="preload"
href="/fonts/YunFengFeiYunTi.ttf"
as="font"
type="font/ttf"
crossorigin="anonymous"
/>修改constants.ts
1
2YunFengHanChanTi: 5,
YunFengFeiYunTi: 6,修改actionProperties.tsx
1
2
3
4
5
6
7
8
9
10
11
12{
value: FONT_FAMILY.YunFengHanChanTi,
text: t("labels.handDrawn"),
icon: FreedrawIcon,
testId: "font-family-virgil",
},
{
value: FONT_FAMILY.YunFengFeiYunTi,
text: t("labels.handDrawn"),
icon: FreedrawIcon,
testId: "font-family-virgil",
},
5. 启动服务
打开终端,执行以下命令
1 | yarn |
打开浏览器:http://localhost:3000/
字体上已经多了两个手写体按钮
输入中文
6. 分享
6.1 前提
- 分享只能通过localhost,127.0.0.1,或者https访问
- 依赖excalidraw-room服务
6.2 部署excalidraw-room
1 | docker run --rm -d --name excalidraw-room -p 9071:80 excalidraw/excalidraw-room:latest |
7. Nginx静态文件部署
7.1 修改打包配置
- 修改package.json
1 | "build:app": "yarn --cwd ./excalidraw-app build:app", |
- 修改vite.config.mts
1 | base: "/excalidraw/", |
7.2 打包静态文件
- 在项目的根目录下执行
yarn build
- 构建完成后,可以看到excalidraw-app目录下生成了一个build文件夹,该文件夹就是编译后的文件
7.3 nginx代理
修改nginx配置文件代理静态文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen 443 ssl;
server_name devtool.xxx.com;
ssl_certificate /home/ssl_cert/xxx.com.pem;
ssl_certificate_key /home/ssl_cert/xxx.com.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
underscores_in_headers on;
location / {
root index;
index index.html index.htm;
}
location /excalidraw {
alias /home/excalidraw/build;
index index.html;
}
location /socket.io {
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9071/socket.io;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600s;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
7. Docker部署
7.1 构建镜像
为了使用方便,讲代码打包成镜像放在服务器上运行,这样可以多人使用了,当前最新是0.17.0,基于此的Dockerfile代码如下:
1 | FROM node:18 AS build |
执行build后会报错:
1 | Step 7/10 : RUN yarn build:app:docker |
测试后发现,Dockerfile文件已经和代码不匹配,无法直接用Dockerfile构建镜像,而且官方提供的镜像包也是很老的版本。
修改如下内容,可以正常打包
- 修改Dockerfile文件
1 | FROM node:18 AS build |
- 修改.dockerignore文件
1 | * |
- 修改根目录下的package.json文件
1 | "build:app:docker": "yarn --cwd ./excalidraw-app build:app:docker", |
此时就可以正常构建镜像了
运行后
7.2 运行镜像
1 | docker run -d --name excalidraw -p 9071:80 excalidraw/excalidraw:aacopy |
8. 问题
centos7受用node启动服务,报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23node:internal/errors:563
ErrorCaptureStackTrace(err);
^
Error: ENOSPC: System limit for number of file watchers reached, watch '/home/excalidraw/excalidraw/dev-docs/docs/@excalidraw/excalidraw/api/children-components'
at FSWatcher.<computed> (node:internal/fs/watchers:247:19)
at Object.watch (node:fs:2473:36)
at createFsWatchInstance (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46210:17)
at setFsWatchListener (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46257:15)
at NodeFsHandler._watchWithNodeFs (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46412:14)
at NodeFsHandler._handleDir (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46648:19)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async NodeFsHandler._addToNodeFs (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46698:16)
Emitted 'error' event on FSWatcher instance at:
at FSWatcher._handleError (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:47909:10)
at NodeFsHandler._addToNodeFs (file:///home/excalidraw/excalidraw/node_modules/vite/dist/node/chunks/dep-9A4-l-43.js:46726:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
errno: -28,
syscall: 'watch',
code: 'ENOSPC',
path: '/home/excalidraw/excalidraw/dev-docs/docs/@excalidraw/excalidraw/api/children-components',
filename: '/home/excalidraw/excalidraw/dev-docs/docs/@excalidraw/excalidraw/api/children-components'在CentOS系统上运行yarn和vite时,如果遇到“Error: ENOSPC: System limit for number of file watchers reached”错误,这意味着系统当前设置的文件监视器(file watchers)数量上限已经达到了Linux内核允许的最大值。当Vite、Webpack或类似工具在监听大量文件以实现实时编译和热重载时,可能会触发这个限制。
1
2
3
4
5
6
7
8打开终端并输入以下命令以查看当前的限制:
cat /proc/sys/fs/inotify/max_user_watches
增加该限制到一个更高的值,例如524288(你可以根据需要选择合适的数值):
sudo sysctl -w fs.inotify.max_user_watches=524288
为了确保更改在重启后仍然有效,将其添加到/etc/sysctl.conf配置文件中:
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
应用新的配置:
sudo sysctl -p