Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

wasm-bindgen / DOM Hello World!を改造してSVGを出力してみます。全体のコードは以下にあります

https://github.com/termoshtt/wasm-svg-example

準備

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を見てください。

最後に

ricos
FEMによる構造解析、機械学習の専門家集団。計算資源のクラウド提供もしています。
https://www.ricos.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away