基于fabric.js的图片编辑器, 画布背景实现原理

  • 基于fabric.js的图片编辑器, 画布背景实现原理已关闭评论
  • 58 次浏览
  • A+
所属分类:Web前端
摘要

使用了element-plus提供的图片上传el-upload组件图片上传支持两种元素,普通图片元素和背景图片元素,所以定义属性type进行区分

基于fabric.js的图片编辑器, 画布背景实现原理

图片上传

使用了element-plus提供的图片上传el-upload组件

<el-upload :show-file-list="false" :auto-upload="false" :on-change="(e) => uploadImage(e, 'background')" >    <button class="right-canvas-resize-btn">上传图片</button> </el-upload>Ï 

图片上传支持两种元素,普通图片元素和背景图片元素,所以定义属性type进行区分

type为Image为普通图片, background为背景

背景也是一张图片,使用fabric.Image创建图片元素

因为没有图片服务器所以把上传的文件转换了base64图片,作为fabric图片的链接

需要区分上传类型type, 不同类型的图片走不同逻辑

fileUpload = async (file: File, name: string, type: string) => {     const src = await this.handler.utils.fileToBase64(file);     if (src) {       const image = new Image();       image.src = src;       const options: any = {         name,         type,         src,       };       await new Promise((resolve) => {         image.onload = () => {           options.width = image.width;           options.height = image.height;           resolve(true);         };       });       let marterialObject;       if (type == "background") {         marterialObject = this.handler.workareaHandler.setBgImage(options);       } else {         marterialObject = this.handler.add(options);       }       return marterialObject;     }  } 

背景设置原理

背景图片和普通图片的区别

  1. 不能选中,不能移动,不能修改,没有操作控件

给背景元素添加以下属性

        hasControls: false,         hasBorders: false,         selectable: false,         lockMovementX: true,         lockMovementY: true,         lockScalingX: true,         lockScalingY: true 
  1. 背景需要自适应画布

计算规则如下

  • 获取宽高比例最大值作为元素缩放值,目的是图片元素保持宽高比例不变的情况下覆盖画布
  • 根据缩放值计算图片最新宽高,需要基于画布居中展示
  • 水平居中规则如下,垂直居中同理

基于fabric.js的图片编辑器, 画布背景实现原理

 _getBgPosition(bgObject: FabricImage | any) {     const { width, height } = this.workspace as any;     let scale = 1;     if (width > bgObject.width || height > bgObject.height) {       if (width / bgObject.width > height / bgObject.height) {         scale = width / bgObject.width;       } else {         scale = height / bgObject.height;       }     }     // 居中     const bgHeight = bgObject.height * scale;     const bgWidth = bgObject.width * scale;     const bgLeft = width / 2 - bgWidth / 2;     const bgTop = height / 2 - bgHeight / 2;     return {       left: bgLeft,       top: bgTop,       scaleX: scale,       scaleY: scale,     } 
  1. 背景图片支持修改,所以上传时需要把画布中的背景元素给移除
 // 获取背景元素   getBgObject() {     return this.handler.canvas.getObjects().find((item: any) => {       if (item.type == "background") {         return item;       }     });   }      // 去重, 防止出现多个背景元素    const bgObject = this.getBgObject();    if (bgObject && bgObject.src !== src) {       this.handler.canvas.remove(bgObject);    } 

基于fabric.js的图片编辑器, 画布背景实现原理

  1. 背景元素永远置底,但比画布高一层,所以先置底再上移一层
      this.canvas.sendToBack(this.bgObject);       this.canvas.bringForward(this.bgObject); 
  1. 画布中有元素层级的逻辑,所以当我们选中某个元素的时候需要保持原有层级,但是fabric.js默认是对象在选中时不保持在当前堆栈位置

所以我们需要在初始化画布时指定保留层级

preserveObjectStacking: true

完整代码如下

async setBgImage(options: WorkareaOption) {     const { src } = options || {};     const editable = false;     const option = {       editable,       hasControls: editable,       hasBorders: editable,       selectable: editable,       lockMovementX: !editable,        lockMovementY: !editable,       lockScalingX: !editable,       lockScalingY: !editable,       hoverCursor: "default",       name: "背景图片",       type: "background",       src,     };     // 去重, 防止出现多个背景元素     const bgObject = this.getBgObject();     if (bgObject && bgObject.src !== src) {       this.handler.canvas.remove(bgObject);     }     const poiOptions = this._getBgPosition(options);     const newOptions = Object.assign({}, option, poiOptions);     this.bgObject = await this.handler.add(newOptions, false);     if (this.bgObject) {       this.canvas.add(this.bgObject);       this.canvas.sendToBack(this.bgObject);       this.canvas.bringForward(this.bgObject);     }     this.canvas.requestRenderAll();     return this.bgObject;   } 

背景的翻转、分离、删除

支持背景图片的翻转、分离、删除

基于fabric.js的图片编辑器, 画布背景实现原理

翻转

修改背景元素的scaleX属性,默认为水平翻转{ scaleX: -1 }

分离

修改背景元素为图片元素

  • type修改为Image
  • 支持选中,移动,修改,有操作控件, 把上文的hasControls等字段取反即可

删除

基于fabric提供的删除方法 this.canvas.remove(target);

简介

vue-design-editor 是仿搞定设计的一款开源图片编辑器, 支持多种格式的导入,包括png、jpg、gif、mp4, 也可以一键psd转模板(后续开发)

github地址 预览

上个开源库是 vue-form-design基于Vue3的可视化表单设计器,拖拽式操作让你快速构建一个表单, 让表单开发简单而高效。

github地址 预览