Android Eclair(2.0/2.1)ブラウザでCanvasを使うときの注意点。
- 詳細は@yukobaさんのブログにとても分かりやすく説明されていますので、自分が試した回避法について書きたいと思います。
Android Eclair(2.0/2.1)ブラウザのCanvasのdrawImage実装がバグっている問題。
- 上記のブログに書いてある通りなのですが下記のような問題があります。
- drawImageを使うと、「端末幅(screen.width) / 320」という計算式で自動的に拡大してくれます。。fillTextやfillRectなどはそのまま拡大されずに描画されます。
- 例
var image = new Image(); image.src = "http://www.google.co.jp/intl/en_com/images/srpr/logo1w.png"; image.onload =function(){ var ctx = document.getElementById('test').getContext('2d'); ctx.drawImage(image, 20, 20, 200, 100); ctx.fillRect(20, 150, 200, 100); };
回避方法
- これもブログに書かれている通りですが、drawImageをする前にscaleで「端末幅(screen.width) / 320」に自動拡大されるのを元に戻してやる必要があります。
- そうするには、「320 / screen.width」でscaleしたらいんじゃないかと思いますが、scaleが2回適用される問題があるので、2回適用されることを計算して平方根を指定する必要があります。
- でAndroid Eclairかどうか判定する処理を加えるとこんな感じでしょうか?
var image = new Image(); image.src = "http://www.google.co.jp/intl/en_com/images/srpr/logo1w.png"; image.onload =function(){ var ctx = document.getElementById('test').getContext('2d'); ctx.save(); // Eclair判定 if ( /Android\s2\.[0|1]/.test(navigator.userAgent)) { // 縮小 var rate = Math.sqrt(320 / screen.width); ctx.scale( rate, rate); } ctx.drawImage(image, 20, 20, 200, 100); ctx.restore(); ctx.fillRect(20, 150, 200, 100); };
反転させたい
- 上記の方法で勝手に拡大される問題については対応が可能になるのですが、自分のようにscale(-1, 1)で画像を反転させたいと思っていた人には困ったことになります。scaleが2回適用されるため、-1の平方根を取得する必要があります。。。
- というわけで困ったなぁと思って悩んで自分が見出した解決策は、「Canvasでやらなくていいんじゃね?」ということでCSS3で実装する方法です。こんな感じ。
var img = document.createElement('img'); img.style.position = "absolute"; img.src = "http://www.google.co.jp/intl/en_com/images/srpr/logo1w.png"; img.width = 200; img.height = 100; img.style.top = "20px"; img.style.left = "20px"; img.style["-webkit-transform"] = "scale(-1, 1)"; document.getElementById('parent').appendChild(img);
こんな感じでブラウザ実装のバグに遭遇することもありますが、CanvasとかCSS3とか楽しいですね。スマートフォン向けだとI.Eを考慮しなくていいのが何より嬉しいです。