p5.js の canvas 要素を渡して obniz ディスプレイでアニメーションを表示させるメモです。
背景
「obniz のディスプレイでアニメーションさせてみたいんです」といった相談があって、結構厳しいんじゃないか?と思ってやってみたら、当初の見立て通りでうまくいきました。
こちらにあるとおり、
displayでは1ピクセルずつどう表示するのかをdisplay.raw()により配列で送信します。左上を起点に白黒なら1pixel-1bitで白黒を、カラーなら対応している色深度により1pixelが何bitなのかが異なります。
また、Canvasを読み取りdisplayに描画するdisplay.draw()関数が用意されています。Nodejsの場合でもnode-canvasを利用することで同様な描画が可能です。
ということで obniz.display.draw(ctx);
といった形で ctx に値に canvas 要素が渡せればうまくいくようです。
動作環境
- Windows 10
- Chrome ブラウザから obniz クラウドで実行
良いヒントがあった
画像ファイルをdisplayする方法を教えて下さい | obniz Developer’s Community Forum
obniz フォーラムで GoogleHomer さんが canvas で JPEG 表示をさせるあたりを質問されていました。分かりやすい。
また、こちらの 3D sphere on Display という公式サンプルもよかったんですが、いかんせん three.js をガッツリ入れるだけに canvas 扱い自体をシンプルに見たいときには苦労したので、参考程度に。でも、きれい。
p5.js でやってみる
Positioning your canvas · processing/p5.js Wiki
obniz に渡したい canvas 要素をどう取得するかの話はこちらにありました。
function setup() { var cnv = createCanvas(windowWidth, windowHeight); cnv.style('display', 'block'); background(255, 0, 200); }
サンプルをみてみると、createCanvas の返り値で受け取ればいけるようです。いいですね!
p5.js – Libraries – cdnjs – The #1 free and open source CDN built to make life easier for developers
CDN 情報はこちらから把握して組み込みました。
ということで ラインが動く公式サンプル をベースに以下のように組み込みました。
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script> <script src="https://unpkg.com/obniz@3.25.0/obniz.js" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js" integrity="sha512-3RlxD1bW34eFKPwj9gUXEWtdSMC59QqIqHnD8O/NoTwSJhgxRizdcFVQhUMFyTp5RwLTDL0Lbcqtl8b7bFAzog==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> </head> <body> <script> // https://p5js.org/examples/structure-loop.html // ラインがループするサンプルをベースに let y = 0; let cnv; function setup() { cnv = createCanvas(128 , 64); stroke(255); frameRate(2); // 30fps はカクつく loop(); } function draw() { background(0); y = y - 10; if (y < 0) { y = height; } line(0, y, width, y); } // 今回の obniz を指示するための設定 const obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { obniz.display.clear(); obniz.display.print("p5.js"); console.log(cnv); obniz.onloop = async function(){ // この形で canvas の getContext('2d') 的な値を渡せる const ctx = cnv.drawingContext; obniz.display.draw(ctx); } } </script> </body> </html>
わりとシンプルに組み込めましたが、少し解説すると、
cnv = createCanvas(128 , 64);
cnv という値を obniz.onloop と p5.js の setup 関数で共通で使えるようなスコープにして、組み込んでいます。さきほどのフォーラムで obniz Board の場合は 128 * 64 のようなので、そうしています。結果バッチリでした。
obniz.onloop = async function(){ // この形で canvas の getContext('2d') 的な値を渡せる const ctx = cnv.drawingContext; obniz.display.draw(ctx); }
obiniz.onloop でループを回しており cnv.drawingContext
がこの形で canvas の getContext(‘2d’) 的な値を渡せるようなので、あとは obniz.display.draw(ctx);
で obniz に渡しています。
こちらを obniz で動かしてみると、こんな風にうまく動きました!
おお! p5.js のラインが動く公式サンプルから canvas 要素渡せば obniz ディスプレイで案外簡単にアニメーション転送できた!2fpsとか良い感じに動くなー。サンプルは動く速度とか fps 変えてます。 #obniz #p5js pic.twitter.com/v9wJrQJBQR
— Tanaka Seigo (@1ft_seabass) March 28, 2023
さすがに元サンプルの 30 fps だと PC 内の描画はサクサク動いても obniz で転送が間に合わなくて処理が詰まったようになるので 5 fps 以下だといい具合に同期しました。 WebSocket ベースで canvas から 128 x 64 な画像データ送ってますからね正直 0.5 秒に 1 回でも変わるんだったら素敵です。