Railsで画面の一部をキャプチャして画像としてダウンロードできる機能をつけてみた。
(photo credit: Stuck in Customs via photopin cc)
絶賛運営中の「THE TOURNAMENT」ではトーナメント表をjsで出力してて、
これはこれでインタラクティブな感じにできたりといいんですが、やはり画像で保存したいというニーズも根強い。
そこで画面のこの部分だけを画像としてダウンロードできる機能をつけてみた。
よくある機能な気がしてたし余裕かと思ったけど意外とめんどくさかったです。。
まずは今回の要件を完璧に満たしてくれる都合のいいgemでもないかなーと探してみたけど、たぶんない。
(もしあったら教えてください)
ただ部分部分をやってくれそうなパーツは見つけたので、それを組み合わせて今回の機能を実現します。
html2canvas.jsでDOM要素を指定してcanvasに変換
HTML5のtoDataURLでcanvasをDataURLに変換
HTML5のdownload属性にDataURLを指定してダウンロードボタンを有効化
という感じでやりました。
ちょっとめんどくさいけど順番に見ていきますか。
html2canvas.jsでDOM要素を指定してcanvasに変換
DOM要素をいきなり画像にしてくれるのはなかったので、canvasに変換してくれるのでがまん。
でも簡単につかえてかなり便利。
まずは公式サイトからjsファイルをダウンロードして、railsのassets/javascriptsに配置。
application.jsから読み込んでおきます。これでとりあえず準備オッケー。
html2canvas($(".hoge"), { onrendered: (canvas) -> # xxxxx })
という感じ。$('.hoge')のとこはキャプチャしたい要素のに置き換えてくださいませ。 xxxxxのところがcanvasに変換したあとの処理になるので次にここを見てみます。
どうでもいいけど大体ドキュメントは素のjsやから、coffee scriptでどう書くのかいつも悩む。。
toDataURLでcanvasからDataURLに変換
お次はこのcanvasをDataURLに変換します。
プログラミングで飯を食え。腕をあげたきゃ備忘録!「そもそもDataURLとは!?~canvasを画像に変換する方法(toDataURL())!①」
そもそもDataURLって何やっけってところから復習しつつ変換。
html2canvas($(".hoge"), { onrendered: (canvas) -> canvasImage = canvas.toDataURL("image/jpeg") })
これだけ。
拡張子は"image/jpeg"と"image/png"が選べるみたいですな。
HTML5.jp「toDataURL()メソッド」
さぁ最後はこのデータをダウンロードできるようにするだけです。
HTML5のdownload属性つかってダウンロードリンクをつくる
そういうえばダウンロードリンクって作ったことがなくて、どうやるんかなーと調べたら
単純にリンク先がブラウザで解釈できん形式やとダウンロードするって感じなんですな。
そしてこれやと画像の場合ブラウザが解釈できちゃうので画面左上に画像だけ表示される、
みたいなよくあるかっこわるい感じになってしまう。別にいいんですけどね。
もうちょっと調べてみたらHTML5でdownload属性ってのができて、簡単にダウンロードリンクを実現できるみたいでした。
WORKABROAD「HTML5を使ってファイルを表示させずにダウンロードさせる方法」
# views %a.hoge(href="#" download="hogehgoe") ダウンロードリンクだよ
という感じの空リンクを用意しといて、DataURLが用意できたらhrefにセットします。
# javascripts html2canvas($(".hoge"), { onrendered: (canvas) -> canvasImage = canvas.toDataURL("image/jpeg") $(".hoge").attr('href', canvasImage) })
これでリンククリックすると変換された画像がダウンロードされました!
しかし、せっかくdownload属性でファイル名指定してるのに全然効かず、download.jpegになってしまう。
hrefにDataURL指定せんかったらちゃんと反映されるから、これが悪さしてんのか。。
しばらくがんばったけどまだ情報も少なくて解決せず。
うーんちょっと気持ち悪いけどしょうがない。。
最後にBootstrapのデフォルトComponentをつかってダウンロードリンクの表示をいい感じにしてみます。
やりたいことは、ダウンロードの準備ができるまではリンクボタンをLoading..表示にして、
準備ができたらクリック可能状態にするという感じ。至れり尽くせりですな。
# views %a.hoge.btn.btn-sm.btn-default(href="#" download="hogehoge" data-loading-text="画像ダウンロードの準備をしています...") 画像ダウンロード # javascripts $(".hoge").button('loading') #=> loading状態にしとく html2canvas($(".hoge"), { onrendered: (canvas) -> canvasImage = canvas.toDataURL("image/jpeg") $(".hoge").attr('href', canvasImage) $(".hoge").button('reset') #=> 完了したらクリック可能状態に戻す })
実物を見たい方はこちらをどうぞ。トーナメント表の下にダウンロードボタンがあります。
(PC版でしか表示されません)
THE TOURNAMENT「FIFAワールドカップ 1990 イタリア大会」