Attach an image from clipboard

ついで、クリップボードに画像が格納されている時、コメント欄で Ctrl+V を押すとそれを直接添付ファイルにする機能を実装してみよう。

基本的にはコメント欄の paste イベントで clipboardData.files を見てその中から画像っぽいものを取り出し、それを覚えておき、投稿時に upfile 要素の内容の代わりに使用する、だけ。

のだが、いくつかめんどくさい点がある。

  • 貼り付けた画像のプレビューを生成しなければならない。これ自体は普通に upfile 要素で選択された画像をプレビューする処理と同じで何か新しくコードを書くわけではない。ただし、基本的な流れは画像を示す file インスタンスの内容を img 要素に割り当て、読み込み完了後に canvas 要素に縮小描画するというもので、特に file→img を従来は data スキーム経由で行っていた。しかしこれはけっこう重い。そんなわけでそこを createObjectURL/revokeObjectURL で行うようにした。今までそうしなかったというのはつまり Presto Opera でも動かすためだ。でももう Presto Opera のことは忘れる
  • 貼り付けられた画像のサイズが、板に貼れる上限を超えている場合。クリップボードに格納されている画像は、おそらく確実にブラウザへは image/png 形式で渡ってくる。png なのでサイズ的には常に大きめだ。それが板の上限を超えていた場合は jpeg でエンコードし直す必要がある。

    その場合は file を canvas に描画した後 toDataURL(‘image/jpeg’) で jpeg エンコードされた data スキームの URL を得て、それを XHR で読み込んで arraybuffer として取得し、そこから blob を生成…となる。途中で生成した canvas はそのままプレビュー生成にも使う。この辺、なんか回りくどい。canvas に blob を返すエンコードメソッドを設けてくれれば、それを FileReader から好きに読み込めばいいので汎用的だと思うのだけど…。

    あと、真面目に作るなら、jpeg エンコードしてもなお上限を超えている場合を考慮して、段階的に jpeg のクオリティを下げていくようなループにするべきなのだが、そこまではしなかった。

    ちなみに板に貼れる上限というのは注意書きの中で例えば「2000KBまで」とか書いてあるのをパースして覚えておくのですが。2000KB というのは 2000*1024=2048000byte のことでいいんだろうか。それとも 2000*1000=2000000byte か? 試してみた所 2000000byte 超のファイルは受け入れられるようなので前者とみなすようにした

だいたいこんな感じ。

Leave a Reply

Your email address will not be published. Required fields are marked *