最近写一个批改的功能,用canvas的原生api真的太吃力了,之后了解到fabric这个库,好用是好用,但是真的踩了很多坑,能百度的资料少之又少,真的是一步一步踩着泥路走过来。
首先项目中引入vue-fabric
vue-fabric gitHub地址
里面有教程和基本api用法,下面是记录项目我踩的坑,我觉得这些坑还是挺有代表性的。
一.画布初始化
图片宽高固定的情况下,直接赋初始值,进行初始化
如果是动态宽高的话,首先动态获取宽高加载图片,画布用v-if进行判断,获取到高度再进行初始化
这种仅针对单张图片处理
let img = new Image();
img.src = 获取的图片地址+'?'+Math.random();
img.setAttribute("crossOrigin",'Anonymous'); //解决图片跨域问题
img.onload = ()=>{
let imgHeight = img.height; //获取宽高
let imgWidth = img.Width;
}
加载完成之后使用createImageByImg这个api绘制图片,createImage这个绘制到时候生成图片的时候会有跨域问题。
二.绘制多张图片
多张图片按顺序绘制,需要同步执行,所以我用的是async/await来处理这个问题。
绘制多图时,高度跟宽度不确定情况下,是没法按1:1比例初始化画布的,如果像上面那种方法去获取,会导致插件画布内外层宽高不一致,导致图片绘制异常,或者显示异常,这里处理的方法就是先固定画布宽度,对图片进行一个1:1显示或者缩放。
for (let i = 0; i < this.ImgFiles.length; i++) {
await this.doIt(i); //遍历图片数组 按顺序加载绘制
}
doIt(index) {
let scale = 1;
let height = 0;
let img = new Image();
img.src = this.answerFiles[index] + '?' + Math.random();
img.setAttribute("crossOrigin", 'Anonymous');
return new Promise((resolve, reject) => {
//对图片进行处理
img.onload = () => {
if(img.width>this.canvasWidth){
//大于画布宽度 进行缩放
scale = Number((this.canvasWidth / img.width).toFixed(1));
height = scale * img.height;
//加入数组,之后进行绘制
this.arr.push({
img,
option: {
height,
scale,
width: this.canvasWidth
}
})
}else{
//小于的话,1:1显示
this.arr.push({
img,
option: {
height,
scale,
width: this.canvasWidth
}
})
}
}
}
}
三.清空全部路径不清除画布
组件封装的api有清空功能,只要是画布上的对象,全部都清空了,点个清空,批阅的卷子一下也清掉了,这不扯淡吗,在我仔细阅读了作者封装的组件api后,发现他没有这个部分清空api,哭哭,好在有个事件方法获取画布上面所有的对象,然后可以进行区分选择性清除(机智如我),看来,那只有自己造轮子了(狗头)。
图片类型是image,在图片上进行打分,这个画笔路径的type是path,这样我们根据类型来区分是不是就可以将图片和路径或者文字区分出来了。
区分出来了,突然又懵逼了!麻蛋(不是脏话)来回翻了几次文档,只找到
removeCurrentObj() 删除当前选中对象
这个api,而且看了下也无法传参进去进行指定删除,这api就是鼠标hover到元素上面,点击一下就删除,我lay了怎么这么曲折啊,郁闷了一会,又振作起来,想了下,这个api应该就是获取当前对象进行删除的,然后我看了下组件源码,果不其然,来人!拿我的斧头来,继续开造!
getActiveObject()应该就是鼠标hover到上面的元素,获取到之后进行remove操作
害,不就是获取对象嘛,上面我们已经获取到了要移除的对象,现在要做的事情就是传参进去,随手一改,so easy!
然后进行调用就行,因为要改源码,我是把这个组件抽离到我本地项目开发的,你要是在node_modules里面改可是没用的哦~哈哈
待更新…