二维绘图库-paper.js踩坑指南

本文只是一个paper.js的使用注意事项,能够算是踩坑指南,不是翻译文档,有问题能够留言交流。javascript

前言

最近在搞一个图形框选工具,支持矩形、椭圆、多边形框选,同时须要限定范围,写本篇目的是看国内中文资料不多,将此次踩坑指南记录一下,便于你们交流;具体操做为首先在一张图片框选一个范围做为限定范围,而后第二我的再次进行框选,只能在第一我的指定的方位框选,限定范围和框选范围均支持三种类型,以下图所示中间透明区域即为限定范围,绿色即为框选范围(图片来自网络)html

pastedImage.png

方案选择

fabric.js:这个框架支持鼠标进行矩形和椭圆形的框选以及变换,我尝试在这个框架的基础上进行多边形框选,以及限定范围的处理,发现本框架扩展较差,不太适合此场景java

原生js:尝试原生,能很快的实现想要的功能,可是对于边界的检测,图形的交叉检测本身写有点费劲git

paper.jstwo.js:均为二维图形绘制库,对比了两个库github的star,以及示例,选择了paper.jsgithub

paper.js踩坑

js调用与PaperScript调用区别

首先要注意的是,关于使用PaperScriptjs调用他的api的区别,我直接使用的js来进行调用,主要须要注意的点以下(paperScript代码不放)canvas

  1. 须要调用方法paper.setup(canvas)或者new Project(canvas)来建立一个空的projectview
  2. 须要在元素加载完毕后,再建立paper project,也就是须要后端

    window.onload = function() {
            var canvas = document.getElementById('myCanvas');
            paper.setup(canvas);
        }
  3. 关于工具,对于PaperScript的工具使用则能够直接使用事件,使用js须要本身建立工具,如api

    var tool = new Tool();
        var path;
        tool.onMouseDown = function(event) {
            path = new Path();
            path.strokeColor = 'black';
            path.add(event.point);
        }
        tool.onMouseDrag = function(event) {
            path.add(event.point);
        }
  4. 关于运算,不少官方示例给出的为+,-,*,/,实际上咱们使用js操做会出现报错,此时咱们应该采用向量的add,subtract,multiply,divide方法来进行代替,以下网络

    var vector = point2 - point1; // paperScript写法
    var vector = point2.subtract(point1); // js写法

参考连接:http://paperjs.org/tutorials/...框架

向量的概念

向量是这里边很重要的一个概念,理解了向量的概念对于绘图以及操做动画轨迹我认为是很重要的一个功能(具体能够看下方资料),此处我只说一点,就是Point自己其实就是表明一个向量,如图

point1point2均为向量,这个其实表明了他们的相对于远点也就是canvas左上角的向量值

若是咱们想把point1移动到point2那么,其实首先向右移动60,而后向下移动50

那么此时咱们有一个更简单的方法,就是经过向量

var vector = point2 - point1;
// = { x: 110, y: 200 } - { x: 50, y: 50 }
// = { x: 60, y: 150 }

这样作减法,咱们就获得了一个向量,也就是说point1point2是绝对位置,而vector则为相对位置,经过这个方式咱们获得了vector,此时咱们能够获得他的长度和角度,帮助咱们完成一些必要的运算

console.log(vector.length);
// 161.55494
console.log(vector.angle);
// 68.19859

经过向量,咱们则能够对点的位置进行操做和处理

参考中文资料:https://www.microheart.me/pap...
参考官网资料:http://paperjs.org/tutorials/...

绘制层级

存在图层的概念,相似于PS工具的层级关系

  • PaperScope1

    • project1(操做对象)

      • layer1(图层)

        • Path(路径)
        • Group(组)
        • Shape(图形)
      • layer2
    • project2
  • PaperScope2

可是此处有几个点须要注意

  1. 当图形实例化时,默认状况是自动会加入到当前活跃的对象(paper.project)中活跃的图层(project.activeLayer)当中,若是须要设置,须要本身处理配置
paper.settings.insertItems // 是否将新建的Item插入到活跃的图层中
  1. 对于图形和路径,虽然都存在椭圆和矩形等形状,可是他们的一些属性操做是不一样的,最容易被坑的就是size属性,这个对于Shape是有的,可是Path没有,必定注意下图的Properties的不一样,避免踩坑

1586158265902.jpg

  1. 实例化Project后会默认加到全局的paper.projects当中,并做为一个被激活的project,若是存在多个project,请处理处理多个project的活跃关系,避免出现想要往一个project里边加,可是却致使加到另一个里边,激活一个对象的方法为(若是insertItems为默认值true,这个问题易出现)
project.activate(); // 使用当前对象绘制图形

绘制工具

paper.js的工具就是处理鼠标和键盘事件,同时当实例化Tools时会加入到全局,若是存在多个Tools也应该注意,避免多个监听事件使用出现问题

var tool1 = new Tools();
var tool2 = new Tools();

tool1.onMouseUp = () => {
    console.log('tool2');
};

tool2.onMouseUp = () => {
    console.log('tool2');
}

tool1tool2均会放在paper.tools当中,同一时间只能有一个工具生效,也就是上面两个onMouseUp同时只能有一个回调被使用到,激活某一个工具,以下

tool1.activate();

碰撞检测

这个东西在图形处理的时候颇有用,这里说一下官网支持的一些东西

  1. 支持检测图形,图形边界和图形的选中边界
  2. 支持检测某个点在图形的什么位置
  3. 只是检测两个图形的是否相交以及相交点的位置

点检测

点检测方法为hitTest,示例为

project.hitTest(point[, options])

其中point即为paper.js实例化的一个点,好比new Point(15, 20)则检测[15, 20]这个店是否命中了某个图形,命中的位置为何,命中的对象结构参照HitResult

其中options为一个对象,表明对检测的一些控制,下面列出一部分

  • tolerance 检测灵敏度,默认为paper.settings.hitTolerance
  • fill 图形上
  • stroke 图形边界
  • segments 是否检测路径Path中每一段segment的控制点
  • bounds 矩形的边界
  • selected 只响应已经选中的店

路径相交检测

aPath是否与bPath相交,返回一个布尔值

aPath.intersects(bPath);

获取aPathbPath相交的点,并返回相交的点集合

aPath.getIntersections(bPath)

动画(我没用到,略过)

其余建议

  • 须要理解canvas原生的一些内容可以帮助更好的绘图,好比两次绘制之间关系(paperjs为blendMode,原生为globalCompositeOperation),参照:https://developer.mozilla.org...
  • 理解原生的裁剪(原生为ctx.clip(),paper.js为使用clipMask属性),使用这个时候后续图形绘制的显示将仅能展现在此裁剪路径当中
  • 下面几个事件处理颇有用,能够注意一下,能够看下方代码使用

    • removeOn(options)
    • removeOnMove()
    • removeOnDown()
    • removeOnDrag()
    • removeOnUp()
      在鼠标拖拽时,不断清空上一次的绘制,而后绘制一个新的,这样就能作出鼠标操做绘制出矩形和椭圆形的功能了

      tools.onMouseDrag = (event) => {
         var path = new Path.Circle({
             center: event.point,
             radius: 10,
             fillColor: 'black'
         });
         path.removeOnDrag();
      }
  • 路径还有不少操做先后端segment段的方法,等待本身去探索使用

结束语

paper.js还有不少有意思的功能,只是须要注意上面的一些坑,虽然中文资料很少,可是逐步看看官方文档,慢慢也就能看懂了

官网API地址:http://paperjs.org/reference/...

相关文章
相关标签/搜索