wasm-bindgen / DOM Hello World!を改造してSVGを出力してみます。全体のコードは以下にあります
準備
npmとwasm-packをインストールしておきます。
cargo install wasm-pack
npmのインストール方法は環境に合わせて適当に構築してください(詳しくないので丸投げ)
web-sys
web-sysはwasm-bindgenでのsubcrateで、
- DOM
- Web Audio
- 2D canvas
- Web GL
- fetch
の機能からなる低水準のAPIです。今回使うのはDOMの部分で、これによりDOMを操作してSVGを挿入する事が出来ます。ますweb-sys
crateをCargo.toml
に追加してみましょう:
[package]
name = "dom"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.48"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'HtmlElement',
'SvgElement', # 追加
'SvgCircleElement', # 追加
'Node',
'Window',
]
これは上述のサンプルからコピペしたものですが、一応SVG周りの使う要素をfeatures
に追加しておきました。これは現行では非常にたくさんのfeatures
が設定されていますが、将来的にはまとめたのを作るという方針のようです。
SVGを挿入する
まず空っぽのHTMLを用意します
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<p>SVG from rust/wasm!</p>
</body>
</html>
この<p>
要素の下にSVGを追加する事を目指しましょう。
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
let body = document.body().expect("document should have a body");
// SVGの描画領域を作る
let svg = document.create_element_ns(Some("http://www.w3.org/2000/svg"), "svg")?;
svg.set_attribute("width", "100")?;
svg.set_attribute("hight", "100")?;
svg.set_attribute("viewBox", "0 0 100 100")?;
// 円を描画
let circle = document.create_element_ns(Some("http://www.w3.org/2000/svg"), "circle")?;
circle.set_attribute("cx", "50")?;
circle.set_attribute("cy", "50")?;
circle.set_attribute("r", "20")?;
circle.set_attribute("stroke", "black")?;
circle.set_attribute("fill", "red")?;
svg.append_child(&circle)?;
body.append_child(&svg)?;
Ok(())
}
はまりポイントとしては、svg
とcircle
を作る際にcreate_element
ではなく、create_element_ns
を使う必要がある事です。
これをコンパイルして実行するには
npm run serve
とします。npm関係の設定はほぼ全て元のサンプルそのままですので、詳しくはrust wasm bookかwasm-bindgen guideを見てください。
最後に
- これはRustオンラインもくもく会 #4の成果です