博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Fabric.js高级点的教程4--内嵌工作台画布
阅读量:7047 次
发布时间:2019-06-28

本文共 4143 字,大约阅读时间需要 13 分钟。

hot3.png

额。。这是我自己创造的名词,内嵌工作台画布

要实现什么效果

如图():

首先想元素脱出画布外一部分也能选中,如图上面就没法选择超出框外的内容。我想到的是如何在画布中间加个画布。周围隐藏掉。

实现思路

  1. 首先创建一个足够大的画布
  2. 设置一个padding
  3. 通过padding 计算中间白色区域四个角的坐标
  4. 在周围画上四个矩形盖住(也可以画一个大矩形,把中间的挖掉,由于各种需求和测试问题没有采用这种方式)
  5. 每次添加新的元素在上面的时候都保持周边四个区域在最上面

其他思路

  1. 使用clipPath,画一个通道给中间区域。
  2. 画两个画布一个再上面一个在下面 其实这些方法可能都能实现,但是问题的关键不是实现,而是如何兼容之后的诸多行为,比如zoom,loadJson,redo, undo

代码

1.先定义一个想要的外边距padding,然后计算内部工作台处于外部画布的四个点的位置。

// 获取中间画布的四个点的位置function setXY(state, obj = {}) {  // 最外边整个画布的宽 高  const w = obj.currentWidth || state.currentWidth   const h = obj.currentHeight || state.currentHeight  // 内部工作台画布的宽pannelW 高pannelH  if (    state.currentWidth / state.currentHeight >    state.pannelW / state.pannelH  ) {    const height = h - state.padding    // 缩放画布,因为pannelW为实际宽度,比如一张A4纸显示在屏幕上,需要缩放一下,zoom后获取到屏幕的宽度    state.zoom = height / state.pannelH    this.commit('zoomCanvas')    const x2 = 0    const y2 = 0    const y0 = state.padding / state.zoom / 2 + y2    const y1 = state.pannelH + y0    const x0 = w / state.zoom / 2 - state.pannelW / 2 + x2    const x1 = state.pannelW + x0    state.arrX = [x0, x1, x2, w / state.zoom + x2]    state.arrY = [y0, y1, y2, h / state.zoom + y2]  } else {    const width = w - state.padding    state.zoom = width / state.pannelW    this.commit('zoomCanvas')    const x2 = 0    const y2 = 0    const x0 = state.padding / state.zoom / 2 + x2    const x1 = state.pannelW + x0    const y0 = h / state.zoom / 2 - state.pannelH / 2 + y2    const y1 = state.pannelH + y0    state.arrX = [x0, x1, x2, w / state.zoom]    state.arrY = [y0, y1, y2, h / state.zoom]  }}

2.创建四周的遮罩,给中间的区域,画个背景

function createMask(state) {  const arrX = state.arrX  const arrY = state.arrY  const pathOption = {    selectable: false,    fill: '#ebeced',    hoverCursor: 'default',    evented: false,    excludeFromExport: true,    hasControls: false,    perPixelTargetFind: false,    strokeWidth: 0,    stroke: null  }  const rect1 = new fabric.Rect({    width: arrX[0] - arrX[2],    height: arrY[3] - arrY[2]  })  const rect2 = new fabric.Rect({    width: arrX[3] - arrX[0] + 2,    height: arrY[0] - arrY[2]  })  const rect3 = new fabric.Rect({    width: arrX[3] - arrX[1],    height: arrY[1] - arrY[0] + 2  })  const rect4 = new fabric.Rect({    width: arrX[3] - arrX[0],    height: arrY[3] - arrY[1]  })  rect1.set({    left: arrX[2],    top: arrY[2],    name: 'mask1',    ...pathOption  })  rect2.set({    left: arrX[0] - 1,    top: arrY[2],    name: 'mask2',    ...pathOption  })  rect3.set({    left: arrX[1],    top: arrY[0] - 1,    name: 'mask3',    ...pathOption  })  rect4.set({    left: arrX[0],    top: arrY[1],    name: 'mask4',    ...pathOption  })  state.maskPath = new fabric.Group([rect1, rect2, rect3, rect4], {    selectable: false,    excludeFromExport: true,    lockMovementX: true,    lockMovementY: true,    lockRotation: true,    lockScalingX: true,    lockScalingY: true,    lockUniScaling: true,    hoverCursor: 'auto',    name: 'grid',    left: arrX[2],    top: arrY[2],    type: 'sMask',    evented: false  })  // 创建中间画布的背景  state.backgroundPanel = new fabric.Rect({    left: arrX[0],    top: arrY[0],    selectable: false,    evented: false,    width: state.pannelW,    height: state.pannelH,    strokeWidth: 0,    fill: !state.activePage ? '#ffffff' : 'rgba(0, 0, 0, 0)',    objectCaching: false,    hoverCursor: 'default',    excludeFromExport: true,    hasControls: false,    type: 'sBg',    perPixelTargetFind: false  })  state.canvas.remove(...state.canvas.getObjects('sMask'))  state.canvas.remove(...state.canvas.getObjects('sBg'))  state.canvas.add(state.maskPath)  state.canvas.add(state.backgroundPanel)  state.canvas.sendToBack(state.backgroundPanel)  state.canvas.renderAll()}

3.刷新画布,或者加载数据的时候

jsonDemo.objects.forEach((item) => {    item.left += state.arrX[0]    item.top += state.arrY[0] })

4.保存json

function saveJson(state) {  // state.toJSONProperties 为要保存的额外属性  const jsonStr = JSON.stringify(state.canvas.toJSON(state.toJSONProperties))  const jsonObj = JSON.parse(jsonStr)  jsonObj.objects.forEach((v) => {    v.left = v.left - state.arrX[0]    v.top = v.top - state.arrY[0]  })}

 

转载于:https://my.oschina.net/xmqywx/blog/3047028

你可能感兴趣的文章
图灵奖的背后
查看>>
iOS-网络基础
查看>>
phonegap中使用自带浏览器打开链接
查看>>
java web接口controller测试控制台输出乱码
查看>>
spring mvc实现自定义注解
查看>>
iis 网页HTTP 错误 404.3 - Not Found解决方案
查看>>
【英语-刘晓艳-词汇】词汇05
查看>>
Java IO(3)
查看>>
AIX 下的 find 命令使用
查看>>
linux之SQL语句简明教程
查看>>
码农们:我们才是真正的土豪!
查看>>
jmeter3.2版本如何进行webservice接口功能测试
查看>>
线段树 区间更新 和 查找时更新时候的探讨。
查看>>
ELKF(Elasticsearch+Logstash+ Kibana+ Filebeat) 部署
查看>>
JS对象操作
查看>>
个人作业 数独
查看>>
将MySQL数据库转移到SqlServer2008数据库
查看>>
Mongodb for .Net Core 驱动的应用
查看>>
js生成二维码
查看>>
009-你觉得测试和开发需要怎么结合才能使软件的质量得到更好的保障
查看>>