13:描画(Drawing)

連続線

マウスのクリック&ドラッグで線が描けます。

function setup() {
    createCanvas(710, 400);
    background(102);
    // 線の色は最初白
    stroke('white');

    // クリアボタン
    const clearButton = setButton('CLEAR', {
        x: 20,
        y: 370
    });
    // 描画物をクリアして線の色を白にする
    clearButton.mousePressed(() => {
        clear();
        background(102);
        stroke('white');
        strokeWeight(1);
    });

    // 赤ボタン
    const redButton = setButton('RED', {
        x: 110,
        y: 370
    });
    // 線を赤い太線にする
    redButton.mousePressed(() => {
        stroke('red');
        strokeWeight(5);
    });

    // 緑ボタン
    const greenButton = setButton('YELLOW', {
        x: 200,
        y: 370
    });
    // 線の色を緑にする
    greenButton.mousePressed(() => {
        stroke('yellow');
    });
}

function draw() {
    // マウスボタンが押されている状態なら
    if (mouseIsPressed === true) {
        // 今のマウス位置から、前のマウス位置まで線を描く
        line(mouseX, mouseY, pmouseX, pmouseY);
    }
}

function setButton(label, pos) {
    const button = createButton(label);
    button.size(80, 30);
    button.position(pos.x, pos.y);
    return button;
}
解説

いわゆるお絵かきアプリの簡易版です。p5.jsでは、draw()関数内で、mouseIsPressed変数とline()関数、mouseX, mouseY, pmouseX, pmouseY変数を組み合わせるだけで、キャンバスに連続線が描けます。なお描いた線は残すので、draw()内にはbackground()関数は使用しません。

mouseIsPressedについては「4_4:応答:クリック p5.js JavaScript」で、pmouseXとpmouseYについては「4_2:応答:マウスを追跡 p5.js JavaScript」で述べています。

パターン

カーソルをキャンバス上で動かすと、マウスのスピードに反応するソフトウエアツールで描画できます。

function setup() {
    createCanvas(710, 400);
    background(102);
}

function draw() {
    variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
}

function variableEllipse(x, y, px, py) {
    // 今のマウス位置と1フレーム前のマウス位置との差の絶対値
    // 大きいほどマウスは速く移動したことになる。
    const speed = abs(x - px) + abs(y - py);
    // speedが大きいほど線の色を薄くする
    stroke(speed);
    // speedが大きいほど描く円の直径を大きくする
    ellipse(x, y, speed, speed);
}
解説

マウスを一瞬で動かした距離をスピードととらえ、それを線の濃さと円の大きさに対応させるというアイデアです。

パルス

ソフトウェア描画装置はリズムにしたがうことも、描画されたジェスチャとは関係のないルールに従うこともできます。これは、設計する人がイメージのある側面を制御し、ソフトウェアがほかの側面を制御するという、描画を合作する形式です。

let angle = 0;

function setup() {
  createCanvas(710, 400);
  background(102);
  noStroke();
  fill(0, 102);
}

function draw() {
  // background()がないので、描画物は残存する

  // マウスが押し下げられている間ずっと描画する
  // => forループも何度も実行されるので、黒い円も重なって描画される
  // ドラッグしても模様(?)が描ける
  if (mouseIsPressed === true) {
    // angleは5ずつ大きくなる
    angle += 5;
    // valは12 -> -12 -> 12..を繰り返すコサイン値
    const val = cos(radians(angle)) * 12.0;
    // a = 0,75,150,225,300 => forループは5回繰り返される
    for (let a = 0; a < 360; a += 75) {
      // 半径がvalの円周上の点(xoff,yoff)
      const xoff = cos(radians(a)) * val;
      const yoff = sin(radians(a)) * val;
      // (mouseX + xoff, mouseY + yoff)を中心とする直径valの黒い円
      // 描かれる円の大きさは大->小->大...を繰り返す
      fill(0);
      ellipse(mouseX + xoff, mouseY + yoff, val, val);
    }
    fill(255);
    ellipse(mouseX, mouseY, 2, 2);
  }
}

マウスボタンの押し下げで花びらのような模様がさまざまなサイズで描けます。模様はボタンを押し下げている時間によって変わります。ドラッグして描くこともできます。

解説

上記のこのサンプルに関する説明文が意味するところは、描かれる花びらのような模様はユーザーがある程度制御でき、描画位置は制御できるが、大きさはこのプログラムが制御する、ということではないかと思います。

このサンプルの特徴は、mouseIsPressedがtrueである間、draw()関数に書かれたコードが全部実行されることです。この仕様によって、マウスのクリック動作(マウスボタンを押してすぐ放す)では花びらのような描画物が作成され、マウスダウン動作(押し下げたままボタンを放さない)では花びらが連続して上書きされ、ドラッグ動作では太いソーセージをつなげたような描画物になるという、ユーザージェスチャによる描画結果の違いが生まれます。

pulseには、持続時間のきわめて短い電流または変調電波という意味があるので、タイトルの「Pulse」は、マウスボタンを押している短い時間を指しているのではないかと想像します。

ポイントとなるのは、draw()関数にある次のコサイン値です。

angle += 5;
const val = cos(radians(angle)) * 12.0;

angleは最初0で、draw()関数が呼び出されるたびに、つまり1秒間に60回(p5.jsのデフォルトのfpsは60)、5が足されていきます。たとえばdraw()関数の1回めの呼び出し時には、0に5が足され、変数valには、cos(5度)*12の計算結果、0.996…x 12(ほぼ12)が代入されます。angleにはその後もつづけて5が足されていくので、変数valにはコサインの特徴を持つ、12と-12の間を滑らかに行き来する数値が代入されます。下図はval値の変化のグラフです。

その後は次のforループで、5つの円が描かれます。

for (let a = 0; a < 360; a += 75) {
    const xoff = cos(radians(a)) * val;
    const yoff = sin(radians(a)) * val;
    fill(0);
    ellipse(mouseX + xoff, mouseY + yoff, val, val);
}

forループ内の最初の2行は、(0,0)を中心とする半径valの円の円周上の点(xoff,yoff)を求めている、と見なすことができます。そしてその後のellipse()関数は、マウス位置からxoffとyoff分だけずらした位置を中心として、valを直径とする黒い円を描きます。

この描画は下図のように表せます。angleは0,75,150,225,300と変化するので、angleが0のときは0度に当たる位置に図の(1)の円が、75のときには75度に当たる位置に(2)の円が描画されます。

そしてループの外では絶えずval値が計算されているので、valを直径とする黒い円の大きさが変化します。下図はサンプルコードに手を加え、val値の変化と、黒い円の大きさの変化を並べた見たものです。ドラッグ時にもvalの値は変化するので、黒い5つの円はこのように、太いソーセージをつなげたように描画されます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA