はじめに
下記で電光掲示板ツール作った時とほぼ同じ構成でGifみたいに1文字ずつ画像をパラパラさせてみようとおもいます。
電光掲示板ツールについて
プロジェクトの作成
Rustで文字から画像を生成するために、文字とFontデータ(今回はNotoSansJPを使用)を受け取る。
今回は1文字のみを表示してパラパラさせるので半角、全角をなるべく中央に来るように
scaleやLayout時の座標などを設定する。
(今回はざっくり計算のpaddingで中央に寄せたので、、、
文字によってはずれている、、、)
最後に、Base64の文字列を返す。
lib.rs
// 省略
#[wasm_bindgen]
pub fn str_to_png(str:&str,font_data:&[u8]) -> String{
let ch = str.chars().nth(0);
let font = rusttype::Font::try_from_vec(Vec::from(font_data)).unwrap();
let scale = Scale::uniform(256.0);
let v_metrics = font.v_metrics(scale);
let glyphs: Vec<_> = font
.layout(&*ch.unwrap().to_string(), scale, point(65.0, 15.0 + v_metrics.ascent ))
.collect();
let glyphs_height = (v_metrics.ascent - v_metrics.descent).ceil() as u32;
let mut image = DynamicImage::new_rgba8(glyphs_height + 64, glyphs_height + 64).to_rgba8();
for glyph in glyphs {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
let pad = 220 - bounding_box.max.x;
glyph.draw(|x, y, v| {
image.put_pixel(
x + bounding_box.min.x as u32 + pad as u32,
y + bounding_box.min.y as u32,
Rgba([0, 0, 0, (v * 255.0) as u8]),
)
});
}
}
let mut buffer = Cursor::new(Vec::new());
image.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で文字数分ループさせて、
0.5秒ごとに1文字ずつ上記関数からBase64のImageを受けとり、
パラパラさせる🕺
index.js
// 省略
await fetchFontAsUint8Array("./NotoSansJP-Regular.ttf")
.then(uint8Array => {
for (let i=0;i<words.length;i++)
{
setTimeout(function() {
document.getElementById("mainImg").src = str_to_png(words[i],uint8Array);
if(i === words.length -1)
{
document.getElementById("GeneBtn").disabled =false;
}
}, i*500);
}
});
// 省略
これでメインの機能は実装完了!
残りのその他の実装して完成!!
今回の成果物
デモURL
デモ画像
画面(下記は静止画ですが、実際にはパラパラ自動で流れる)
ソース
まとめ
今回はRustを使ってGifのようなパラパラ文字作ってみました。🧑🎨
正直Gif使えば済む話なので、、、
何の役にも立ちそうにないが、気になったので
記事にしました。💪
※間違い等ありましたら、ご指摘いただけると助かります。