GitHub: https://github.com/typsusan-zzz/canvas-drawing-editor
NPM: https://www.npmjs.com/package/canvas-drawing-editor
在线文档 / Documentation: https://typsusan-zzz.github.io/canvas-drawing-editor/
一个强大的基于 Canvas 的画布编辑器 Web Component,零依赖,支持 Vue 2/3、React、Angular 和原生 HTML。
- 🎨 绑图工具 - 画笔、矩形、圆形、线条、箭头、多边形、文本
- 🖼️ 图片支持 - 导入和编辑图片,支持亮度/对比度/模糊等滤镜
- 🔍 缩放平移 - 鼠标滚轮以光标为中心缩放,拖拽平移画布
- ↩️ 撤销/重做 - 完整的历史记录支持(Ctrl+Z / Ctrl+Y)
- 📚 图层管理 - 图层上移/下移/置顶/置底,可见性和锁定控制
- 🔗 组合/解组 - 多选对象组合(Ctrl+G)和解组(Ctrl+Shift+G)
- 📐 对齐/分布 - 左/中/右对齐,水平/垂直分布
- 🔥 热区功能 - 给文本绑定动态变量,实现模板化动态替换
- 💾 导入导出 - JSON 格式保存/加载项目,PNG 格式导出
- ⚡ 零依赖 - 纯 JavaScript 实现,无需 React/Vue
- 🎛️ 可配置 - 通过 tool 配置对象显示/隐藏任意工具
- 📦 轻量级 - gzip 后约 20KB
- 🔄 旋转控制 - 对象旋转手柄,支持自由旋转
- ⚖️ 等比缩放 - Shift + 拖拽角点保持宽高比
- ⭐ 更多形状 - 星形、心形、三角形、菱形、贝塞尔曲线、平滑曲线
- ✏️ 线条样式 - 实线/虚线/点线样式,单向/双向箭头
- 🎨 填充模式 - 支持描边/填充/描边+填充三种模式
- 🖋️ 富文本 - 支持部分加粗、部分改色、部分斜体
- 🎬 Tween 动画 - 对象属性过渡动画(位置、大小、透明度等)
- 📱 移动端支持 - 单指拖拽、双指缩放/旋转、长按选择、响应式布局
- 📐 形状库 - 注册自定义形状,支持带文字的组合形状,可搜索选择
npm install canvas-drawing-editor<!DOCTYPE html>
<html>
<head>
<style>
canvas-drawing-editor { width: 100%; height: 600px; display: block; }
</style>
</head>
<body>
<canvas-drawing-editor title="我的画板"></canvas-drawing-editor>
<script src="https://unpkg.com/canvas-drawing-editor/dist/canvas-drawing-editor.umd.js"></script>
</body>
</html><template>
<canvas-drawing-editor
title="Vue 画板"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>
</template>
<script setup>
import 'canvas-drawing-editor';
</script>可选配置: 如果控制台出现 Failed to resolve component: canvas-drawing-editor 警告,可在 vite.config.ts 中添加以下配置来消除警告:
export default defineConfig({
vue: {
template: {
compilerOptions: {
isCustomElement: (tag) => tag === 'canvas-drawing-editor'
}
}
}
});// main.js
import 'canvas-drawing-editor'
// 可选:如需消除控制台警告
// Vue.config.ignoredElements = ['canvas-drawing-editor']<template>
<canvas-drawing-editor
title="Vue2 画板"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>
</template>import 'canvas-drawing-editor';
function App() {
return (
<canvas-drawing-editor
title="React 画板"
style={{ width: '100%', height: '600px' }}
/>
);
}// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import 'canvas-drawing-editor';
@NgModule({
// ...
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }<!-- app.component.html -->
<canvas-drawing-editor
title="Angular 画板"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title |
string | "Canvas Editor" | 编辑器标题 |
lang |
string | "zh" | 界面语言("zh" 中文,"en" 英文) |
theme-color |
string | "#5450dc" | 主题色(影响按钮、悬停状态等) |
initial-data |
string | - | 初始化 JSON 数据(格式见下方) |
enable-hotzone |
boolean | false | 是否启用热区功能(管理员模式) |
hotzone-data |
string | - | 热区变量数据(JSON 格式,用于动态替换文本) |
tool-config |
string | - | 工具配置对象(JSON 格式,见下方) |
max-image-size |
string | - | 图片大小限制(支持 "500kb"、"2mb" 等格式,不设置则无限制) |
推荐使用 tool-config 属性统一配置工具显示:
<canvas-drawing-editor
tool-config='{"pencil":true,"rectangle":true,"circle":true,"line":true,"arrow":true,"polygon":true,"text":true,"image":true,"undo":true,"redo":true,"zoom":true,"download":true,"exportJson":true,"importJson":true,"clear":true,"color":true,"layers":true,"group":true,"align":true}'
></canvas-drawing-editor>| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
pencil |
boolean | true | 画笔工具 |
rectangle |
boolean | true | 矩形工具 |
circle |
boolean | true | 圆形工具 |
line |
boolean | true | 线条工具 |
arrow |
boolean | true | 箭头工具 |
polygon |
boolean | true | 多边形工具 |
text |
boolean | true | 文本工具 |
image |
boolean | true | 图片导入 |
undo |
boolean | true | 撤销按钮 |
redo |
boolean | true | 重做按钮 |
zoom |
boolean | true | 缩放控制 |
download |
boolean | true | PNG 导出 |
exportJson |
boolean | true | JSON 保存 |
importJson |
boolean | true | JSON 加载 |
clear |
boolean | true | 清空画布 |
color |
boolean | true | 颜色选择器 |
layers |
boolean | true | 图层管理 |
group |
boolean | true | 组合/解组 |
align |
boolean | true | 对齐/分布 |
shapePanel |
boolean | true | 形状库面板 |
仍支持单独的 show-* 属性,但推荐使用 tool-config:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
show-pencil |
boolean | true | 显示画笔工具 |
show-rectangle |
boolean | true | 显示矩形工具 |
show-circle |
boolean | true | 显示圆形工具 |
show-line |
boolean | true | 显示线条工具 |
show-arrow |
boolean | true | 显示箭头工具 |
show-polygon |
boolean | true | 显示多边形工具 |
show-text |
boolean | true | 显示文本工具 |
show-image |
boolean | true | 显示图片导入 |
show-undo |
boolean | true | 显示撤销按钮 |
show-redo |
boolean | true | 显示重做按钮 |
show-zoom |
boolean | true | 显示缩放控制 |
show-download |
boolean | true | 显示 PNG 导出 |
show-export |
boolean | true | 显示 JSON 保存 |
show-import |
boolean | true | 显示 JSON 加载 |
show-color |
boolean | true | 显示颜色选择器 |
show-clear |
boolean | true | 显示清空画布按钮 |
show-layers |
boolean | true | 显示图层管理 |
show-group |
boolean | true | 显示组合/解组 |
show-align |
boolean | true | 显示对齐/分布 |
可以通过 initial-data 属性传入 JSON 数据来初始化画布内容:
<canvas-drawing-editor
initial-data='{"objects":[{"id":"abc123","type":"RECTANGLE","x":100,"y":100,"width":200,"height":150,"color":"#3b82f6","lineWidth":2}]}'
></canvas-drawing-editor>当画布内容变化时触发。e.detail.objects 数组包含所有绑图对象。
document.addEventListener('editor-change', (e) => {
console.log('对象列表:', e.detail.objects);
// 保存到服务器或 localStorage
localStorage.setItem('canvas-data', JSON.stringify({ objects: e.detail.objects }));
});e.detail.objects 中每个对象都有以下基础属性:
| 属性 | 类型 | 说明 |
|---|---|---|
id |
string | 唯一标识符 |
type |
string | 对象类型:RECTANGLE、CIRCLE、PATH、TEXT、RICH_TEXT、IMAGE、LINE、ARROW、POLYGON、TRIANGLE、STAR、HEART、DIAMOND、BEZIER、GROUP |
rotation |
number | 旋转角度(弧度,可选,默认 0) |
opacity |
number | 透明度(0-1,可选,默认 1) |
x |
number | X 坐标 |
y |
number | Y 坐标 |
color |
string | 描边/填充颜色(十六进制格式,如 #3b82f6) |
lineWidth |
number | 线条宽度(像素) |
visible |
boolean | 是否可见(可选,默认 true) |
locked |
boolean | 是否锁定(可选,默认 false) |
矩形 (type: "RECTANGLE"):
| 属性 | 类型 | 说明 |
|---|---|---|
width |
number | 矩形宽度 |
height |
number | 矩形高度 |
圆形 (type: "CIRCLE"):
| 属性 | 类型 | 说明 |
|---|---|---|
radius |
number | 圆形半径 |
画笔路径 (type: "PATH"):
| 属性 | 类型 | 说明 |
|---|---|---|
points |
Array<{x, y}> | 点坐标数组 |
线条 (type: "LINE"):
| 属性 | 类型 | 说明 |
|---|---|---|
x2 |
number | 终点 X 坐标 |
y2 |
number | 终点 Y 坐标 |
箭头 (type: "ARROW"):
| 属性 | 类型 | 说明 |
|---|---|---|
x2 |
number | 终点 X 坐标 |
y2 |
number | 终点 Y 坐标 |
多边形 (type: "POLYGON"):
| 属性 | 类型 | 说明 |
|---|---|---|
radius |
number | 外接圆半径 |
sides |
number | 边数(如 3=三角形,6=六边形) |
文本 (type: "TEXT"):
| 属性 | 类型 | 说明 |
|---|---|---|
text |
string | 文本内容 |
fontSize |
number | 字体大小(像素) |
fontFamily |
string | 字体(可选,默认 sans-serif) |
bold |
boolean | 是否加粗(可选) |
italic |
boolean | 是否斜体(可选) |
hotzone |
object | 热区配置(可选,详见下方热区功能) |
图片 (type: "IMAGE"):
| 属性 | 类型 | 说明 |
|---|---|---|
width |
number | 图片宽度 |
height |
number | 图片高度 |
dataUrl |
string | Base64 编码的图片数据 |
组合 (type: "GROUP"):
| 属性 | 类型 | 说明 |
|---|---|---|
width |
number | 组合宽度 |
height |
number | 组合高度 |
children |
Array | 子对象数组 |
富文本 (type: "RICH_TEXT"):
| 属性 | 类型 | 说明 |
|---|---|---|
segments |
Array | 文本段落数组,每段包含 text, color, bold, italic, fontSize |
fontSize |
number | 默认字体大小(像素) |
星形 (type: "STAR"):
| 属性 | 类型 | 说明 |
|---|---|---|
outerRadius |
number | 外圆半径 |
innerRadius |
number | 内圆半径 |
points |
number | 星形角数(默认 5) |
心形 (type: "HEART")、三角形 (type: "TRIANGLE")、菱形 (type: "DIAMOND"):
| 属性 | 类型 | 说明 |
|---|---|---|
width |
number | 宽度 |
height |
number | 高度 |
贝塞尔曲线 (type: "BEZIER"):
| 属性 | 类型 | 说明 |
|---|---|---|
points |
Array | 控制点数组(包含锚点和控制柄) |
closed |
boolean | 是否闭合路径 |
// 保存画布内容
document.addEventListener('editor-change', (e) => {
const data = JSON.stringify({ objects: e.detail.objects });
localStorage.setItem('my-canvas', data);
});
// 加载画布内容
const savedData = localStorage.getItem('my-canvas');
if (savedData) {
document.querySelector('canvas-drawing-editor').setAttribute('initial-data', savedData);
}document.addEventListener('editor-close', () => {
console.log('编辑器已关闭');
});当动画开始时触发。
document.addEventListener('animation-start', (e) => {
console.log('动画开始:', e.detail);
// e.detail: { tweenId, objectId }
});当动画完成时触发。
document.addEventListener('animation-complete', (e) => {
console.log('动画完成:', e.detail);
// e.detail: { tweenId, objectId }
});动画每帧更新时触发。
document.addEventListener('animation-update', (e) => {
console.log('动画进度:', e.detail.progress);
// e.detail: { tweenId, objectId, progress }
});热区功能允许你给文本对象绑定动态变量,实现模板化的动态文本替换。
- 设计模板(如证书、名片、海报)
- 给文本添加热区,绑定变量名
- 使用时传入变量值,动态替换文本内容
<!-- 启用热区编辑功能 -->
<canvas-drawing-editor
title="模板设计器"
enable-hotzone="true"
></canvas-drawing-editor>操作步骤:
- 创建文本(如:"姓名")
- 右键点击文本 → 选择「新建热区」
- 输入变量名(如:
name)→ 保存 - 导出 JSON 保存模板
<!-- 传入模板数据和变量值 -->
<canvas-drawing-editor
initial-data='{"objects":[...]}'
hotzone-data='{"name": "张三", "company": "XX公司"}'
></canvas-drawing-editor>// 文本对象的热区配置
{
"type": "TEXT",
"text": "姓名",
"hotzone": {
"variableName": "name", // 变量名(必填)
"defaultValue": "默认值", // 默认值(可选)
"description": "用户姓名" // 描述(可选)
}
}形状库功能允许你注册自定义形状,用户可以从形状面板中选择并添加到画布。
const editor = document.querySelector('canvas-drawing-editor');
// 注册单个或多个形状
editor.registerShapes([
{
id: 'btn-confirm',
name: '确认按钮',
type: 'roundedRect',
category: '按钮',
fillColor: '#22c55e',
fillMode: 'fill',
cornerRadius: 8,
width: 100,
height: 40,
text: '确认',
textColor: '#ffffff',
fontSize: 14,
fontWeight: 'bold'
},
{
id: 'flow-start',
name: '开始节点',
type: 'ellipse',
category: '流程图',
fillColor: '#dbeafe',
fillMode: 'both',
strokeColor: '#3b82f6',
strokeWidth: 2,
width: 100,
height: 60,
text: '开始',
textColor: '#1e40af'
}
]);| 属性 | 类型 | 说明 |
|---|---|---|
id |
string | 形状唯一标识 |
name |
string | 形状名称(显示用) |
type |
string | 形状类型:rectangle, circle, triangle, star, heart, diamond, polygon, ellipse, roundedRect, parallelogram, trapezoid, hexagon |
category |
string | 分类名称(可选) |
fillColor |
string | 填充颜色 |
fillMode |
string | 填充模式:stroke, fill, both |
strokeColor |
string | 边框颜色 |
strokeWidth |
number | 边框宽度 |
width |
number | 默认宽度 |
height |
number | 默认高度 |
cornerRadius |
number | 圆角半径(圆角矩形) |
text |
string | 形状中心文字 |
textColor |
string | 文字颜色 |
fontSize |
number | 文字大小 |
fontWeight |
string | 文字粗细:normal, bold |
icon |
string | 自定义 SVG 图标(面板显示用) |
editor.addEventListener('shape-added', (e) => {
console.log('形状已添加:', e.detail.shape.name);
console.log('创建的对象:', e.detail.object);
});通过 tool-config 或 show-shape-panel 属性控制形状库按钮显示:
<canvas-drawing-editor
tool-config='{"shapePanel": true}'
></canvas-drawing-editor>
<!-- 或使用单独属性 -->
<canvas-drawing-editor
show-shape-panel="true"
></canvas-drawing-editor>通过 tweenAnimate() 方法可以为对象创建平滑的属性过渡动画:
const editor = document.querySelector('canvas-drawing-editor');
// 基本用法
editor.tweenAnimate(objectId, { x: 300, y: 200 }, {
duration: 1000, // 动画时长(毫秒)
easing: 'easeOutQuad', // 缓动函数
onComplete: () => console.log('动画完成')
});
// 可动画属性:x, y, width, height, rotation, opacity, fontSize, radius
// 缓动函数:linear, easeInQuad, easeOutQuad, easeInOutQuad,
// easeInElastic, easeOutElastic, easeInBounce, easeOutBounce,
// easeInBack, easeOutBack
// 循环动画
editor.tweenAnimate(objectId, { x: 400 }, {
duration: 1000,
repeat: -1, // 无限循环
yoyo: true // 往返
});
// 停止动画
editor.stopAllAnimations();通过 getImageData() 方法可以获取画布图片数据(base64 或 Blob),无需触发下载:
const editor = document.querySelector('canvas-drawing-editor');
// 获取 base64 格式(默认)
const dataURL = await editor.getImageData();
console.log(dataURL); // data:image/png;base64,...
// 获取 Blob 格式(适合上传到服务器)
const blob = await editor.getImageData({
type: 'blob',
format: 'png', // 'png' | 'jpeg' | 'webp'
quality: 0.92, // jpeg/webp 质量 (0-1)
background: '#ffffff' // 背景色
});
// 上传到服务器示例
const formData = new FormData();
formData.append('image', blob, 'canvas.png');
await fetch('/api/upload', { method: 'POST', body: formData });| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
format |
string | 'png' | 图片格式:'png', 'jpeg', 'webp' |
quality |
number | 0.92 | 图片质量(仅 jpeg/webp 有效,0-1) |
type |
string | 'dataURL' | 返回类型:'dataURL' 或 'blob' |
background |
string | '#ffffff' | 背景颜色 |
限制用户上传图片的文件大小,超出限制时会显示友好的错误提示。
<!-- 限制图片大小为 500KB -->
<canvas-drawing-editor max-image-size="500kb"></canvas-drawing-editor>
<!-- 限制图片大小为 2MB -->
<canvas-drawing-editor max-image-size="2mb"></canvas-drawing-editor>
<!-- 不限制(默认) -->
<canvas-drawing-editor></canvas-drawing-editor>const editor = document.querySelector('canvas-drawing-editor');
// 设置限制为 500KB
editor.setMaxImageSize(500); // 数字默认单位为 KB
editor.setMaxImageSize('500kb'); // 字符串方式
// 设置限制为 2MB
editor.setMaxImageSize('2mb');
// 取消限制
editor.setMaxImageSize(0);
// 获取当前限制(返回 KB,0 表示无限制)
const limit = editor.getMaxImageSize();
console.log(limit); // 500当用户上传的图片超出限制时,会显示一个 Toast 提示框:
- 🔴 图片大小超出限制!
- 当前图片大小: 1.25 MB
- 最大允许: 500 KB
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 构建库
npm run build:libA powerful canvas-based drawing editor Web Component with zero dependencies. Works with Vue 2/3, React, Angular, and vanilla HTML.
- 🎨 Drawing Tools - Pencil, Rectangle, Circle, Line, Arrow, Polygon, Text
- 🖼️ Image Support - Import and manipulate images with brightness/contrast/blur filters
- 🔍 Zoom & Pan - Mouse wheel zoom centered on cursor, drag to pan
- ↩️ Undo/Redo - Full history support (Ctrl+Z / Ctrl+Y)
- 📚 Layer Management - Move up/down/top/bottom, visibility and lock control
- 🔗 Group/Ungroup - Multi-select and group objects (Ctrl+G / Ctrl+Shift+G)
- 📐 Align/Distribute - Left/center/right alignment, horizontal/vertical distribution
- 🔥 Hotzone - Bind dynamic variables to text for template-based replacement
- 💾 Import/Export - Save and load projects as JSON, export as PNG
- ⚡ Zero Dependencies - Pure JavaScript, no React/Vue required
- 🎛️ Configurable - Show/hide any tool via tool config object
- 📦 Lightweight - ~20KB gzipped
- 🔄 Rotation Control - Object rotation handle for free rotation
- ⚖️ Proportional Scaling - Shift + drag corner to maintain aspect ratio
- ⭐ More Shapes - Star, Heart, Triangle, Diamond, Bezier curves, Smooth curves
- ✏️ Line Styles - Solid/dashed/dotted styles, single/double arrows
- 🎨 Fill Modes - Supports stroke/fill/stroke+fill modes
- 🖋️ Rich Text - Support partial bold, partial color, partial italic
- 🎬 Tween Animation - Object property transition animations (position, size, opacity, etc.)
- 📱 Mobile Support - Single finger drag, two-finger zoom/rotate, long press selection, responsive layout
- 📐 Shape Library - Register custom shapes with text, searchable panel for quick selection
npm install canvas-drawing-editor<!DOCTYPE html>
<html>
<head>
<style>
canvas-drawing-editor { width: 100%; height: 600px; display: block; }
</style>
</head>
<body>
<canvas-drawing-editor title="My Canvas"></canvas-drawing-editor>
<script src="https://unpkg.com/canvas-drawing-editor/dist/canvas-drawing-editor.umd.js"></script>
</body>
</html><template>
<canvas-drawing-editor
title="Vue Canvas"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>
</template>
<script setup>
import 'canvas-drawing-editor';
</script>Optional: To suppress the Failed to resolve component: canvas-drawing-editor warning in the console, add to vite.config.ts:
export default defineConfig({
vue: {
template: {
compilerOptions: {
isCustomElement: (tag) => tag === 'canvas-drawing-editor'
}
}
}
});// main.js
import 'canvas-drawing-editor'
// Optional: To suppress console warnings
// Vue.config.ignoredElements = ['canvas-drawing-editor']<template>
<canvas-drawing-editor
title="Vue2 Canvas"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>
</template>import 'canvas-drawing-editor';
function App() {
return (
<canvas-drawing-editor
title="React Canvas"
style={{ width: '100%', height: '600px' }}
/>
);
}// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import 'canvas-drawing-editor';
@NgModule({
// ...
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }<!-- app.component.html -->
<canvas-drawing-editor
title="Angular Canvas"
style="width: 100%; height: 600px;"
></canvas-drawing-editor>| Attribute | Type | Default | Description |
|---|---|---|---|
title |
string | "Canvas Editor" | Editor title |
lang |
string | "zh" | UI language ("zh" for Chinese, "en" for English) |
theme-color |
string | "#5450dc" | Theme color (affects buttons, hover states, etc.) |
initial-data |
string | - | Initial JSON data to render (see format below) |
enable-hotzone |
boolean | false | Enable hotzone feature (admin mode) |
hotzone-data |
string | - | Hotzone variable data (JSON format for dynamic text replacement) |
tool-config |
string | - | Tool configuration object (JSON format, see below) |
max-image-size |
string | - | Image size limit (supports "500kb", "2mb" format, no limit if not set) |
Recommended: Use tool-config attribute for unified tool configuration:
<canvas-drawing-editor
tool-config='{"pencil":true,"rectangle":true,"circle":true,"line":true,"arrow":true,"polygon":true,"text":true,"image":true,"undo":true,"redo":true,"zoom":true,"download":true,"exportJson":true,"importJson":true,"clear":true,"color":true,"layers":true,"group":true,"align":true}'
></canvas-drawing-editor>| Option | Type | Default | Description |
|---|---|---|---|
pencil |
boolean | true | Pencil tool |
rectangle |
boolean | true | Rectangle tool |
circle |
boolean | true | Circle tool |
line |
boolean | true | Line tool |
arrow |
boolean | true | Arrow tool |
polygon |
boolean | true | Polygon tool |
text |
boolean | true | Text tool |
image |
boolean | true | Image import |
undo |
boolean | true | Undo button |
redo |
boolean | true | Redo button |
zoom |
boolean | true | Zoom controls |
download |
boolean | true | PNG export |
exportJson |
boolean | true | JSON save |
importJson |
boolean | true | JSON load |
clear |
boolean | true | Clear canvas |
color |
boolean | true | Color picker |
layers |
boolean | true | Layer management |
group |
boolean | true | Group/Ungroup |
align |
boolean | true | Align/Distribute |
shapePanel |
boolean | true | Shape library panel |
Individual show-* attributes are still supported but tool-config is recommended:
| Attribute | Type | Default | Description |
|---|---|---|---|
show-pencil |
boolean | true | Show pencil tool |
show-rectangle |
boolean | true | Show rectangle tool |
show-circle |
boolean | true | Show circle tool |
show-line |
boolean | true | Show line tool |
show-arrow |
boolean | true | Show arrow tool |
show-polygon |
boolean | true | Show polygon tool |
show-text |
boolean | true | Show text tool |
show-image |
boolean | true | Show image import |
show-undo |
boolean | true | Show undo button |
show-redo |
boolean | true | Show redo button |
show-zoom |
boolean | true | Show zoom controls |
show-download |
boolean | true | Show PNG export |
show-export |
boolean | true | Show JSON save |
show-import |
boolean | true | Show JSON load |
show-color |
boolean | true | Show color picker |
show-clear |
boolean | true | Show clear canvas button |
show-layers |
boolean | true | Show layer management |
show-group |
boolean | true | Show group/ungroup |
show-align |
boolean | true | Show align/distribute |
You can pass JSON data to initialize the canvas content:
<canvas-drawing-editor
initial-data='{"objects":[{"id":"abc123","type":"RECTANGLE","x":100,"y":100,"width":200,"height":150,"color":"#3b82f6","lineWidth":2}]}'
></canvas-drawing-editor>Fires when canvas content changes. The e.detail.objects array contains all drawing objects.
document.addEventListener('editor-change', (e) => {
console.log('Objects:', e.detail.objects);
// Save to server or localStorage
localStorage.setItem('canvas-data', JSON.stringify({ objects: e.detail.objects }));
});Each object in e.detail.objects has the following base properties:
| Property | Type | Description |
|---|---|---|
id |
string | Unique identifier |
type |
string | Object type: RECTANGLE, CIRCLE, PATH, TEXT, IMAGE, LINE, ARROW, POLYGON, GROUP |
x |
number | X coordinate |
y |
number | Y coordinate |
color |
string | Stroke/fill color (hex format, e.g., #3b82f6) |
lineWidth |
number | Line width in pixels |
visible |
boolean | Visibility (optional, default true) |
locked |
boolean | Lock state (optional, default false) |
Rectangle (type: "RECTANGLE"):
| Property | Type | Description |
|---|---|---|
width |
number | Rectangle width |
height |
number | Rectangle height |
Circle (type: "CIRCLE"):
| Property | Type | Description |
|---|---|---|
radius |
number | Circle radius |
Path/Pencil (type: "PATH"):
| Property | Type | Description |
|---|---|---|
points |
Array<{x, y}> | Array of point coordinates |
Line (type: "LINE"):
| Property | Type | Description |
|---|---|---|
x2 |
number | End point X coordinate |
y2 |
number | End point Y coordinate |
Arrow (type: "ARROW"):
| Property | Type | Description |
|---|---|---|
x2 |
number | End point X coordinate |
y2 |
number | End point Y coordinate |
Polygon (type: "POLYGON"):
| Property | Type | Description |
|---|---|---|
radius |
number | Circumscribed circle radius |
sides |
number | Number of sides (e.g., 3=triangle, 6=hexagon) |
Text (type: "TEXT"):
| Property | Type | Description |
|---|---|---|
text |
string | Text content |
fontSize |
number | Font size in pixels |
fontFamily |
string | Font family (optional, default sans-serif) |
bold |
boolean | Bold style (optional) |
italic |
boolean | Italic style (optional) |
hotzone |
object | Hotzone config (optional, see Hotzone section) |
Image (type: "IMAGE"):
| Property | Type | Description |
|---|---|---|
width |
number | Image width |
height |
number | Image height |
dataUrl |
string | Base64 encoded image data |
Group (type: "GROUP"):
| Property | Type | Description |
|---|---|---|
width |
number | Group width |
height |
number | Group height |
children |
Array | Array of child objects |
// Save canvas content
document.addEventListener('editor-change', (e) => {
const data = JSON.stringify({ objects: e.detail.objects });
localStorage.setItem('my-canvas', data);
});
// Load canvas content
const savedData = localStorage.getItem('my-canvas');
if (savedData) {
document.querySelector('canvas-drawing-editor').setAttribute('initial-data', savedData);
}document.addEventListener('editor-close', () => {
console.log('Editor closed');
});Triggered when an animation starts.
document.addEventListener('animation-start', (e) => {
console.log('Animation started:', e.detail);
// e.detail: { tweenId, objectId }
});Triggered when an animation completes.
document.addEventListener('animation-complete', (e) => {
console.log('Animation completed:', e.detail);
// e.detail: { tweenId, objectId }
});Triggered on each animation frame update.
document.addEventListener('animation-update', (e) => {
console.log('Animation progress:', e.detail.progress);
// e.detail: { tweenId, objectId, progress }
});The hotzone feature allows you to bind dynamic variables to text objects for template-based dynamic text replacement.
- Design templates (certificates, business cards, posters)
- Add hotzones to text, bind variable names
- Pass variable values at runtime to dynamically replace text
<!-- Enable hotzone editing -->
<canvas-drawing-editor
title="Template Designer"
enable-hotzone="true"
></canvas-drawing-editor>Steps:
- Create text (e.g., "Name")
- Right-click on text → Select "Create Hotzone"
- Enter variable name (e.g.,
name) → Save - Export JSON to save template
<!-- Pass template data and variable values -->
<canvas-drawing-editor
initial-data='{"objects":[...]}'
hotzone-data='{"name": "John Doe", "company": "Acme Inc"}'
></canvas-drawing-editor>// Text object with hotzone config
{
"type": "TEXT",
"text": "Name",
"hotzone": {
"variableName": "name", // Variable name (required)
"defaultValue": "Default", // Default value (optional)
"description": "User name" // Description (optional)
}
}The Shape Library feature allows you to register custom shapes that users can select from a panel and add to the canvas.
const editor = document.querySelector('canvas-drawing-editor');
// Register one or more shapes
editor.registerShapes([
{
id: 'btn-confirm',
name: 'Confirm Button',
type: 'roundedRect',
category: 'Buttons',
fillColor: '#22c55e',
fillMode: 'fill',
cornerRadius: 8,
width: 100,
height: 40,
text: 'Confirm',
textColor: '#ffffff',
fontSize: 14,
fontWeight: 'bold'
},
{
id: 'flow-start',
name: 'Start Node',
type: 'ellipse',
category: 'Flowchart',
fillColor: '#dbeafe',
fillMode: 'both',
strokeColor: '#3b82f6',
strokeWidth: 2,
width: 100,
height: 60,
text: 'Start',
textColor: '#1e40af'
}
]);| Property | Type | Description |
|---|---|---|
id |
string | Unique shape identifier |
name |
string | Shape name (for display) |
type |
string | Shape type: rectangle, circle, triangle, star, heart, diamond, polygon, ellipse, roundedRect, parallelogram, trapezoid, hexagon |
category |
string | Category name (optional) |
fillColor |
string | Fill color |
fillMode |
string | Fill mode: stroke, fill, both |
strokeColor |
string | Stroke color |
strokeWidth |
number | Stroke width |
width |
number | Default width |
height |
number | Default height |
cornerRadius |
number | Corner radius (for rounded rectangles) |
text |
string | Center text content |
textColor |
string | Text color |
fontSize |
number | Font size |
fontWeight |
string | Font weight: normal, bold |
icon |
string | Custom SVG icon (for panel display) |
editor.addEventListener('shape-added', (e) => {
console.log('Shape added:', e.detail.shape.name);
console.log('Created object:', e.detail.object);
});Control shape library button visibility via tool-config or show-shape-panel attribute:
<canvas-drawing-editor
tool-config='{"shapePanel": true}'
></canvas-drawing-editor>
<!-- Or use individual attribute -->
<canvas-drawing-editor
show-shape-panel="true"
></canvas-drawing-editor>Use tweenAnimate() method to create smooth property transition animations:
const editor = document.querySelector('canvas-drawing-editor');
// Basic usage
editor.tweenAnimate(objectId, { x: 300, y: 200 }, {
duration: 1000, // Animation duration (ms)
easing: 'easeOutQuad', // Easing function
onComplete: () => console.log('Animation complete')
});
// Animatable properties: x, y, width, height, rotation, opacity, fontSize, radius
// Easing functions: linear, easeInQuad, easeOutQuad, easeInOutQuad,
// easeInElastic, easeOutElastic, easeInBounce, easeOutBounce,
// easeInBack, easeOutBack
// Loop animation
editor.tweenAnimate(objectId, { x: 400 }, {
duration: 1000,
repeat: -1, // Infinite loop
yoyo: true // Reverse on repeat
});
// Stop animations
editor.stopAllAnimations();Use getImageData() method to get canvas image data (base64 or Blob) without triggering download:
const editor = document.querySelector('canvas-drawing-editor');
// Get base64 format (default)
const dataURL = await editor.getImageData();
console.log(dataURL); // data:image/png;base64,...
// Get Blob format (suitable for server upload)
const blob = await editor.getImageData({
type: 'blob',
format: 'png', // 'png' | 'jpeg' | 'webp'
quality: 0.92, // jpeg/webp quality (0-1)
background: '#ffffff' // Background color
});
// Upload to server example
const formData = new FormData();
formData.append('image', blob, 'canvas.png');
await fetch('/api/upload', { method: 'POST', body: formData });| Parameter | Type | Default | Description |
|---|---|---|---|
format |
string | 'png' | Image format: 'png', 'jpeg', 'webp' |
quality |
number | 0.92 | Image quality (jpeg/webp only, 0-1) |
type |
string | 'dataURL' | Return type: 'dataURL' or 'blob' |
background |
string | '#ffffff' | Background color |
Limit the file size of images uploaded by users. A friendly error message will be displayed when the limit is exceeded.
<!-- Limit image size to 500KB -->
<canvas-drawing-editor max-image-size="500kb"></canvas-drawing-editor>
<!-- Limit image size to 2MB -->
<canvas-drawing-editor max-image-size="2mb"></canvas-drawing-editor>
<!-- No limit (default) -->
<canvas-drawing-editor></canvas-drawing-editor>const editor = document.querySelector('canvas-drawing-editor');
// Set limit to 500KB
editor.setMaxImageSize(500); // Number defaults to KB
editor.setMaxImageSize('500kb'); // String format
// Set limit to 2MB
editor.setMaxImageSize('2mb');
// Remove limit
editor.setMaxImageSize(0);
// Get current limit (returns KB, 0 means no limit)
const limit = editor.getMaxImageSize();
console.log(limit); // 500When a user uploads an image that exceeds the limit, a Toast notification will appear:
- 🔴 Image size exceeded!
- Current image size: 1.25 MB
- Maximum allowed: 500 KB
# Install dependencies
npm install
# Start dev server
npm run dev
# Build library
npm run build:libMIT © typsusan