BLOG 雑記

土地擬お写真

2023.09.23 創作物

現在地に応じて土地擬スタンプを写真に貼れるwebアプリ作りました。
https://nih.lsv.jp/product/tochigi-photo/

旅行した時とかこんな感じで遊べます。

作り方

基本的にcanvas使ってdrawImageです。
使用ライブラリはスタンプ画像のドラッグリサイズにmoveable、遊び方スライダーにSplideです。

現在地取得

JSのgeolocationで取得、逆ジオコードはGoogle APIを使用しています。

カメラ起動

今回知ったけどinputで気軽にカメラ起動できた。
PCだとファイル選択になるっぽい。

スタンプ出力

取得した住所の県名で分岐、画像出力しています。
今回は県名基準だけど、市町村名だと全国で被る自治体あるし難易度跳ね上がりそう。住所の正規表現こわいよ〜。

スタンプ画像化

配置したあと確定ボタン押したらそれぞれ座標取得して描画。

画像保存・Xシェア

シェア時のテキストは現在地の県名が入ります。

苦労したとこ

スタンプ傾いた時の描画

1番難しかった〜。
傾斜つくと座標もサイズも変わるから計算大変。

スタンプ傾かせるとインラインにrotate入るんで条件分岐、getBoundingClientRect()で角度付いた状態の幅高さ取得。drowImageする際に先ほどのrotate流用するんですが、transformは中心が基準軸なのに対してcanvas.rotateは左上基準のためそのまま回転させると描画位置がずれます。回転軸を中心にしたいので、X軸+要素の高さ/2ずらして擬似的に中心で回転、回転したあと高さ/2分だけ戻して正しい位置になります。canvas.rotate、オプションとかで中心軸に出来るようならんかなあ。

殴り書きメモ。頑張ってるのが伝われば……。

スタンプ左右反転した時の描画

左右反転は (多分) moveableで対応してないので自分でscaleX追記させて対応したんだけど、これも面倒くさかったなあ。

左右反転だけならX軸を反対にすれば済むんだけど、傾斜もつくと前述した処理に加え反転した座標とか角度も気にしなきゃいけない。

しかもtransformのrotate後にscaleがつく場合、scale後にrotateがつく場合で角度の正負が変わるのでそれも条件分岐させました。もう二度と書けねえ。

スタンプリストの配置

flexで横並びにするとスタンプ拡大した際他のスタンプも移動してしまう……のでabsoluteで浮かせてます。ただそうすると拡大時の基準位置がなぜか左上になるので、さらに親要素をcreateElementしてflexで中央寄せにしました。
最初は変形対象をimgにしていましたが、max-widht指定していると拡大されないぽいのでabsoluteしているdivを対象にしてます。うーん良いのかなこれで。

写真サイズの計算

そのままだと画面上の300pxぐらいで出力されちゃうので、元画像との比率計算して乗算しています。ただbase64で出力されるので容量が重い……元画像が大きいと容量もえらいことになるので、最大幅1500pxに設定して条件分岐でaspectを変更しています。

Google API

サイトが見づらえ!
JSのgeolocationは緯度経度しか取得できないので、住所変換するのにGoogle APIを使用しています。
Google APIの無料枠超えないかビクビクしてたけど、月40000リクエストまで無料でテストで使ったのが450ぐらいだったから余裕だった😄✌️

画像シェア

完成画像をそのままツイート……が理想だけど出来ないので悩みました。最初ダウンロードボタンを設置してましたが、Safariだと写真じゃなくてファイルに保存されるので絶対見失うんですよね。

と思ってたらポケモンSVのアカデミーサイトが公開されて、レポートの画像出力とXシェアへの誘導が今やりたい事と全く同じ!……というわけで大いに参考にさせていただきました。ポケモンはいつだって私を救ってくれる。

 

あとはおまけのスタンプ画像一覧です。現地じゃないと見てもらえないの寂しいから、ぜひ現地行って遊んでみてね。