JavaScriptで縮小画像を作成してサーバーにPOST送信する方法

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

本日、JavaScriptで縮小画像の作成 | while(isプログラマ)のコメント欄にて、慎之助さんから下記のようにコメントがありました。

「画像を縮小して表示」サンプルと
「canvasで描いた絵をバイナリ形式でサーバーにPOST送信する方法 | while(isプログラマ)」のサンプルを元にして、
「JavaScriptで縮小画像を作成してサーバーにPOST送信する方法」を試行錯誤しながら作っていますが、なかなか出来ません。
そのやり方のサンプルを掲載されることを、とてもとても楽しみにいたしております。

canvasで描いた絵をバイナリ形式でサーバーにPOST送信する方法 | while(isプログラマ)を使って縮小画像をサーバーに送りたいのだけれども、できないということらしい。

自分も上記エントリーの最後に「できそうです」と書いているものの、実際に試したわけではないので、今回試してみました。

とりあえず、『JavaScriptで縮小画像の作成』で作ったサンプルページをもとに、それをPOST送信するようなプログラムを作ってみることにします。利用するサーバー側プログラムのPHPは『canvasで描いた絵をバイナリ形式でサーバーにPOST送信する方法』でも利用したPHPを何も変更せずに利用することに。

結論からいうと、できました。
サンプルページ:画像を縮小して表示してPOSTでサーバーに送信
画像をアップすると、その下にアップした画像を指定分縮小した画像が表示されます。ファイルを選択するとすぐにアップロードする仕組みになっているので、ネットに公開したくない画像を間違って選択してしまわないように注意してください。もし間違えた場合は、すぐに公開してもいい画像をアップロードしてください。

『JavaScriptで縮小画像の作成』で作ったサンプルページの変更点としては、jQueryを使ってなかったので、jQueryを呼び出し、base64形式の文字列をBLOB形式にするbase64ToBlobという関数とBLOB形式のファイルをPOSTで送信するsendImageBinary関数を追加しています。

後は、canvasのtoDataURLメソッドでBase64形式の文字列を取得し、それをbase64ToBlobの引数にいれて、さらにその戻り値をsendImageBinaryの引数にいれるということをしています。

ただ、そもそも慎之助さんがどこで躓いていたのかが分からないので、注意点を言っておくと、古いブラウザだと動きません。例えば、IEだと10以降でないと動きません。また、サーバーの設定でファイルの作成や書き込みができないようになっているとうまくいきませんし、アップする画像が大きい場合にもうまくいかない可能性があります。

さて、ここまできたら、ExifのOrientationを見たうえでcanvasに画像を表示できるJSライブラリ | while(isプログラマ)で書いた内容をもとに、Exifも考慮して縮小画像を作成し、POSTで送信するということもできるはずです。そこまでは実装してませんが、興味ある人は試してみてください。

CSSとJSで要素の背景にcanvas画像を設定する方法

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

WebKit系とFirefox限定です(IEでは利用できない)。

CSSのbackgroundプロパティにおいて、WebKit系のブラウザにはcanvas()関数、Firefoxではelement()関数という値が指定できます。canvas()関数は、canvasに描画したものを背景に設定できる関数で、element()関数は指定の要素を画像として扱い背景にすることができます(残念ながら、背景にしかできない)。

で、これに関連してWebKit系のブラウザのJavaScriptにはgetCSSCanvasContextメソッド、FirefoxにはmozSetImageElementメソッドというものが用意されています。これは、どちらもブラウザ上でcanvasを作成し、ブラウザ上にcanvasを描画せずにcanvas画像を背景に設定できる機能です(参考:[CSS3] (Webkit専用) CSSを用いて要素の背景にCanvasを指定する – YoheiM .NETCSSのelement()関数 – Weblog – Hail2u.net)。

関数が違うので、どちらも共通の指定でcanvasの背景画像を作成できるように関数を作ってみました。

この関数からえたコンテキストを利用すると、WebKit系でもFirefoxでも同じ処理で背景用canvasを取得できます。
利用例は以下のような感じ。

CSSは下記のように書きます。

というわけで、以下実行サンプルです。

正直、そこまで実用性があるわけではなさそうですが、こういうことができるという紹介。IEにも対応したい場合は、canvasのtoDataURLでBase64の画像データを取得して、それをJavaScriptを用いて要素の背景に設定するという方法でできそうです(というより、それでcanvasに対応している全てのブラウザに対応できる)。

HTML5のcanvasで描画する文字の後ろに白地をつける方法

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

本題に入る前に一つ問題です。Canvasで文字を描画(fillTextメソッドを利用)する時、文字の縦基準位置を指定しない、つまりデフォルトの場合、文字は指定座標にたいしてどの位置に描画されるでしょう。次の3つの中からお選びください(点は指定座標の位置)

drawTxt1 drawTxt2 drawTxt3
文字より上の位置 文字の縦中央の位置 文字より下の位置

続きを読む

canvasのお絵描きツールに拡大機能をつけてみる

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

久々にcanvasのお絵描きツールに機能を追加してみた。今回追加した機能は拡大機能。

最初は、拡大画像用のcanvasを新たに作成してそこにdrawImageメソッドを使って、拡大した部分を描画し、終わったらその拡大画像用のcanvasを逆にdrawImageメソッドで元のcanvasに描画したらいけるかなぁ・・・。なんて思っていたのですが、どうにもそのやり方に少し抵抗があってなかなか手につけられずにいました。『canvas 拡大』と検索するとcanvasのtransformメソッドについてでてきましたが、何か違う気がします。あくまで今から描画する図形に対しての指定みたいなので。

ただ、transformという単語をみてふと思いました。そういえば、CSS3にtransformというプロパティがあったよな・・・と(参考:transform – CSS | MDN)。

結論からいうと、このtransformプロパティを使ってお絵描きツールの拡大機能を実装することができました。というわけで、以下そのソースコードの説明。

とりあえず、今までcanvas部分にはボーダーをつけていたのですが、transformで拡大するとボーダーまで拡大してしまうので、divタグで囲んでそのdivタグにボーダーをつけることに。

HTML

CSS

また、canvasを拡大するとdivタグからはみ出して表示されてしまうので、overflowプロパティをhiddenにして拡大してはみ出した部分は非表示とすることに。そして、transform-originプロパティで拡大するときの原点を要素の左上に指定しています(参考:transform-origin – CSS | MDN)。

つづいてメインの拡大機能の実装部分。拡大機能にはラジオボタン選択ではなく、Hammer.jsを使ってダブルクリック(もしくはダブルタップ)すると2倍に拡大することにしました。

JavaScript

これで拡大はうまくいきました。scaleFactorという変数が拡大率を表しています。もう一度ダブルクリックすると元の大きさに戻るようにもしています。

ただ、これだと拡大した後に描画しようとすると、ペン先の位置が右下にズレてしまうので、描画のx座標とy座標をscaleFactorで除算することに。

以下、動作サンプル。
canvasを使ったお絵描き投稿システム

拡大するときには『塗りつぶし』ではなく、『ペン』を選ぶようにしてください。塗りつぶしを選んでいる状態だとおかしな動きになりました(いまさらだけど、やっぱり普通にラジオボタンで『拡大』を増やしてそこで拡大するかどうかを判定すればよかったかもしれない)。

今回作った機能はcanvasの拡大だけではなく、画像の拡大なんかにも利用できそうです。縮小した画像を表示させといて、ダブルクリックするとその位置を拡大するというような動きにしたり(試してませんが)。

ExifのOrientationを見たうえでcanvasに画像を表示できるJSライブラリ

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

先日、画像を縮小して表示するページを作成してこのブログで紹介しました(JavaScriptで縮小画像の作成 | while(isプログラマ))。

ただ、このページからiPadやiPod touchで開いたうえで、ファイルの選択から『写真を撮る』を選び、縦向き(縦長)にして写真を撮ってみると、縮小した写真は横向きに表示されてしまいました。これは、写真が標準で縦表示になっているわけではなく、Exif情報のOrientation(向き情報)によって縦方向の写真となっているためにおこります。HTML5のcanvasではどうやらExif情報を考慮してくれないようで、そのため縦に撮った写真が横に表示されてしまったというわけです(それどころか、Orientationによって縦表示とされている写真をimgタグで普通に表示させても、PCのブラウザからは横表示になってしまうという)。

ただ、これでは少し困るのでOrientationを見たうえで実際の方向通りにcanvasに描画する方法はないものかと思って探してみたところ、『JavaScript Load Image』というJavaScriptライブラリを見つけました。相変わらず英語は苦手なので全部わかったわけではないのですが、どうもExif情報を見るライブラリらしく、Exif情報を見たうえで画像をcanvasに表示することができるライブラリだそう。サンプルを使ってみると確かにOrientationで縦向きとなっている画像が、縦向きになってcanvasに描画されました。これはすごいよさそうです。

というわけで、上記ライブラリを用いたうえで、先日の画像縮小ページのJavaScript部分を下記のように変更してみました。

以下、実行サンプル。
画像を縮小して表示

Base64形式のURI Dataの画像をいれても画像は表示されるようなのですが、Exif情報が取得できませんでした(そのため、わざわざ画像をロードしたうえで、その幅を取得している)。

Exif情報が取得できた場合、開発者ツールのコンソール画面に一覧して表示するようにしてみました。PCにExif情報のついた写真がある場合はそれをアップしてみて確認してください。Exif情報と一言でいっても、いろんな情報があるものですね。自分でも試してみましたが、ほとんどundefinedでした(表示している一覧はundefinedとなった情報は省いています)。