Arantium Maestum

プログラミング、囲碁、読書の話題

js_of_ocamlでHTMLにCanvasを追加して操作してみる

前回、前々回に続いてjs_of_ocamlの話。今回はDOM要素をコード側で作成する。

だいたいの元ネタはjs_of_ocaml公式サンプルのこれ:

https://github.com/ocsigen/js_of_ocaml/blob/master/examples/minesweeper/main.ml

ただし、この記事ではCanvas要素を作成・追加して赤い四角を描画してみる。

構成は前回と同様。duneファイルには変更なし。

main.mlはこんな感じ:

open Js_of_ocaml
module Html = Dom_html

let js = Js.string
let document = Html.window##.document

let create_canvas width height =
  let canvas = Html.createCanvas document in
  canvas##.width := width;
  canvas##.height := height;
  canvas##.style##.border := (js "1px solid #000000");
  canvas

let draw_square canvas_context x y w h =
  canvas_context##.fillStyle := (js "#FF0000");
  canvas_context##fillRect x y w h

let start _ =
  let main = Js.Opt.get (document##getElementById (js "main")) (fun () -> assert false) in
  let canvas = create_canvas 500 500 in
  let canvas_context = canvas##getContext Html._2d_ in
  ignore @@ draw_square canvas_context 200. 200. 50. 50.;
  Dom.appendChild main canvas;
  Js._false

let () = Html.window##.onload := Html.handler start

create_canvasCanvas要素を作成してプロパティをいくつかセットしている。draw_squareは与えられたCanvasContextに赤い四角を描く。

start関数は多少こみいっている。

Js.Opt.get (document##getElementById (js "main")) (fun () -> assert false)でidがmainのDOM要素を取ってきている。そんな要素が存在しない時のためにgetElementByIdはjs_of_ocaml特有のオプション型を返してくるのでJs.Opt.getでオプションを外してやる(要素が見つからなかったらassert falseここは公式サンプルに準拠

create_canvasdraw_squareで赤い四角の描かれたCanvasを作成してから、id=mainの要素の子として追加している。

最後にonload時のハンドラとしてこのstart関数を設定。ここでうっかり

let () = start ()

などとしてしまうと、スクリプトが読み込まれた時点ではid=mainなHTML要素がまだ作成されていないのでエラーだけ投げて何も起きない。ここらへんはJSではおなじみ。

HTMLにはid=mainなdivを追加しておく:

<html>
    <head>
        <script type="text/javascript" src="_build/default/main.bc.js"></script>
    </head>
    <body>
        <div id="main"></div>
    </body>
</html>

これでdune build ./main.bc.jsしてmain.htmlをブラウザで開けば白いCanvasの真ん中に赤い四角が描かれている。