头图

前言

最近项目中需要用到图形编辑工具,综合考虑下使用了paperjs。感谢 @jackwang的文章二维绘图库-paper.js踩坑指南,避免了很多坑,当时在实战项目中依然发现到一些问题。

项目中使用paperjs完成了一个图形框选工具,支持矩形、多边形、多点、线、虚线工具,功能上有框选、编辑、标签、位移、边界约束、缩放、放大镜、辅助线等常用功能 。

paperjs层级关系


开始之前一定要熟悉paper的项目层次结构避免coding时无从下手!!!

  1. 项目初始化paper.setup()后,paperjs将自动创建一个active状态的project和子属性layer,而tool需要自行添加。
  2. 注意project和layer的激活,只有激活了当前项才会改变。
  3. group分组可有可无,可以直接将path、text、raster放到layer中(如果项目中创建的物体包含多个path、text,建议使用group以便集中统一管理)

raster


 const raster = new paper.Raster({
        // source: 'https://xxxxxx.jpg',
        // source:`data:image/jpg;base64,xxxxxxxxxxxx`
        // image: document.getElementById('img'),
        // crossOrigin: 'anonymous',
        visible: false,
        name: 'raster',
        onLoad: e => {},
        onError: e => {},
      });

source: 这个参数可传入URL,也可以传入base64,base64格式一定要注意前面加上”data:image/jpg;base64“
crossOrigin: canvas对外链图片有跨域问题,如果提示’Access-Control-Allow-Originxxxxxxx‘可自行尝试.
onLoad: 最坑的一个!
多图切换:假设两张图片A、B,当切换图片时,每次都要调用new paper.Raster(),初次加载A可以通过onLoad参数获取到图片信息,这是我们切换到B图片依旧通过onLoad参数获取到图片信息,但是在切换到已加载过的A时onLoad会返回图片信息为null,通过查阅源码发现其根据complete判断是否加载过当前图片以节约性能。源码逻辑可见paper-full.js _setImage() 约5514行。
解决方案:通过 const raster = new paper.Raster({的raster变量来读取信息
visible: (优化)多图切换是会出现短暂画布空白或图片尺寸瞬间变大的情况,这是因为画布默认加载出示图片大小,
解决方案:默认visible为false在onLoad中重新计算图片大小后在恢复visible即可

point区域内检测

Rectangle、Path、等绘制图形需要加上fillColor才能进行区域内检测,
如果想要透明形状并且需要区域内检测,设置透明值即可item.fillColor.alpha = 0.0001;
检测点是否在图形范围内hitTest(point)

带有背景的文本

paperjs没有自带的文本背景功能需要自行添加

const text = new paper.PointText({
      content: content,
    });
const bg = new paper.Path.Rectangle({
      point: text.bounds.point,
      size: text.bounds.size,
      fillColor: '#cccccc',
    });

其他


获取选中的select索引:获取当前点击手柄的索引 e.location.index
id、查找匹配不要使用item自带的id!,item.id在操作中很可能会自动变更,所有关联数据放到data中,查找使用LAYER.getItem({xxx: xxx})
clone复制: clone后的item默认插入到激活的layer中,如果想要插入到其他位置,Hierarchy Operations下的api
清空画布:paper自带了清空画布api,但是文档未说明paper.remove();
获取多个图形的bounds:将多个item编组,获取编组的Group.bounds
冒泡问题:item绑定的事件可以使用e.stopPropagation();阻止叠加的item触发事件,但是tool工具不受影响
快去获取:给item设置名称(可重复),item.name = 'testName',

const testName = group.children['testName']
或
const { testName } = group.children

image.png


,,,
12 声望0 粉丝