Excalidraw: Bảng vẽ ảo dành cho dân phác thảo
Làm thế nào để vẽ minh họa nhanh khi cần giải thích kiến trúc, luồng xử lý? Bài viết này sẽ giới thiệu về Excalidraw, một công cụ bảng vẽ ảo với nhiều tính năng hấp dẫn, rất tiện lợi và phù hợp cho công việc phác thảo.
Trong công việc hàng ngày, sẽ có nhiều lúc chúng ta cần trình bày ý tưởng của mình bằng hình ảnh, chữ viết. Như anh bạn Nekogami cạnh tôi lúc này đang loay hoay tìm cây bút (thứ luôn tự động biến mất khi cần) để nguệch ngoạc phác thảo lên giấy về luồng xử lý mà tôi vừa hỏi.
Để tiết kiệm thời gian tìm bút, tôi liền giới thiệu Excalidraw cho bạn mình, đây là công cụ bảng vẽ ảo mã nguồn mở với nhiều tính năng hay mà tôi nghĩ anh ấy sẽ thích. Tôi nghĩ có thể các bạn chuộng viết vẽ cũng sẽ hứng thú với Excalidraw vì cũng có khá nhiều điều thú vị.
Mở đề hư cấu chút xíu thôi, chứ thật ra Excalidraw là công cụ sếp chúng tôi giao để tìm hiểu cho dự án, tìm hiểu xong thấy cũng hay hay nên lên bài chia sẻ với mọi người. Mời bạn cùng "vọc" Excalidraw với tôi nhé.
Excalidraw là một bảng vẽ ảo (virtual whiteboard) dành cho các công việc phác thảo, đặc biệt hữu dụng trong việc tạo đồ thị, giải thích luồng xử lý. Công cụ này không chỉ hỗ trợ những thao tác cơ bản như vẽ hình đơn giản, thêm chữ, tô màu... mà người dùng còn có thể tuỳ chỉnh nét vẽ. Đặc biệt với lựa chọn Sloppiness là Artist hay Cartoonist, người dùng có thể tạo ra cảm giác "vẽ tay" cho bản vẽ của mình. Còn nếu thích mọi thứ "ngay hàng thẳng lối", Architect sẽ là cấu hình dành cho bạn. À nhân tiện nói về architect, Excalidraw cũng hỗ trợ cả dark mode mà các lập trình viên thường thích nữa nha.
Excalidraw hỗ trợ tính năng dark mode
Bên cạnh việc tự "vẽ tay" những thứ mình cần, người dùng cũng có thể tận dụng hơn 100 bộ hình ảnh, kí hiệu sẵn có thuộc nhiều đề tài, lĩnh vực khác nhau thông qua tính năng thư viện - Library. Ví dụ như khi cần vẽ kiến trúc hệ thống, bạn có thể sử dụng các bộ kí hiệu về dịch vụ cloud như GCP, Azure, AWS... Hơn nữa, người dùng cũng có thể tự tạo thư viện cho cá nhân mình từ những hình ảnh thường xuyên sử dụng. Bạn có thể xem qua các thư viện của Excalidraw để tìm kiếm "chân ái" của đời mình nha.
Một tính năng nữa hẳn sẽ khiến bạn ngạc nhiên về sự "có tâm" của Excalidraw, đó là khi người dùng copy-paste nội dung từ hai cột của một bảng tính (như từ Excel chẳng hạn), và có một cột là số liệu, thì người dùng có thể lựa chọn hiển thị nội dung đó dưới dạng biểu đồ, rất tinh gọn và đỡ mắc công biết bao nhiêu.
Bạn có thể thử bằng cách copy-paste nội dung bên dưới vào Excalidraw:
Và đặc sắc hơn đó là Excalidraw cũng hỗ trợ tính năng Collaboration. Tính năng này cho phép người dùng có thể chia sẻ bảng vẽ của mình với người khác để cùng nhau thao tác. Hơn nữa, Excalidraw còn cẩn thận tạo cơ chế mã hoá dữ liệu trên đường truyền để "bảo vệ" nội dung. Để test thử tính năng này, bạn có thể chọn Collaboration trên Excalidraw và mời bạn bè của mình cùng vẽ.
Còn nếu muốn tự host một server cho mình, bạn có thể sử dụng thư viện excalidraw-room.
Là một dự án mã nguồn mở, bạn hoàn toàn có thể "đem Excalidraw về" với website của mình để có thể tuỳ chỉnh và nâng cấp mã nguồn của Excalidraw tuỳ theo nhu cầu. Trong trường hợp đó, bạn đã có sẵn thư viện excalidraw wrap công cụ này:
Thư viện này giúp chúng ta nhúng Excalidraw một cách dễ dàng thông qua các component có sẵn:
```
import { useState, useEffect } from "react";
export default function IndexPage() {
const [Comp, setComp] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) => setComp(comp.default));
}, []);
return <>{Comp && <Comp />}</>;
}
```
Với những method được public qua thư viện, ta có thể dễ dàng tuỳ chỉnh các hành vi như:
- onChange: khi bảng vẽ thay đổi
- onCollabButtonClick: khi thực hiện collaboration
- updateScene + addFiles: khi cập nhật nội dung bảng vẽ bằng tập tin JSON
- getSceneElements + getFiles + getAppState; khi cần lấy nội dung bảng vẽ
Ngoài ra, các tính năng tiện ích như export thành tập tin hình ảnh SVG/PNG hay tập tin JSON cũng được hỗ trợ sẵn.
Tập tin JSON của Excalidraw là danh sách các element được vẽ lên bảng vẽ, cùng các cấu hình của những element đó. Cấu trúc JSON của Excalidraw cũng khá đơn giản như bên dưới:
```
{
"type": "excalidraw",
"version": 2,
"source": "http://localhost:3001",
"elements": [
{
"type": "image",
"version": 254,
"versionNonce": 1937741759,
"isDeleted": false,
"id": "-_Xd5lJQnb6m36LJN9H7g",
"fillStyle": "hachure",
"strokeWidth": 1,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"x": 719,
"y": -20,
"strokeColor": "transparent",
"backgroundColor": "transparent",
"width": 48,
"height": 48,
"seed": 1858260293,
"groupIds": [
"5x-pNSwhl3P8oD_ji-ZGv"
],
"strokeSharpness": "round",
"boundElements": [],
"updated": 1656485934254,
"link": null,
"status": "pending",
"fileId": "file_832066996",
"scale": [
1,
1
]
},
{
...
}
...
],
"appState": {
"gridSize": 20,
"viewBackgroundColor": "#ffffff"
},
"files": {
"file_832066996": {
"id": "file_832066996",
"dataURL": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvb..."
}
}
}
```
Bạn hoàn toàn có thể chỉnh sửa tập tin JSON (với các giá trị phù hợp) và import lại vào Excalidraw để thấy sự thay đổi. Sơ lược một số đặc điểm của cấu trúc này:
- Một số các type element Excalidraw hỗ trợ: rectangle, diamond, ellipse, line, arrow, freedraw, và image. Các type khác nhau sẽ có thêm các thuộc tính riêng biệt.
- Thuộc tính
version
vàversionNonce
được Excalidraw sử dụng trong quá trình syncing và merging nội dung khi collaboration. - Thứ tự các element trong mảng
elements
sẽ quyết định thứ tự render của các element (vị trí trên/dưới giữa các element). - Nội dung của hình ảnh sẽ được lưu trong thuộc tính
files
(với dataURL là định dạng base64 hoặc URL của image), các element có typeimage
sẽ tham chiếu đến hình ảnh này thông qua thuộc tínhfileId
.
Còn nếu bạn sắp cần chỉnh sửa source code của Excalidraw thì bên dưới là một số class đáng chú ý trong source code:
appState.ts
: chứa cấu hình mặc định cho các thuộc tính như font-family, font-size, sloppiness (roughness)... Bạn có thể tuỳ chỉnh lại cho phù hợp với mục đích sử dụng. Ví dụ khi cần host Excalidraw dành cho người vẽ kiến trúc hệ thống, bạn sẽ muốn đổi thuộc tínhcurrentItemEndArrowhead
(đầu mũi tên) thànhtriangle
, đổi thuộc tínhcurrentItemRoughness
(sloppiness) thành1
, vàcurrentItemFillStyle
thànhsolid
. Như vậy, nét vẽ sẽ trở nên cứng cỏi hơn.actionProperties.ts
: chứa các hàm render component tuỳ chỉnh trên giao diện Excalidraw, cần xem khi bạn muốn thêm nút mới hoặc tuỳ chỉnh UI các nút sẵn có.renderElement.ts
: chứa các hàm thực thi thao tác render element lên canvas của Excalidraw, cần xem khi bạn muốn can thiệp hay thay đổi hành vi render.mutateElement.ts
: chứa các hàm để persist dữ liệu cho element.
Một số tính năng mà tôi đã thử "làm thêm" trên Excalidraw:
Thêm font size XS - Extra small để làm chú thích cho các icon:
Thêm tuỳ chỉnh Line type để vẽ mũi tên vuông góc, dành cho dân kỹ thuật:
Ngoài ra, nếu cần export tập tin svg hoặc png từ Excalidraw JSON, bạn cũng có thể tìm các thư viện chuyên dụng như excalidraw-to-svg hoặc build trực tiếp từ thư mục /src/packages/utils
để có thư viện exporter.
Tôi đã thử sử dụng thư viện này kết hợp với jsdom
và triển khai bằng Azure Functions
để thử làm một API extract tập tin PNG từ Excalidraw JSON. Kết quả là API chạy ổn với hầu hết Excalidraw JSON, chỉ khi có element kiểu image là API không render được JSON. Vì thời gian tìm hiểu có hạn nên tôi chưa nghiên cứu thêm nhiều, nhưng tôi sẽ quay lại điểm này khi có cập nhật mới về exporter trên github của Excalidraw.
Đó là tổng hợp những điều tôi muốn chia sẻ với các bạn về công cụ bảng vẽ ảo Excalidraw qua quá trình sử dụng cũng như tuỳ chỉnh. Đây thật sự là một công cụ hay và đáp ứng được nhiều mục đích, phù hợp với các bạn cần phác thảo nhanh hoặc thích "gói mang về" một công cụ viết vẽ cho website của mình.