仿写设计编辑器第四天

97 阅读2分钟

今天完成了canvas对象的锁定,删除复制,整个画布的清空,和保存画布为JSON文件,SVG,复制到剪贴板,保存为图片,还实现了返回上一步操作

选中对象的锁定

使用Element-ui的switch组件,使用v-model绑定switch的开关值,判断是否选中canvas对象,来决定开关是否可用,给event实例上绑定的selectOne上事件设定回调,每次选中单个元素是,就拿到当前选中元素的hasControls的属性值并赋值给switch的开关值,使每次选中对象时都可正确显示开光,点击开关时绑定事件,改变选中对象的可控属性,把选中元素的hasControls属性取反可以使对象无法改变大小,并且给选中对象的lockMovementX(Y,Z)设置为当前的开关的值,可以是选中对象无法移动

created() {
    this.event.on("selectOne", (item) => {
    if (this.isLocked !== "undefined") {
        this.isLocked = !item[0].hasControls;
       }
    });
},

methods: {
isSelected() {
    return this.mSelectMode !== "one";
},
changeLock() {
    const activeObject = this.canvas.c.getActiveObject();
    // 改变选中对象的大小是否可设置属性
    activeObject.hasControls = !activeObject.hasControls;
    // 取消选中
    this.canvas.c.discardActiveObject().renderAll();
    // 修改选中对象的是否可以移动属性
    lockAttrs.forEach((item) => {
        activeObject[item] = this.isLocked;
        });
    },
},

复制元素

使用fabric.js的clone方法克隆后添加到画板即可

copySelected() {
const activeObject = this.canvas.c.getActiveObject();
// 克隆选中的对象
activeObject.clone((cloned) => {
    this.canvas.c.discardActiveObject();
    cloned.set({
        left: cloned.left + 10,
        top: cloned.top + 10,
        id: uuid(),
    });
    // 添加克隆的对象
        this.canvas.c.add(cloned);
        this.canvas.c.renderAll();
    });
},

清空画板

使用fabric.js的clear方法即可清空画板

clear() {
    this.canvas.c.clear();
},

保存画板

使用Element-ui的## Dropdown下拉菜单来实现ui,el-dropdown里面可以绑定command事件,可以根据el-dropdown-item的command属性来判断点哪个下拉菜单

复制到剪贴板

copyToClipboard() {
    const jsonStr = this.canvas.c.toJSON(["id"]);
    this._mixinClipboard(JSON.stringify(jsonStr, null, "\t"));
},

// 复制
import VueClipboard from "vue-clipboard2";
_mixinClipboard(clipboardText) {
    this.$copyText(clipboardText).then(() => {
        this.$message('复制成功');
    }, () => {
        this.$message('复制失败');
    })
},

保存为图片,svg文件,json文件

拿到文件路径后,生成一个a标签,把生成的路径给元素的herf,然后使用a.download下载路径文件

// 下载文件

downFile(fileUrl, fileType) {
    const a = document.createElement("a");
    a.href = fileUrl;
    a.download = uuid() + "." + fileType;
    a.click();
    a.remove();
},

保存为图片

saveToImg() {
       //图片设置
    const option = {
        name: "New Image",
        format: "png",
        quality: 1,
        multiplier: 2,
    };
    const dataUrl = this.canvas.c.toDataURL(option);
    this.downFile(dataUrl, "png");
},

保存为SVG文件

saveToSvg() {
    const svgUrl = this.canvas.c.toSVG();
    // encodeURIComponent() 函数
    // 作用:可把字符串作为URI 组件进行编码。其返回值URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。
    const fileStr = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(
        svgUrl
    )}`;
    this.downFile(fileStr, "svg");
},

保存为JSON文件

saveToJSON() {
    const jsonUrl = this.canvas.c.toJSON();
    const fileStr = `data:text/json;charset=utf-8,${encodeURIComponent(
        JSON.stringify(jsonUrl, null, "\t")
    )}`;
    this.downFile(fileStr, "json");
},

返回上一步操作

思路:创建两个队列一个保存之前的canvas(backList),一个保存返回之前的canvas(toList),给canvas绑定事件: 先将改变前的canvas加入backList object:modified,selection:updated,但更改canvas对象时,使用push将当前canvas对象加入backList(json格式),当用点击返回上一步时,使用splice(backList.lenght,1)[0],拿到改变前的json对象,然后使用loadFormJSON()使用拿到的对象渲染画布,之后使用pop()拿到当前的json对象,把这个对象push到toList,点击前进时使用pop()拿到toList的最后一个json对象,使用这个对象渲染画布

mounted() {
    this.$nextTick(() => {
        this.backList = this.$backList;
        this.canvas.c.on({
        "object:modified": this.save,
        "selection:updated": this.save,
    });
});
methods: {
// 保存纪录
save() {
    const item = this.canvas.c.toJSON("id");
    if (this.backList.length == maxNum) {
        this.backList.shift();
    }
    this.backList.push(item);
},

// 后退
back() {
if (this.backList.length) {
// 拿到返回队列最新添加的元素
    const item = this.backList.splice(this.backList.length - 2, 1)[0];
    this.renderCanvas(item);
    // 将本次加入队列
    const item2 = this.backList.pop();
    this.goList.push(item2);
    }
},

// 前进
go() {
    if (this.goList.length) {
    const item = this.goList.pop();
    this.renderCanvas(item);
    this.backList.push(item);
  }
},

// 渲染
renderCanvas(json) {
    this.canvas.c.clear();
    this.canvas.c.loadFromJSON(
        json,
        this.canvas.c.renderAll.bind(this.canvas.c)
    );
        this.canvas.c.requestRenderAll();
    },
},