客户提供一个楼层平面图,需要对图片进行一些标注和系统中的房屋数据进关联。
因为之前没有接触过Canvas,所以感觉这事搞不出来。奈何领导说别人能做出来你就做不出来。最后是在是没办法了,我就说我试试吧。然后我就不停的百度,最后发现了一个Canvas辅助工具库Fabric.js
,基本上解决了我的难点和痛点,剩余的问题只有遇到再解决了。
Fabric 是一个强大而简单的 JS Canvas 库,我们能通过使用它实现在 Canvas 上创建、填充图形、给图形填充渐变颜色。组合图形(包括组合图形、图形文字、图片等)等一系列功能。简单来说我们可以通过使用 Fabric 从而以较为简单的方式实现较为复杂的 Canvas 功能。
不设置为背景图的话,图片就相当于画布上的一个元素可以来回移动,还会存在着层级问题
)// 设置画布背景图
setCanvasBackground(imgUrl) {
fabric.Image.fromURL(imgUrl, image => {
// 设置图片背景在水平方向上的缩放比例
image.scaleX = this.canvas.width / image.width;
// 设置图片背景在竖直方向上的缩放比例
image.scaleY = this.canvas.height / image.height;
this.canvas.setBackgroundImage(image);
//重新渲染画布
this.canvas.renderAll();
});
},
序列化和反序列化
)//序列化,可以将整个Canvas画布上的所有元素通过JSON数据进行存储,
this.canvas.toJSON(["houseId", "houseName", "linkObj"])
//反序列化,根据Json数据,在画布上重新绘制出来
this.canvas.loadFromJSON(jsonInfo);
你自己添加的都是一个元素对象,给对象增加你需要的属性即可,注意在序列化的时候需要告诉canvas你需要哪些对象
)//如果想要拿到用户自定义的数据,需要以数组的形式传递即可。
this.canvas.toJSON(["houseId", "houseName", "linkObj"])
fabric组的概念
)//创建圆圈文字组合
createCircleGroup(top, left) {
let circle = new fabric.Circle({
radius: 40,
//使文字保持水平垂直居中
originX: "center",
originY: "center",
fill: 'red',
statefullCache: true //修改元素后进行更新
});
let text = new fabric.Text("暂未设置", {
//绘制文本
fontSize: 13,
//使文字保持水平垂直居中
originX: "center",
originY: "center",
statefullCache: true //修改元素后进行更新
});
//进行组合
let group = new fabric.Group([circle, text], {
top,
left,
statefullCache: true //修改元素后进行更新
});
//组合添加到画布上
this.canvas.add(group);
}
let polyline = new fabric.Polyline(points, {
stroke: "red",
fill: 'red',
originX: "center",
originY: "center",
statefullCache: true //修改元素后进行更新
});
// 获取绘制图形的中心点坐标,
let obj = polyline.getCenterPoint();
let text = new fabric.Text("暂未设置", {
//绘制文本
left: obj.x - 30, //横坐标再减去文本的长度,默认为30
top: obj.y,
fontSize: 13,
statefullCache: true //修改元素后进行更新
});
//进行组合
let group = new fabric.Group([polyline, text], {
statefullCache: true //修改元素后进行更新
});
this.canvas.add(group);
不能跳过目标检测,将每个元素的selectable设置为false
) this.canvas = new fabric.Canvas("c", {
isDrawingMode: false, //绘画模式
fireRightClick: true, // 启用右键,button的数字为3
stopContextMenu: true, // 禁止默认右键菜单
selection: true, //
skipTargetFind: false //不能跳过目标检测,否则获取不到元素身上的自定义属性
});
if (mapMsg) {
mapMsg = JSON.parse(mapMsg);
// 为每一个元素添加不能选中的属性,元素对象不能移动
mapMsg.objects.map(v => {
v.selectable = false;
});
this.transformJsonToCanvas(mapMsg);
}
很多细节上的实现参考如下(很全、很细、很贴心):Fabric.js专栏