基于fabricjs搭建canvas画布 - 画布下载
下载画布
现在我们的画布上已经有了很多元素,各种操作结束后我们如何把编辑的效果下载下来呢?
fabric针对canvas提供了toDataURL的API可以以base64格式输出画布数据, 我们基于这个api来实现画布下载的功能
在这之前首先我们基于a标签的download来实现一个基础的下载能力,
// 下载功能
let a = document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("download", name);
a.setAttribute("target", "_blank");
a.setAttribute("id", "downLoad");
a.click();
接着我们来调用toDataURL,将返回的base64赋值给a标签的href
const baseimg = canvas.toDataURL()
// 下载功能
let a = document.createElement("a");
a.setAttribute("href", baseimg);
a.setAttribute("download", 'test.jpg');
a.setAttribute("target", "_blank");
a.setAttribute("id", "downLoad");
a.click();
但这个时候我们就会发现下载下来的图片有些不对,那是因为默认下来下来的只是当前屏幕内的, 所以我们需要在toDataURL的时候对画布进行剪切。也就是说我们需要算出画布上所有元素的范围,然后用这个范围对画布进行裁剪,再下载裁剪后的画布。上代码
/**
* 下载画布
*
* @param {string} type 可以下载的图片格式
*/
const outputImg = (type) => {
type = type || "jpeg";
// 通过偏移量、宽高处理全图
const all = this.getAllObject();
// 计算画布元素边界
const maxleftObj = _.maxBy(all, (o) => {
return o.left;
});
const minleftObj = _.minBy(all, (o) => {
return o.left;
});
const maxtopObj = _.maxBy(all, (o) => {
return o.top;
});
const mintopObj = _.minBy(all, (o) => {
return o.top;
});
// 剪切画布, 输出画布数据base64格式
// console.log(111, minleftObj, minleftObj.left, mintopObj, mintopObj.top);
const baseimg = this.canvas.toDataURL({
format: type,
quality: 1,
// multiplier: this.zoom,
withoutTransform: true,
left: minleftObj.getBoundingRect().left,
top: mintopObj.getBoundingRect().top,
width: (maxleftObj.left - minleftObj.left + maxleftObj.width) * this.zoom,
height: (maxtopObj.top - mintopObj.top + mintopObj.height) * this.zoom,
});
this.canvas.requestRenderAll();
// 下载功能
let a = document.createElement("a");
a.setAttribute("href", baseimg);
a.setAttribute("download", `${Date.parse(new Date())}.${type}`);
a.setAttribute("target", "_blank");
a.setAttribute("id", "downLoad");
a.click();
}
到这里我们已经实现了一个画布的基础能力,基于这些能力我们就可以做很多事。但这里还有很大的优化空间。比如图片数据量大的时候如何提高canva的渲染能力,虽然fabric内部已经做了离线渲染,但其实我们依旧可以针对元素进行可是区域内外的分批渲染等