二維繪圖庫-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/...

相關文章
相關標籤/搜索