2021年4月12日 星期一

p5.js 學習筆記 (三) : 基本繪圖 (中)

由於篇幅太長了, 所以將基本繪圖的測試拆成三篇, 這是中篇, 主要是測試矩形與圓的繪製. 本系列之前的文章參考 : 


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

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


11. 繪製矩形 : 

繪製矩形是呼叫 rect(x, y, w [, h]), 此函式有三種不同的參數模式 (參數意義不同) :
  • CORNER : (x, y) 表示矩形左上角坐標, (w, h) 表示寬與高 (預設模式)
  • CENTER : (x, y) 表示矩形中心點坐標, (w, h) 表示寬與高
  • RADIUS : (x, y) 表示矩形中心點坐標, (w, h) 表示寬與高的一半
預設模式是 CORNER, 但可以利用 rectMode() 更改為其他模式, 例如 rectMode(CENTER) 是改為 CENTER 模式. 例如 :


測試 11-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('violet');
      rect(0, 0, 100, 100);       // 左上角坐標 (0, 0), 寬高 (100, 100) 之矩形
      fill('pink');
      rect(100, 0, 100, 100);   // 左上角坐標 (100, 0), 寬高 (100, 100) 之矩形
      }
  </script>
</body>
</html>

此例繪製了兩個矩形, 其左上角坐標分別為 (0, 0) 與 (100, 0), 寬高都是 100, 故第一個矩形左上角為畫布的左上角, 第二個矩形的左上角為畫布上邊的中點, 兩個矩形剛好佔據畫布的左半邊與右半邊, 結果如下 :




可見若矩形的寬高相等就是正方形了. 


測試 11-2 : 重疊的矩形 (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('wheat');
      rect(20, 20, 160, 20);   // 先繪製的矩形在下
      fill('tomato');
      rect(120, 10, 20, 80);   // 後繪製的矩形在上
      }
  </script>
</body>
</html>

結果如下 :




此例的兩個矩形有重疊, 可見先畫的圖形會被後畫的圖形蓋住重疊區域. 下面是將上面程式中的兩個 rect() 前後順序對調的範例 : 


測試 11-3 : 重疊的矩形 (2) [看原始碼] 

<!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('tomato');
      rect(120, 10, 20, 80);      // 先繪製的矩形在下
      fill('wheat');
      rect(20, 20, 160, 20);      // 後繪製的矩形在上
      }
  </script>
</body>
</html>

結果如下 : 




如果設定上層圖形的透明度, 則被蓋住的下層圖形就可以被看見了, 但這時 fill() 必須改用 RGB 加上 alpha 參數來設定, 上例中後圖使用 'tomato' 填滿, 此顏色的 RGB 為 (245, 222, 179), 參考 :


修改上面範例, 設定上層矩形的透明度後就可以看到下層的矩形了, 例如 : 



<!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('tomato');
      rect(120, 10, 20, 80);            //下層矩形
      fill(245, 222, 179, 120);       // 上層矩形設定透明度 alpha=120
      rect(20, 20, 160, 20);
      }
  </script>
</body>
</html>

此例將上層矩形的顏色改用 RGB 指定以便能設定透明度 120 (0~255, 0 為全透明, 255 為不透明), 大約為半透明, 這樣就可以看到原本被蓋住的下層矩形了, 結果如下 : 


 

畫矩形除了預設的 CORNER 參數模式外, 還可以用 CENTER 參數模式, 此時傳入的前兩個參數是矩形的中心坐標, 後兩個參數仍然是寬與高, 但在繪製之前必須先呼叫 rectMode(CENTER) 將預設的 CORNER 模式改為 CENTER 模式, 例如 : 



<!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('royalblue');
      rectMode(CENTER);     //將參數模式改為 CENTER
      rect(100, 50, 100, 50);     //繪製矩形, 前面的 (100, 50) 為矩形中心坐標
      }
  </script>
</body>
</html>

此例的 rectMode(100, 50, 100, 50) 前兩個參數 (100, 50) 表示矩形之中心坐標, 而後兩個參數 (100, 50) 則表示寬與高, 因此矩形會畫在 (200, 100) 畫布的中央, 結果如下 :




另外一個參數模式 RADIUS 的前兩個與 CENTER 模式一樣為矩形中心坐標, 但後兩個參數則是矩形的寬高的一半 ("半徑"), 但在繪圖之前要先呼叫 rectMode(RADIUS) 將預設模式改為 RADIUS, 例如 :



<!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('yellowgreen');
      rectMode(RADIUS);      //設為 RADIUS 模式
      rect(100, 50, 50, 25);
      }
  </script>
</body>
</html>

結果如下 :




此例除了填滿顏色不同外與上例是一樣的, 但因為使用 RADIUS 模式, 故後兩個參數是上例的一半. 


12. 繪製圓形 : 

呼叫 circle(x, y, d) 可繪製圓形, 預設為 1px 的黑色邊框與白色填滿, 可先用 stroke(color) 設定邊框顏色, 用 strokeWeight(px) 設定邊框粗細, 例如 : 


測試 12-1 : 用 circle() 畫圓 [看原始碼] 

<!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() {
      circle(50, 50, 40)    //繪製圓心 (50, 50) 直徑 40 的圓 (預設白色填滿 1px 邊線)
      fill('violet');            //設定填滿顏色
      stroke('blue');         //設定邊線顏色
      strokeWeight(3);    //設定邊線粗細 (px)
      circle(150, 50, 50);    //繪製圓心 (150, 50) 直徑 50 的圓 
      noStoke();     //取消邊線顏色設定
      noFill();         //取消填滿顏色設定
      }
  </script>
</body>
</html>

此例繪製兩個圓, 左邊的使用預設值 (黑 1px 邊線白色填滿), 右邊的則在呼叫 circle() 前先用 fill(), stoke(), 與 stokeWeight() 設定邊線與填滿. 由於 draw() 會在無限迴圈中被呼叫, 故畫完第二個圓後必須用 noStoke() 與 noFill() 取消邊線與填滿設定, 否則第一個圓只有套用預設值一次, 之後就會套用第二個圓的設定. 結果如下 :




由上面的測試可知, 如果沒有設定透明度, 後繪製的圖繪掩蓋前面先繪製的圖, 因此在繪製同心圓時必須先畫較大的圓, 再依序繪製較小的圓, 這樣圖疊上去時小圓才不會被蓋在底下, 例如 :
 


<!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');
      stroke('indigo');
      strokeWeight(4);
      circle(100, 50, 80);       //先繪製最大的圓 
      fill('green');
      stroke('magenta');
      strokeWeight(2);
      circle(100, 50, 60);      //再繪製次大的圓 
      fill('blue');
      stroke('yellow');
      strokeWeight(1);
      circle(100, 50, 40);      //後繪製最小的圓 
      }
  </script>
</body>
</html>

結果如下 : 




如果順序顛倒, 先繪製小圓再繪製大圓, 則最後圖面上只會看到填滿紅色的大圓而已. 

下面是局部重疊的三個圓之範例 :



<!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);
      noStroke();      //取消邊線
      }
    function draw() {
      fill('red');
      circle(60, 40, 80);
      fill('green');
      circle(110, 30, 80);
      fill('blue');
      circle(100, 80, 80);
      }
  </script>
</body>
</html>

結果如下 : 




可見後畫的藍色圓在最上層, 次畫的綠色圓在中間, 而先畫的紅色圓在最下層. 如果設定填滿顏色的透明度 (預設是 255 不透明), 就可以看到較底層的圓了, 但 fill() 的參數要改用 (R, G, B, alpha) 格式才行, 例如 : 



<!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);
      noStroke();
      }
    function draw() {
      fill(255, 0, 0, 100);       //紅色填滿, 透明度 100
      circle(60, 40, 80);
      fill(0, 255, 0, 100);       //綠紅填滿, 透明度 100
      circle(110, 30, 80);
      fill(0,0, 255, 100);        //藍紅填滿, 透明度 100
      circle(100, 80, 80);
      }
  </script>
</body>
</html>

結果如下 : 




這樣底層的圖就不會完全被蓋住了, 但是設定透明度後, 怎麼綠色圓感覺偏黃了? 

下面範例是結合矩形與圓形繪製的禁止任何車輛進入之交通標誌 : 



<!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);
      noStroke();
      }
    function draw() { 
      fill('red');                         //設定填滿紅色
      circle(100, 50, 80);         //繪製圓形
      fill('white');                     //設定填滿白色
      rectMode(CENTER);     //設定矩形參數模式為 CENTER
      rect(100, 50, 60, 12);      //繪製矩形
      }
  </script>
</body>
</html>

此例在 setup() 中用 noStroke() 取消預設之黑邊線, 然後於 draw()中先繪製紅底之圓, 再繪製白底之矩形 (順序不可相反), 結果如下 :


沒有留言 :