基于fabricjs搭建canvas画布 - 画布下载

355 阅读2分钟

基于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内部已经做了离线渲染,但其实我们依旧可以针对元素进行可是区域内外的分批渲染等

上一篇: 基于fabricjs搭建canvas画布 - 画笔、橡皮擦 - 掘金 (juejin.cn)