はじめに
前回RustとWebAssemblyで拡大鏡ツール作った際に、mouse操作中でもそれなりのパフォーマンスで画像を加工できたので、
Canvasタグ使わなくてもImgタグに直接お絵描きできそうだと思ったので実際にやってみる。🖌️
前回作った拡大鏡ツールについて
プロジェクトの作成
まず、load時にCanvas代わりとなるImageを表示する。
(今回は白紙の320pxベース)
lib.rs
// 省略
#[wasm_bindgen]
pub fn set_canvas() -> String {
let canvas = DynamicImage::new_rgba8(320, 320);
let mut buffer = Cursor::new(Vec::new());
canvas.write_to(&mut buffer, ImageFormat::Png).unwrap();
let base64_string = general_purpose::STANDARD.encode(buffer.get_ref());
// データURL形式で返す
format!("data:image/png;base64,{}", base64_string)
}
// 省略
次にパフォーマンスを考慮してmouseupのタイミングで
Imgタグの画像とmousemoveで通過した座標を受け取り、
受け取った座標をつなげて線にして画像に描画するような処理を実装する。
lib.rs
// 省略
#[derive(Serialize, Deserialize)]
struct Point {
x: f64,
y: f64,
}
#[wasm_bindgen]
pub fn draw_canvas(str_url: String,json_str :String) -> String {
let points: Vec<Point> = serde_json::from_str(&*json_str).unwrap();
let comma_pos = str_url.find(',').unwrap();
let str_base64 :String =Some(&str_url[comma_pos + 1..]).unwrap().to_string();
let image_data = general_purpose::STANDARD.decode(str_base64).unwrap();
let mut img = image::load_from_memory_with_format(&image_data, ImageFormat::Png).unwrap();
let color = Rgba([0, 0, 0,255]);
// 座標をつなげて線を描画
for i in 0..(points.len() - 1) {
let start = &points[i];
let end = &points[i + 1];
draw_line_segment_mut(
&mut img,
(start.x as f32, start.y as f32),
(end.x as f32, end.y as f32),
color,
);
}
let mut buffer = Cursor::new(Vec::new());
img.write_to(&mut buffer, ImageFormat::Png).unwrap();
let base64_string = general_purpose::STANDARD.encode(buffer.get_ref());
// データURL形式で返す
format!("data:image/png;base64,{}", base64_string)
}
// 省略
この上記関数をJavascript側でmouseupのeventで呼び出す。
index.js
// 省略
mainImg.addEventListener("mouseup", (event) => {
document.getElementById("mainImg").src = draw_canvas(mainImg.src, JSON.stringify(myXY));
pressed = false;
myXY.length = 0;
});
// 省略
メインの処理は実装したので、
残りのmouseやtouchのevent処理を実装すれば完成!💪
今回の成果物
デモURL
デモ画像
ソース
まとめ
今回はRustとWasmでImgタグをCanvasタグの代わりにしてみました。🎨
正直、なんの役にも立ちそうにないですが、、、
気になったので記事にしてみました。📝
※間違い等ありましたら、ご指摘いただけると助かります。