はじめに
Ruby 3.2がリリースされてWebAssembly/WASIに対応しましたが、折角ブラウザでRubyが動くようになったのにHello, world!だけじゃ勿体ないので、もう一歩踏み込んでお絵描きをしてみます。
図形の描画
最初にJavascriptで書いてみます。HTML5のCanvasを用意してそこに簡単な図形を描画するコードです。
<html>
<canvas id="canvas"></canvas>
<script>
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.fillStyle = "Orange";
ctx.fillRect(25, 25, 50, 50);
ctx.strokeStyle = "Red";
ctx.lineWidth = 10;
ctx.strokeRect(100, 25, 50, 50);
</script>
</html>
これをRubyに移植すると
<html>
<script src="https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@0.5.0/dist/browser.script.iife.js"></script>
<canvas id="canvas"></canvas>
<script type="text/ruby">
require "js"
Document = JS.global[:document]
canvas = Document.getElementById("canvas")
ctx = canvas.getContext("2d")
ctx[:fillStyle] = "Orange"
ctx.fillRect(25, 25, 50, 50)
ctx[:strokeStyle] = "Red"
ctx[:lineWidth] = 10
ctx.strokeRect(100, 25, 50, 50)
</script>
</html>
こんな感じです。
ctx[:fillStyle] という書き方が若干気になるのですが、Javascriptプロパティはこういう風に読み書きするようです。
Rubyでブラウザに描画できました。
マンデルブロ集合を描いてみる
インターフェースさえ分かればあとは応用でなんでも描画できるはずということでマンデルブロ集合を描いてみます。マンデルブロのコードはAI(ChatGPT)に書いてもらいました(……が微妙に間違っていたので手直し)。
<html>
<script src="https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@0.5.0/dist/browser.script.iife.js"></script>
<canvas id="canvas"></canvas>
<script type="text/ruby">
require "js"
Document = JS.global[:document]
canvas = Document.getElementById("canvas")
ctx = canvas.getContext("2d")
MAX_ITERATIONS = 100
canvas[:width] = WIDTH = 512
canvas[:height] = HEIGHT = 512
def mandelbrot(z, c)
MAX_ITERATIONS.times do |i|
z = z * z + c
return i if z.magnitude > 2.0
end
return MAX_ITERATIONS
end
xmin, xmax = -2.0, 1.0
ymin, ymax = -1.5, 1.5
colors = MAX_ITERATIONS.times.map do |i|
r = (i * 3) % 256
g = (i * 7) % 256
b = (i * 11) % 256
"rgb(#{r}, #{g}, #{b})"
end
colors << "black"
HEIGHT.times do |j|
WIDTH.times do |i|
x = xmin + (xmax - xmin) * i.to_f / WIDTH
y = ymin + (ymax - ymin) * j.to_f / HEIGHT
c = Complex(x, y)
n = mandelbrot(0, c)
ctx[:fillStyle] = colors[n]
ctx.fillRect(i, j, 1, 1)
end
end
</script>
</html>
AMD Ryzen 7 PRO 6850U で表示されるまで数十秒かかりました。重たい人は画像サイズを小さくすれば早く表示されます。
拡大して表示
min, xmax = -0.6, -0.5
ymin, ymax = -0.7, -0.6

マンデルブロは無限に観ていられます。
感想
Rubyはグラフィック系が弱かったので、環境に依存せずに描けるようになったのは大きいです。

