こんにちは。fujimuraです。
今回は次回リリース予定のコンテンツに利用されている小技についてお話します。
ちょっとフライングですね。
Canvasのクリックされた場所の色を取得する
Canvasのクリック箇所によって処理を変えたい場合など有効な技になります。
※Canvasって何?という方はこちらを参照してください → http://www.html5.jp/canvas/what.html
例えば、
日本地図の画像をCanvas上に描画し、クリックされた都道府県がどこかを判定したい時、
いちいち座標から計算して割り出すのは大変です。
そんな時は、
①各都道府県別に色を変えた画像を用意します。
この時、画像にアンチエイリアスを使用しないでください。
アンチエイリアスを使用すると色が変わってしまいますからね。
実はこれで少し嵌りました。。。
後述のソースコードで、rgb値を 都道府県コード*2 にしたり、
Math.ceil(color.r / 2) としたりしてたのはその名残りです。
②クリックされた箇所の色を取得して、その色に対応する都道府県を割り出します。
といった感じにします。
簡単ですね。画像を用意する方が難しいくらいです。
ただし、このままでは都道府県ごとに色を変えたくない場合などに不都合が生じますので、その場合は表示用と判定用の画像、2種類を用意します。
ソースコードは以下のようになります。
var $j = jQuery.noConflict();
var pathM = "http://labs.microad.jp/blog/wp-content/uploads/2013/02/map.png";
var pathI = "http://labs.microad.jp/blog/wp-content/uploads/2013/02/index.png";
/* 日本地図作成 */
function createJapanMap(container) {
var $container = $j("#" + container);
/* 表示用Canvas */
var canvasM = document.createElement("canvas");
// 適当なサイズ
canvasM.width = 300;
canvasM.height = 300;
/* canvas対応チェック */
if (!canvasM || !canvasM.getContext) {
$container.text("利用ブラウザはCANVASに対応していません。");
return;
}
/* 判定用Canvas */
var canvasI = document.createElement("canvas");
/* 表示用と大きさを合わせる */
canvasI.width = canvasM.width;
canvasI.height = canvasM.height;
/* 表示用canvasのみ追加 */
$container.append(canvasM);
/* 描画機能取得 */
var ctxM = canvasM.getContext("2d");
var ctxI = canvasI.getContext("2d");
/* 指定座標の色を取得 */
ctxI.getColor = function(x, y) {
/* 指定座標の色を取得 */
var bit = this.getImageData(x, y, 1, 1);
/* 配列に r g b a の順で格納されている */
var buf = bit.data;
var color = {r: buf[0], g: buf[1], b: buf[2], a: buf[3]};
return color;
};
var imgM = new Image();
imgM.onload = function() {
/* 画像読み込み後描画 */
drawImage(canvasM, ctxM, this);
};
var imgI = new Image();
imgI.onload = function() {
/* 画像読み込み後描画 */
drawImage(canvasI, ctxI, this);
};
/* 表示用Canvasにクリックイベント処理追加 */
$j(canvasM).click(function(e) {
var x, y;
/* 各ブラウザ用の処理 */
if ($j.browser.mozilla) {
var off = $j(this).offset();
x = (e.pageX - off.left);
y = (e.pageY - off.top);
} else {
x = (e.offsetX == undefined) ? e.layerX : e.offsetX;
y = (e.offsetY == undefined) ? e.layerY : e.offsetY;
}
/* 判定用Canvasの色を取得 */
var color = ctxI.getColor(x, y);
/* r = 都道府県コード * 2 */
var pid = Math.ceil(color.r / 2);
if (pid > 0 && pid <= 47) {
alert("都道府県コード:" + pid + " が選択されました。");
}
});
/* 画像読み込み */
imgM.src = pathM;
imgI.src = pathI;
}
/* 画像をcanvasに描画する */
function drawImage(canvas, ctx, image) {
/* 画像の幅をcanvasに合わせる */
var sc = canvas.width / image.width;
var iw = Math.floor(image.width * sc);
var ih = Math.floor(image.height * sc);
ctx.drawImage(image, 0, 0, iw, ih);
}
$j(function() {
/* 呼び出し */
createJapanMap("canvas_frame");
});
実行結果
といった感じで、判定用のCanvasはHTML上に追加しないので表示されることはありませんが、実際にクリックされた座標と照らし合わせ判定を行っています。
判定用の画像は、rgbの値をそれぞれ 都道府県コード*2 に設定していますが、rの値だけで判定しています。
前回の記事にソースコードが足りないと指摘があったので、今回は全部入れてみました。
誰かのお役に立てれば幸いです。
ではまた。
fujimura









