p5.js備忘録(2)

目次
  1. 時計
  2. 木のフラクタル図形
  3. imageとpixels
  4. bezier

時計

  • map(value, start1, stop1, start2, stop2, [withinBounds])
    数値をある範囲から別の範囲にマップします
    value : 変換される入力値
    start1: 現在の範囲の下限
    stop1: 現在の範囲の上限
    start2 :ターゲット範囲の下限
    stop2: ターゲット範囲の上限
    withinBounds:Boolean値を新しくマップされた範囲に制限します (オプション)
  • norm(value, start, stop)
    別の範囲の数値を0 ~1の値に正規化します
    value:正規化される受信値
    start :現在の範囲の下限
    stop :現在の範囲の上限
  • arc(x, y, w, h, start, stop, [mode], [detail])
    円弧を描きます
    x :円弧の楕円の x 座標
    y :円弧の楕円の y 座標
    w :デフォルトでの円弧の楕円の幅
    h :デフォルトでの円弧の楕円の高さ
    start : 円弧の開始角度
    stop : 円弧を停止する角度
    mode 定数: 円弧の描画方法を決定するオプションのパラメーター
    CHORD・PIE・ OPEN
    detail : WebGLモードのみのオプション
  • Time & Date(PCから取得)
    hour() :現在の時間を 0 から23の値で返します
    second():現在の秒を 0 から59の値として返します
    minute():現在の分を 0 から59の値で返します
    day():現在の日付を 1 から31の値で返します
    month():現在の月を 1 から12の値で返します
    year():現在の年を整数 (2023 など)として返します
    millis():setup() が呼び出されたときのミリ秒 (1000 分の 1 秒)を返します

ロードされた時の時刻を表示しています(クリックでスタートとストップを制御)

<div id="canvas1"></div>
<script>
function setup() {
  createCanvas(300, 300).parent('canvas1');
  frameRate(1);
  angleMode(DEGREES);
  noLoop();
}
function draw() {
  background(200);
  translate(width/2, height/2);
  rotate(-90); //頂点からスタートするため
  const hColor = 'red'
  const mColor = 'blue'
  const sColor = 'white'
  let hr = hour();
  let mn = minute();
  let sc = second();
  strokeWeight(6);
  noFill();
//秒、分を0から360(時は360*2)の範囲にマップ
//分と時はnorm()で途中経過を表現(最大が1)
  let sAngle = map(sc, 0, 60, 0, 360);
  let mAngle = map(mn + norm(sc, 0, 60), 0, 60, 0, 360);
  let hAngle = map(hr + norm(mn, 0, 60) , 0, 24, 0, 360*2);
//arcで進んだ分の円弧を表示
  stroke(sColor); 
  arc(0, 0, 280, 280, 0, sAngle);
  stroke(mColor);
  arc(0, 0, 260, 260, 0, mAngle);
  stroke(hColor);  
  arc(0, 0, 240, 240, 0, hAngle);
//lineを角度だけ回転
  push();
  rotate(sAngle);
  stroke(sColor);
  line(0, 0, 90, 0);
  pop();
  push();
  rotate(mAngle);
  stroke(mColor);
  line(0, 0, 75, 0);
  pop();
  push();
  rotate(hAngle);
  stroke(hColor);
  line(0, 0, 50, 0);
  pop();
 //point
  stroke(0);
  point(0, 0);
  beginShape(POINTS);
  for (let a = 0; a < 360; a += 360/12) {
    let x =  cos(a) * 100;
    let y =  sin(a) * 100;
    vertex(x, y);
  }
  endShape();
}
const el1 = document.getElementById('canvas1');
   el1.addEventListener('click', ()=>{
    isLooping()? noLoop():loop()
  })
</script>

木のフラクタル図形

再帰関数(自分自身を呼び出す関数)で、再起処理をしてツリーのような構造を描きます
クリックした位置のY座標の位置を0〜90度の角度に置き換えて、枝の角度にしています
*上0〜下90

<div id="canvas2"></div>
<script>
let angle;
function setup() {
  createCanvas(300, 300).parent('canvas2');
  angleMode(DEGREES);
  noLoop();
}
function draw() {
  background(0);
  frameRate(30);
  stroke(255);
  //マウスのY座標を0~90度の角度にマップ
  angle = map(mouseY, 0, width, 0, 90);
  //幹
  translate(width/2, height);
  line(0,0,0,-120);
  //幹の上に移動
  translate(0,-120);
  //枝branchは再起関数
  branch(80);
}
function branch(h) {
  //前の枝*0.7のサイズ
  h *= 0.7;
  if (h > 2) { //枝の長さが2になるまで再起処理
    push(); 
    rotate(angle);
    line(0, 0, 0, -h);
    translate(0, -h); //枝元に戻る 
    branch(h);  //自分を呼び出す
    pop(); 
    // 左側
    push();
    rotate(-angle);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h); //自分を呼び出す
    pop();
  }
}
const el2 = document.getElementById('canvas2');
   el2.addEventListener('click', ()=>{
    redraw();
  })
</script>

imageとpixels

  • image(img, x, y, [width], [height])
  • image(img, dx, dy, dWidth, dHeight, sx, sy, [sWidth], [sHeight], [fit], [xAlign], [yAlign])
    dx:ソース画像を描画する宛先長方形の x 座標
    dy:ソース画像を描画する宛先長方形の y 座標
    dWidth : コピー先の四角形の幅
    dHeight:コピー先の四角形の高さ
    sx:ソース画像のサブセクションの x 座標で、宛先の四角形に描画されます
    sy :ソース画像のサブセクションの y 座標を指定して、目的の四角形に描画します
    sWidth : ソース画像のサブセクションの幅で、宛先の四角形に描画されます (オプション)
    sHeight :ソース画像のサブセクションの高さ(オプション)
    fit :CONTAIN ・ COVER (オプション)
    xAlign : LEFT・RIGHT・CENTER のいずれか デフォルトは CENTER(オプション)
    yAlign : TOP・BOTTOM・CENTER のいずれか デフォルトは CENTER(オプション)

画像を表示して、グレースケールfilter

<div id="canvas3"></div>
<script>
let img;
function preload() {
  img = loadImage("https://koro-koro.com/wp-content/uploads/2022/12/canvas-test2.jpg");
}
function setup() {
  createCanvas(300, 200).parent('canvas3');
  image(img, 0, 0, width, height);
//  image(img, 0, 0, width, height, 0, 0, img.width, img.height, COVER);
  filter(GRAY);
}
</script>
  • pixels[]
    表示ウィンドウ内のすべてのピクセルの値を含むUint8ClampedArray
    各ピクセルの R、G、B、A 値を順番に表し
    画像が 100 × 100 ピクセルの場合40,000 (Retinaディスプレイでは160,000)
    pixels[]にアクセスする前に、loadPixels()でデータをロードする必要があり
    配列データが変更された後、 updatePixels() で変更を更新する必要があります
    *(注意)JavaScript配列ではない
  • loadPixels()
    表示ウィンドウのピクセルデータを pixel[] 配列に読み込みます
  • updatePixels()
    set()で行われた変更またはpixels[]の変更を更新します
  • pixelDensity()
    高ピクセル密度ディスプレイのピクセル スケーリングを設定します
    デフォルトはピクセル密度は表示密度と一致
    オフにするには、pixelDensity(1)
    引数なしで pixelDensity() を呼び出すと現在のピクセル密度が返されます
  • get(x, y, w, h)
    キャンバスからピクセルの領域または単一のピクセルを取得します
    引数が指定されていない場合はイメージ全体が返されます
    引数がxとy:1 ピクセルの値を取得します
  • set(x, y, c)
    任意のピクセルの色を変更するか、画像を表示ウィンドウに直接書き込みます
    c : グレースケール値・ピクセル配列 ・p5.Color オブジェクト・コピーする p5.Image
  • resize(width, height)
    画像サイズを変更します
    アスペクト比を維持する場合は0
    例:画像の幅を150でアスペクト比を維持する場合resize(150, 0)

多次元配列 
行の数:「height 」
列の数:「width * 4」

let d = pixelDensity();
for (let i = 0; i < d; i++) {
  for (let j = 0; j < d; j++) {
    index = 4 * ((y * d + j) * width * d + (x * d + i));
    pixels[index] = r;
    pixels[index+1] = g;
    pixels[index+2] = b;
    pixels[index+3] = a;
  }
}

1秒ごとに色を書き換えます(クリックでスタートとストップを制御)

<div id="canvas4"></div>
<script>
function setup() {
  createCanvas(150, 150).parent('canvas4');
  frameRate(1);
  pixelDensity(1);
  noLoop();
}
function draw(){
  loadPixels();
  let r =random(255)
  let g = random(255)
  let b = random(255)
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let index = (x + y * width) * 4;
      pixels[index] = r;
      pixels[index + 1] = g;
      pixels[index + 2] = b;
      pixels[index + 3] = 255;
    }
  }
  updatePixels();
}
const el4 = document.getElementById('canvas4');
   el4.addEventListener('click', ()=>{
    isLooping()? noLoop():loop()
  })
</script>

画像の色を取得し、四角形を描画することでモザイクにします

<div id="canvas5"></div>
<script>
const WIDTH = 300;
const HEIGHT = 200;
let img;
function preload() {
  img = loadImage("https://koro-koro.com/wp-content/uploads/2022/12/canvas-test2.jpg");
}
function setup() {
  createCanvas(WIDTH, HEIGHT).parent('canvas5');
  img.resize(WIDTH, HEIGHT);
  noLoop();
}
function draw() {
   const step = 8;
    background(0);
    noStroke();
    for (let y = 0; y < HEIGHT; y += step) {
      for (let x = 0; x < WIDTH; x += step) {
       const color = img.get(x, y);
       fill(color);
       rect(x, y, step, step);
     }
   }
}
</script>

bezier

  • bezier()
    画面に3次ベジエ曲線を描画します
    *ベジエ曲線は緩やかに傾斜した曲線を定義するために一般的に使用されます
  • p5.Vector.fromAngle((角度, [長さ])
    角度から 2Dベクトルを作成します
    角度はラジアン単位(angleModeの影響を受けない)
    長さは新しいベクトルの長さ(デフォルトは 1)

サイドバー(CG)のグラフィック
円の中でベジエ曲線を描画(クリックでスタートとストップを制御)
マウスのX座標の位置を0〜200(ベジエ曲線の数)置き換えて描画します

<div id="canvas6"></div>
<script>
let r;
let step = 2;
function setup() {
  createCanvas(300, 300).parent('canvas6');
  r = height / 2 - 10;
  colorMode(HSB);
  noLoop();
}
function draw() {
  background(0);
  //マウスのX座標の位置を0〜200にマウント
  let total = map(mouseX, 0, width, 0, 200);
  step += 0.02;
  translate(width / 2, height / 2);
  stroke(255);
  strokeWeight(1);
  noFill();
  ellipse(0, 0, r * 2);

  strokeWeight(1);
  for (let i = 0; i < total; i++) {
    let a = getVector(i, total); //始点のxとy座標 
    let b = getVector((i + 5) * step, total);//1つ目コントロールポイントのxとy座標 
    let c = getVector((i + 10) * step, total);//2つ目コントロールポイントのxとy座標 
    let d = getVector((i + 15) * step, total);//制御点
    let h = map(i, 0, total, 0, 360);
    stroke(h, 255, 255);
    bezier(a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y);
  }
}
function getVector(i, total) {
  const angle = map(i % total, 0, total, 0, TWO_PI);
  const v = p5.Vector.fromAngle(angle, r);
  return v;
}
const el6 = document.getElementById('canvas6');
   el6.addEventListener('click', ()=>{
    isLooping()? noLoop():loop()
  })
</script>