LoginSignup
40
23

More than 3 years have passed since last update.

wasmからDOMを操作してSVGを描画する

Posted at

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に追加してみましょう:

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(())
}

はまりポイントとしては、svgcircleを作る際にcreate_elementではなく、create_element_nsを使う必要がある事です。

これをコンパイルして実行するには

npm run serve

とします。npm関係の設定はほぼ全て元のサンプルそのままですので、詳しくはrust wasm bookwasm-bindgen guideを見てください。

最後に

40
23
0

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
40
23