montage.js
v0.1.26
Published
一个基于canvas的绘图库
Downloads
148
Readme
montage.js
简介
montage.js 是一个基于 canvas 的绘图库,并且内置了一些鼠标交互功能,在一些需要用到 canvas 的场景下可使用此库来更简单的完成开发,比如拼接图片、简易绘图功能等等
也可以基于此库来开发一些自定义组件,几个常用场景的使用可见 demo 👇
性能测试
大致性能可见下表( Mac Pro, M1, 2020 )
说明:
- 图案个数指画布中实际存在的图案/连线数量;
- 响应时长为鼠标 "按下" 至 "抬起" 过程中所花费的响应时间总和;
- 加载图案上限约为 1.34w 个;
- 本次测试不包含图片,图片加载/响应时长受图片大小/格式影响,具体性能以实际使用情况为准;
- 本次测试在设备通电情况下进行,实际使用过程中建议将图案个数控制在 6000 以内,否则会对性能产生较为明显的影响;
| 图案个数 | 加载时长 ms | 响应时长 ms | 测试次数 | | -------- | ----------- | ----------- | -------- | | 60 | 2 | 12 ~ 33 | 6 | | 600 | 23 | 72 ~ 103 | 6 | | 6000 | 650 ~ 662 | 545 ~ 603 | 6 | | 12000 | 2248 ~ 2306 | 1000 ~ 1200 | 6 |
仓库
demo
开发示例,仅供参考
cd example
npm i
npm run serve
快速开始
安装
npm install montage.js
创建第一组图案
- 创建画布
<canvas id="board"></canvas>
- 渲染节点
import Montage from "montage.js";
// 初始化
this.draw = new Montage(
{
drag: true, // 注意:如果要当成画布使用(允许缩放/拖拽),则需要开启 drag ,若只需要生成静态图案,则无需开启此选项
width: 300,
height: 300,
},
document.getElementById("board")
);
// 添加两个节点
this.draw.addNode({
type: "rect",
x: 20,
y: 50,
width: 80,
height: 40,
zoom: true, // 开启缩放
connect: true, // 开启连线功能
textInfo: {
text: "hello world",
},
});
this.draw.addNode({
type: "circular",
x: 200,
y: 70,
radiusX: 50,
radiusY: 30,
zoom: true,
connect: true,
textInfo: {
text: "hello world",
},
});
创建节点后会返回被创建的节点信息
注意:只有在调用 addNode 方法时会返回
// 获取创建的节点信息
this.draw
.addNode({
type: "rect",
x: 100,
y: 100,
width: 50,
height: 50,
})
.then((node) => {
console.log("node: ", node);
});
效果
数据导入及导出
当要将画布中的元素保存下来时,可调用 getNodes 方法,该方法会返回画布中的节点信息和连接线信息,导入时需要将这两组数据分别导入
同理,如果需要将两个图形连接起来,也可以定义一组 connects 进行导入(可参考 demo 中的示例)
// 获取节点信息
let { nodes, connects } = this.draw.getNodes();
// 导入
for (let i of nodes) {
this.draw.addNode(i);
}
for (let i of connects) {
this.draw.addConnect(i);
}
事件监听及回调
监听
当需要使用 addEventListener 监听某些事件时,请不要直接监听 canvas 元素,推荐监听父级元素,示例如下:
需注意:在鼠标按下并选中了某一个元素后,为了防止不必要的重绘,会渲染一层蒙版,所以鼠标抬起时将无法监听 up / move ... 等事件
<div id="canvasEvent">
<canvas id="canvas"></canvas>
</div>
document
.getElementById("canvasEvent")
.addEventListener("mousemove", (event) => {
console.log("move", event);
});
回调
创建画布时,传入第三个参数作为点击画布的回调,当选中图案时,会将选中的图案作为参数传入
import montage from "montage.js";
function checked(node) => {
console.log('checked node', node)
}
new Montage({
drag: true,
width: 300,
height: 300,
}, document.getElementById('board'), checked);
节点配置项及方法
画布配置
画布默认为静态画布,只用于展示添加的图案,同时内置了图案的拖拽方法,若需要对画布进行操作,需要将 drag 属性设置为 true
注意:此插件不提供画布整体拖拽 / 缩放功能,整体缩放 / 拖拽的实现可运行 example 后查看示例
| 属性 | 说明 | 可选值 | 默认值 | 类型 | | ------------ | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | width | 画布宽度 | - | - | number | | height | 画布高度 | - | - | number | | drag | 是否开启拖拽操作,如果关闭,则无法更新画布内的图案信息 | true/false | false | boolean | | highlight | 鼠标选中高亮设置(高亮效果取决于节点的 fillType 属性) | fillColor:高亮颜色; | { fillColor: 'rgb(0,217,255)', } | object | | defaultStyle | 默认的元素样式(可配置默认颜色/默认线宽,当使用自带的绘制方法去绘制图形时会非常有用) | fillColor:默认颜色;lineWidth:默认宽度(图案 fillType='stroke'时生效); zoomColor: 缩放框颜色;zoomWidth: 缩放框线宽;rotateColor: 旋转框颜色;rotateWidth: 旋转框宽度; connectColor: 连接点颜色 | { fillColor: 'rgba(0, 0, 0, 1)', lineWidth: 1, zoomColor: 'rgb(30, 0, 255)', zoomWidth: 1, rotateColor: 'rgb(30, 0, 255)', rotateWidth: 1,connectColor: 'rgb(19, 154, 251)' } | object |
画布方法
// 初始化
import Montage from "montage.js";
this.ctx = new Montage(
{
drag: true,
width: 300,
height: 300,
},
document.getElementById("board")
);
addNode: 往画布中添加节点
用于往画布中添加一个新的节点,可选值见节点配置项 type 属性
addNode(prop: object) // 传入要创建的节点属性
注意:这个操作是异步的,返回创建的节点信息
// prop 见节点配置项
// * 如果指定了节点id,那么在下一次加入相同id节点的时候,将覆盖之前创建的节点
this.ctx.addNode(prop).then((node) => {
console.log("new node", node);
});
getNode: 获取节点信息
获取当前选中的节点信息,或指定 id 的节点信息
注意:这将返回一个响应式对象,修改其属性时会自动修改画布内此节点的属性
// 传入节点 id,返回这个节点的实例
let node = this.ctx.getNode(id: string | null);
getNodes: 获取画布中的所有图案
获取画布当前状态下的所有图案
let {
nodes, // 当前画布中的所有节点
connects, // 当前画布中所有的连接线的信息集合
} = this.ctx.getNodes();
deleteNode: 删除某一节点
用于删除某一当前选中的节点,或是根据 id 删除节点
deleteNode(id: string | null) // 传入节点id
let nodeId = "id";
this.ctx.deleteNode(nodeId);
clearable: 清空画布中所有元素
清空整个画布
this.ctx.clearable();
reload: 重绘画布
用于重绘当前画布上的所有节点(刷新)
this.ctx.reload();
customDrawing: 创建自定义图案
根据图案路径去绘制自定义图案,区别于 addNode 方法,这个方法用于创建一个纯静态展示的复杂图案
注意:纯静态图案,仅用于展示,更新时需要使用 reload 方法更新画布
// 传入要绘制的图案路径信息,详见 自定义图案配置项
this.ctx.customDrawing(node: object)
// 这是一个绘制星星的示例
let custom = {
start: {
x: 200,
y: 200,
},
lineWay: [
[230, 100],
[260, 200],
[360, 230],
[260, 260],
[230, 360],
[200, 260],
[100, 230],
[200, 200],
],
fillType: "stroke",
fillColor: "rgba(200,200,100,0.8)",
};
this.ctx.customDrawing(custom);
addConnect: 配置两个不同节点间的连线
将两个图案使用连线进行连接,目前只支持曲线和箭头曲线两种连线
addConnect(connect: object) // 传入节点的连线信息
let connect = {}; // 详见连接线配置项
this.ctx.addConnect(connect);
setNodeType: 设置图案类型
// 传入图案类型, 自定义图案属性,及辅助属性, 无返回值
setNodeType(type: string, customProp: object | null, auxProps: object | null)
注意:只有在手动绘制图案时有效
用于设置即将在画布中绘制的图案类型
// type可选值为 rect: 矩形 / line: 线 / circular: 圆形
let type = 'rect';
// 自定义的节点属性,这些属性将被原封不动的保存在节点中
let customProp = {
prop1: 'xx',
prop2: 'xx',
...
};
// CanvasRenderingContext2D 的一些属性,实际使用频率较低,逐步开放中
// 目前仅支持 globalCompositeOperation
let auxProps = {
globalCompositeOperation: '', // 设置合成的操作类型,详见 https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
}
this.ctx.setNodeType(type, customProp, auxProps)
节点配置项
对于使用 getNode 方法获取的节点对象,插件内部使用 Proxy 来响应外界对节点的操作,为了防止频繁更改节点属性带来不必要的刷新,在节点更改完成后需要调用 reload 方法更新画布的展示效果
关于层级的说明:
- 图层按照层级从小到大排序,当点击位置包含多个图案,则会优先选中层级较大的图案
- 由于图片是异步加载,为了防止遮挡其他图案,加载时会置底,但是选取时仍会受到层级影响
- 当前选中的图案会默认置顶,取消选中后恢复原层级
| 属性 | 说明 | 可选值 | 默认值 | 类型 | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- | | id | 节点 id,每次添加节点时会自动验证是否重复当未填写 id 时,会自动填充,如果需要固定 id,请指定 | - | - | - | | type | 节点类型 | rect: 矩形circular: 圆形line: 线image: 图片 | - | string | | x, y | 起点 x 坐标, 起点 y 坐标 | - | - | number | | width, height | 图案宽高 | - | - | number | | src | 自定义图片路径(type='image'时生效) | - | - | string | | radiusX, radiusY | 自定义圆的半径(type='circular'时生效) | - | - | number | | endX, endY | 终点坐标(type='line'时生效) | - | - | number | | rotate | 旋转弧度,n*Math.PI | - | 0 | number | | level | 层级 | - | 1 | number | | zoom | 允许缩放/旋转(画布允许拖拽时生效) | true/false | false | boolean | | connect | 允许连线(画布允许拖拽时生效) | true/false | false | boolean | | drag | 允许拖拽(画布允许拖拽时生效) | true/false | true | boolean | | unClick | 禁止选中(当无法被选中时,将无法响应式的更新该图案配置,修改配置后需要先调用 deleteNode 方法删除,再调用 addNode 方法重新加载) | true/false | false | boolean | | unLight | 选中后禁止高亮 | true/false | false | boolean | | fillColor | 填充颜色 | color/rgb()/rgba() | rgb(0,0,0) | string | | fillType | 类别 | fill/stroke | stroke | string | | lineWidth | 宽度(fillType = 'stroke'时生效) | - | 1 | number | | textInfo | 文字信息 * 注意:文字换行可使用 /n 来处理,文字缩进可直接使用空格填充 | text: string, font: string(与 css font 属性用法相同), fillType: 'fill/stroke', fillColor: 'color/rgb()/rgba()' | - | object |
连接线配置项
连线用于配置不同图案之间的连接关系,目前仅支持曲线、剪头曲线;
需要注意:
- 在实际连线过程中,将每一个图形分成了上右下左四个方位,分别对应 1、2、3、4 号位置,节点中的 pos 属性为此位置的序号
- 需要确保开始节点和目标节点的已经存在并且 id 完全一致,否则会失效
| 属性 | 说明 | 可选值 | | ---------- | -------------------------------------------------- | ------------------------------------------------- | | id | 连接线 id | ----- | | lineWidth | 连接线宽度(注意:如果使用了箭头,不建议设置过大) | number | | fillColor | 连接线颜色 | string | | startInfo | 开始节点的信息 | {id: 开始节点的 idpos: 开始的位置} | | targetInfo | 目标节点的信息 | {id: 目标节点的 idpos: 结束的位置} |
自定义图案配置项
用于创建一个纯静态的自定义图案,由于是根据路径绘制的,所以这个图案可以是一个复杂图形 | 属性 | 说明 | 可选值 | | --- | --- | ----- | | start | 开始位置 | { x, y } | | lineWay | 绘制的路径,将按照路径顺序进行绘制 | [[x, y], [x1, y1], ...] | | fillType | 图案类型 | fill: 实心 / stroke: 空心 | | fillColor | 图案颜色 | rgba() | | lineWidth | 线宽,在 filleType = 'stroke'时生效 | number |