2021年4月11日 星期日

p5.js 學習筆記 (二) : 基本繪圖 (上)

布置好 p5.js 的執行環境後就可以開始在畫布上繪圖了, 除了繪圖與互動應用, 其實透過 p5.js 來學習 Javascript 非常有效, 因為它可以將學習轉化成玩, 玩的樂趣無形中會沖淡學習必有的痛苦. 

本系列之前的文章參考 :


以下測試使用之參考文件 : 

https://p5js.org/reference/ (教學文件)
https://editor.p5js.org (線上編輯器)


1. 網頁模板  : 

以下測試將使用上一篇 "環境配置" 中的 CDN 網頁模板 : 

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(400, 300);
      }
    function draw() {
      background(200, 200, 200);
      }
  </script>
</body>
</html>

p5.js 的程式架構很簡單, 只有兩個函式 (與 Arduino 的程式架構類似), 由只執行一次的 setup() 與預設每秒執行 60 次的 draw() 函式組成, 所以初始設定的指令碼要放在 setup() 內, 而需重複執行的指令碼則放在 draw() 內. 上面的模板網頁中, 如果畫布的背景不需要改變, 則可將 background() 移到 setup() 內. 


2. 偵錯工具 console.log() : 

p5.js 為 Javascript 網頁應用程式的互動繪圖函式庫, 程式開發與結果驗證都是在瀏覽器上, 開發中的偵錯除錯主要是利用 Javascript 的 console.log() 將變數輸出到瀏覽器的控制台觀察變數之值以資判斷, 在 Chrome 瀏覽器上按 F12 (筆電要同時按 Fn 鍵) 會在頁面右邊顯示開發介面, 切到 Console 頁籤即可下達 Javascript 指令 :




例如下面的範例是呼叫 p5.js 的內建函式 frameRate() 取得 draw() 的迴圈頻率, 然後再用 console.log() 輸出此頻率值:



<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 200);
      }
    function draw() {
      background(100);
      console.log(frameRate());      //輸出 draw() 的迴圈頻率預設值
      }
  </script>
</body>
</html>

結果如下 :




可見 draw() 大約每秒會被呼叫 60 次左右. 


3. 內建常數, 變數, 與函式 : 

撰寫 sketch 程式時除了會用到 Javascript 本身的常數, 變數, 與函式外, p5.js 函式庫也提供了很多與繪圖相關的常數, 變數, 與函式, 只要熟悉這些內建函式的呼叫方式與常數變數所代表的意義, 就能用少許的程式碼在畫布上繪圖或產生互動效果. 以下摘要整理常用的常數, 變數, 與函式 : 


常用的內建常數如下表 :

 p5.js 常用內建常數 說明
 PI 圓周率, 約 3.1415926
 HALF_PI 半圓周率, 約 1.5707963
 QUARTER_PI 四分之一圓周率, 約 0.7853982
 TWO_PI 兩倍圓周率, 約 6.2831853
 DEGREES 角度, 作為 angleMode() 函式之參數, 設定為角度模式
 RADIANS 弧度, 作為 angleMode() 函式之參數, 設定為弧度模式
 CENTER 前兩個參數為圓心, 後兩個參數為寬度 w 與高度 h (或置中對齊)
 RADIUS 前兩個參數為圓心, 後兩個參數為寬度半徑 w/2 與高度半徑 h/2
 CORNER 前兩個參數為左上角座標, 後兩個參數為寬度 w 與高度 h
 CORNERS 前兩個參數為橢圓外方框一角之座標, 後兩個參數為對角座標
 LEFT 向左對齊 (水平, 垂直)
 RIGHT 向右對齊 (水平)
 BOTTOM 向下對齊 (垂直)
 CLOSE 傳入 endShape() 會使形狀之終點與起點相連成封閉圖形


常用的內建變數如下表 :

 p5.js 常用內建變數 說明
 width 畫布寬度 (px)
 height 畫布高度 (px)
 windowWidth 瀏覽器視窗寬度 (px)
 windowHeight 瀏覽器視窗高度 (px)
 frameCount draw() 的累計呼叫次數
 mouseIsPressed 滑鼠左鍵是否被按下 (true/false)
 mouseButton 被按下的滑鼠按鍵 (LEFT/CENTER/RIGHT)
 mouseX 滑鼠的 X 座標
 mouseY 滑鼠的 Y 座標
 pmouseX 前一個 frame 之滑鼠 X 座標
 pmouseY 前一個 frame 之滑鼠 Y 座標


常用的內建函式如下表 :


 p5.js 常用內建函式 說明
 createCanvas(w, h) 以網頁左上角為起點建立寬 w, 高 h 之畫布 (單位 px)
 background(R [, G, B, alpha]) 設定畫布背景色 (值 0~255), 只傳入一個參數時表示 R=G=B
 fill(R [,G, B, alpha]) 設定封閉圖形之填滿顏色直到呼叫 noFill() 為止
 noFill() 取消上一次的 fill() 填滿設定, 恢復預設值 (白色)
 stroke(R [, G, B, alpha]) 設定線條或封閉圖形框邊顏色
 strokJoin(join) 設定線條接合處樣式, join=MITER(預設)/BEVEL/ROUND
 strokCap(cap) 設定線條端點樣式, cap=ROUND(預設)/SQUARE/PROJECT
 noStroke() 取消圖形之邊線 (無邊線)
 strokeWeight(px) 設定線條或封閉圖形邊線寬度 (px)
 point(x, y [, z]) 在座標上繪製一個點, 顏色大小用 stroke() 與 strokeWeigth()
 line(x1, y1, x2, y2) 在座標 (x1, y1) 與 (x2, y2) 間繪製直線
 quad(x1,y1,x2,y2,x3,y3,x4,y4) 用 (x1,y1), (x2,y2), (x3, y3), (x4,y4) 作頂點繪製四邊形
 square(x, y, s [, r]) 在 (x, y) 座標繪製邊長 s 的正方形 (r=圓角半徑)
 triangle(x1,y1,x2,y2,x3,y3) 用 (x1,y1), (x2,y2), (x3, y3) 作頂點繪製三角形
 rect(x, y, w [, h]) 繪製一個左上角座標為 (x, y), 寬 w 高 h 的矩形 (CORNER 模式)
 rectMode(mode) 設定矩形繪圖函式 rect() 的參數模式, 預設 CORNER 模式
 circle(x, y, d) 繪製圓心為 (x, y), 直徑為 d 之圓形
 ellipse(x, y, w [, h]) 繪製圓心為 (x, y), 寬徑 w, 高徑 h 之橢圓 (w=h 時為正圓)
 ellipseMode(mode) 設定橢圓函式 ellipse() 的參數模式, 預設 CENTER=(x, y, w, h)
 arc(x, y, w, h, start, stop) 繪製圓心為 (x, y), 寬徑 w, 高徑 h, 起訖弧度 start~stop 之弧形
 radians(d) 將角度 d 轉成弧度
 degrees(r) 將弧度 r 轉成角度
 angleMode(mode) 設定方位度數模式, mode=RADIANS(預設)/DEGREES
 textSize(size) 設定字型大小 (px)
 textAlign(halign [,valign]) 文字對齊 halign=LEFT/CENTER/RIGHT valign=TOP/BOTTOM
 textWidth() 傳回字串寬度 (px)
 textStyle(style) 設定字串風格, style=NORMAL/BOLD/ITALIC/BOLDITALIC
 text(str, x, y) 在座標 (x, y) 處開始輸出字串 str
 beginShape([kind]) 開始記錄形狀 kind (LINES/QUADS/TRIANGLES 等) 之頂點
 vertex(x, y [, z]) 用來在 beginShape() 與 endShape() 之間指定頂點座標 
 endShape([CLOSE]) 終止紀錄頂點 (傳入 CLOSE 會連接起點與終點形成封閉形狀)
 frameRate([fps]) 傳入參數 fps 時設定圖框率 (每秒), 否則傳回目前設定值


注意, RGB 與 alpha 值皆在 0~255 間, alpha=0 為全透明, alpha=255 為不透明 (預設). 

事實上 p5.js 所提供的函式非常豐富, 但上面所列的常用常數, 變數, 與函式已足夠來作測試了, 完整的 p5.js 說明文件參考 :



5. 顏色設定 : 

在 p5.js 中用來設定顏色的函式主要有下面五個 : 
  • background(R [,G, B, alpha]) : 畫布的背景色
  • stroke(R [,G, B, alpha]) : 線條或圖形之邊框顏色
  • noStroke() : 取消前一次的 stroke() 設定
  • fill(R [,G, B, alpha]) : 圖形內之填滿顏色
  • noFill() : 取消前一次的 fill() 設定
這些函式的參數型態其實有多種模式, 通常 RGB 三原色模式較常用, 備選的第四參數 alpha 可設定顏色的透明度, 其值為 0 (不透明) ~ 255 (全透明). 

顏色色碼可用 Mozilla 的顏色選擇器來選定 : 


另外一個常用的顏色指定法為傳入 CSS 的顏色字串, 例如 :

background('red');
fill('ivory');
stroke('cyan'); 

完整的 CSS 顏色名稱字串參考 :



6. 用 point() 繪製點 : 

呼叫 point() 函式可繪製一個點, 預設畫筆顏色為黑色, 大小是一個 1px 的點, 可分別用 stroke() 與 strokeWeight() 設定, 例如 : 



<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 200);      
      background(0, 0, 0);    //背景=黑色
      }
    function draw() {
      stroke(255, 255, 0);     //設定顏色=黃色
      strokeWeight(5);          //設定大小=5px
      point(100, 100);           //在 (100, 100) 繪製一個點
      }
  </script>
</body>
</html>

此例在 setup() 中建立一個 200*200 px 的畫布, 並設定背景色為黑色, 然後在 draw() 迴圈函式中先用 stroke() 設定前景色為黃色, 用 strokeWeight() 設定畫筆粗細為 5px, 最後呼叫 point() 在 (100, 100) 座標處繪製一個點, 結果如下 :



可見在畫布中央繪製了一個黃點. 


7. 用 line() 繪製線 : 

呼叫 line(x1, y1, x2, y2) 可以在畫布的兩個坐標點 (x1, y1) 與 (x2, y2) 之間繪製一條直線, 例如 :



<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 200);      
      background(0, 0, 0);
      }
    function draw() {
      stroke(255, 255, 0);       //前景色=黃色
      strokeWeight(2);            //畫筆=2px
      line(0, 0, 200, 200);       //左上至右下畫一直線
      stroke(255, 255, 255);   //前景色=白色
      strokeWeight(6);            //畫筆=6px
      line(200, 0, 0, 200);       //右上至左下畫一直線
      }
  </script>
</body>
</html>

此例先設定前景色為黃色畫筆為 2px, 然後呼叫 line() 於 (0, 0) 與 (200, 200) 間繪製直線 (左上到右下); 然後更改前景色為白色, 畫筆改為 5px, 再次呼叫 line() 於 (200, 0) 與  (0, 200) 間繪製直線 (右上到左下), 結果如下 : 




8. 用 quad() 繪製四邊形 : 

呼叫 quad(x1, y1, x2, y2, x3, y3, x4, y4) 函式繪製四邊形必須傳入四個頂點的坐標 : (x1, y1), (x2, y2), (x3, y3), (x4, y4), 連接此四點即為四邊形, 例如 :



<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 100);      
      background(200, 200, 200);
      }
    function draw() {  
      fill('red');           //設定填滿顏色為紅色
      quad(38, 31, 86, 20, 69, 63, 30, 76);    //繪製四邊形
      noFill();            //取消上一次填滿顏色設定
      fill('yellow');     //設定填滿顏色為黃色
      quad(128, 45, 170, 34, 180, 85, 158, 88);     //繪製四邊形
      noFill();            //取消上一次填滿顏色設定
      }
  </script>
</body>
</html>

此例繪製了兩個四邊形, 同時利用 CSS 顏色字串呼叫 fill() 來填滿四邊形內的顏色, 注意, 雖然可以直接設定新的填滿顏色, 但先用 noFill() 取消設定是個好習慣, 結果如下 :




9. 用 square() 繪製正方形 : 

呼叫 square(x, y, s [, r]) 繪製正方形需傳入左上角頂點坐標 (x, y) 與邊長 s, 若傳入備選的第四參數 r 則可將正方形圓角化, 此第四參數為圓角之半徑 (px), 例如 : 


測試 9-1 : 繪製正方形 [看原始碼]  

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 100);      
      background(200, 200, 200);
      }
    function draw() {  
      fill('cyan'); 
      square(25, 25, 50);           //繪製正方形
      noFill();
      fill('gold');
      square(125, 25, 50, 10);    //繪製有 10px 圓角之正方形
      noFill();
      }
  </script>
</body>
</html>

此例繪製了兩個正方形, 其中第二個使用第四參數指定了半徑為 10 px 之圓角, 結果如下 :




10. 用 triangle() 繪製三角形 : 

呼叫 triangle(x1, y1, x2, y2, x3, y3) 繪製三角形時需傳入三角形的三個頂點坐標 (x1, y1), (x2, y2), (x3, y3), 例如 :


測試 10-1 : 繪製三角形 [看原始碼]  

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
  <script>
    function setup() {
      createCanvas(200, 100);      
      background(200, 200, 200);
      }
    function draw() {  
      fill('indianred');
      triangle(50, 20, 20, 80, 80, 80);         //繪製三角形
      noFill();
      fill('lime');
      triangle(120, 20, 180, 20, 150, 80);   //繪製三角形
      noFill();
      }
  </script>
</body>
</html>

結果如下 : 


沒有留言 :