55
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.jsでp5.jsを使ってみる

Last updated at Posted at 2018-12-09

画面収録 2018-12-09 23.24.48.mov.gif

p5.jsをVueのフレームワークを使って描画するためにリサーチした時のメモです。p5.jsはProcessingから派生したライブラリで、ビジュアル表現やGenerative Designをする時に便利です。OpenProcessingというWeb上で開発できる環境があり、プログラムを書いてすぐにビジュアルを確認できます。今回はここで書いたコードをVueを使って表示する方法を調べました。

ライブラリをインポート

Vueのプロジェクトを作成したら、p5.jsのライブラリをインストールします。
(私はNuxtで作成しましたが、通常のvue-cliでも同じだと思います。)

npm install --save p5

これですぐにp5.jsを使うことができるのですが、p5.jsであらかじめ用意されている関数やプロパティはグローバルで展開されてしまうようで、うまく扱うことができません。そこで、p5.jsにinstance modeと呼ばれるモードで、p5.jsを単体のオブジェクトとして生成して、グローバルとの競合を防ぐことができます(参考)。

mountedした時に描画するような記述は以下の通りです。p5.jsの実質的な実装コードを関数内に書いていき、その関数をP5クラスに渡しています。

mounted内
mounted() {

  const script = function (p5) {
    var speed = 2;
    var posX = 0;
    p5.setup = _ => {
      p5.createCanvas(500, 500);
      p5.ellipse(p5.width / 2, p5.height / 2, 500, 500);
    }

    p5.draw = _ => {
      p5.background(0);
      const degree = p5.frameCount * 3;
      const y = p5.sin(p5.radians(degree)) * 50;
      p5.push();
      p5.translate(0, p5.height / 2);
      p5.ellipse(posX, y, 50, 50);
      p5.pop();

      posX += speed;
      if (posX > p5.width || posX < 0) {
        speed *= -1;
      }
    }
  }

  const P5 = require('p5')
  new P5(script)
}

画面収録 2018-12-09 21.47.30.mov.gif

任意のCanvas内に表示

このままだとp5.jsの表示は左上に表示されてしまうので、html内の任意のCanvasの位置に表示させます(参考)

template
<template>
  <div class="container border">
    <div class="d-flex justify-content-center" id="p5Canvas"></div>
  </div>
</template>

mounted内の修正箇所
// p5.createCanvas(500, 500);
var canvas = p5.createCanvas(500, 500)
canvas.parent("p5Canvas");

任意のCanvasにidをつけ、p5.js内で作成したCanvasの親コンテナに割り当てることで任意のCanvas内に表示できます。

スクリーンショット 2018-12-09 21.55.00.png

外部リソースにする

本末転倒かもしれませんが、基本的にp5.js部分の記述はJavaScriptなので、Vue内に書かなくても良いと思いました。そこで、p5.jsの記述部分だけ抜き出して別ファイル(Radar.js)にし、それをVue側から呼び出して使用するように変更しました。

mounted内の実装
var radar = require('@/js/Radar.js')
const P5 = require('p5')
new P5(radar.main)
Radar.js
let p5;

export function main(_p5) {
  p5 = _p5

... 以下同じ
}

export文でp5.js部分(main関数)にアクセスできるようにして、new P5(radar.main)でオブジェクトを生成する時にその関数を渡しています。

コールバックを受け取る

もう少しVueの特徴を活かせられるように、p5.jsからコールバックを受け取って、その内容を表示させてみます。

methodsを追加
methods: {
  callbackOnP5: function(timeStr) {
    this.message = timeStr;
  }
}
templateに追加
<div class="message d-flex justify-content-center">
  {{message}}
</div>
dataを追加
data() {
  return {
    message: ""
  }
},
mounted
// NOTE: p5.jsからのコールバックを受け取る
radar.setDelegate(this.callbackOnP5);
Radar.js
let delegate;
let p5;
export function main(_p5) {
 p5 = _p5
 p5.draw = _ => {
   notifyCurrentTime();
 }
}

export function setDelegate(_delegate) {
  delegate = _delegate;
}

function notifyCurrentTime() {
  if (delegate !== undefined) {
    const message = p5.hour() + ":" + p5.minute() + ":" + p5.second();

    delegate(message);
  }
}

callback関数をあらかじめp5.js側のソースコードに渡しておき、任意のタイミングでコールバック関数を呼び出し、データバインディングしているmessageプロパティを更新させています。



冒頭のデモは[github](https://github.com/mitsuyacider/p5VueDemo)に置いています。 元となっているOpenProcessingでのソースコードは[こちら](https://www.openprocessing.org/sketch/627975)です
55
40
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?