やったこと
深夜の思いつきでこんなものを作ってしまいました。
このように縦書きの文章と画像を合成できます。
ソースコードはこちらです。
技術スタック
Vue3+Bulmaで作っています。今回、Cloudflare Pagesを使ってみたんですが、開発体験がとてもよかったです。プッシュしたら即時デプロイしてくれるのがありがたい。突然の思いつきを形にするにはもってこいですね。
仕組み
仕組みは割と単純で、 HTML+CSSで描画した後にDOM to Imageというライブラリを使って画像に変換しています。
HTML5だとCanvasに描画してからごにょごにょする方法もあるらしいですね。(作ってから知りました...)
また機会があったらやってみたい。
ここが困った
開発中に困ったことを備忘録的にまとめておきます。
Bulmaの導入方法がわからない
CSSフレームワークとしてBulmaを使おうと思ったんですが、Vueに導入する方法がわからず若干苦戦しました。
解決法
main.scssに次の一文を追加。
@import 'bulma/css/bulma.css';
main.tsでmain.scssを読み込む。
import '/src/assets/main.scss'
謎にscss使ってますがcssでもいけるはずです。今思いましたが、App.vueから直接読み込んでもよかったのかな...?
デザイン丸投げできるのでいいですね。
iOSでダウンロードできない
ダウンロード機能は次のように実装しています。新規でa要素を作り、hrefにbase64エンコードされた生成画像を指定、download属性を指定してクリックイベントを発生させることでダウンロードさせます。
//ダウンロード機能の部分のみ抜粋
(dataUrl) => {
const link = document.createElement("a");
link.href = dataUrl;
link.download = `tategaki.png`;
link.click();
};
テストしたところPCとAndroidでは問題なくダウンロードできました。
ですがiPadではなぜかボタンを押してもダウンロードできません......
調べてみるとどうやらiOS14からhref属性にbase64を指定しても開けなくなったようです。
解決法
苦肉の策としてiOS用に画像表示ボタンを追加し、表示された画像を長押しして保存してもらうようにしました。もっといい方法があるような気もしますが... 教えて偉い人。
画面幅に合わせて描画を調整したい
ウィンドウの幅が変わっても描画エリアが崩壊しないようにしたかった。
解決法
JavaScript標準搭載のResizeObserverを使ってリサイズを検知します。
Vueで使うときには監視したい要素にref属性を指定します。
const text_renderer = ref(null);
//~~~省略~~~//
onMounted(() => {
render(); //描画を更新する関数
const resizeObserver = new ResizeObserver(() => { //リサイズ時に呼び出されるコールバック関数
render();
});
if (text_renderer.value) {
resizeObserver.observe(text_renderer.value); //監視を開始
}
});
以下の記事が非常に参考になりました。
あとがき
完全に深夜テンションで作ったのですが、思ったより反響があってびっくりしました。
Vueのいい復習にもなりました。次はReactを使ってみたい気持ちがあります。