jQueryとcanvasを使ってイメージマップでhoverすると色かわるみたいな〜
サンプルはこちら→W7工廠分室|トップページ
■目的
イメージマップってマウス乗っても色変わらないし〜、ロールオーバー時の画像を1つずつ用意するのって面倒だし〜
・・・とかそういう場合にどうぞ。
図で表すとこうなります。既存のイメージマップの下にcanvasを(以下略w)
■仕様
・XHTML1.0, HTML4.01/5で動作します
・ブラウザは各種最新版でチェック、IE6〜IE8もチェック
・altへのアクション(ツールチップ的な説明)も考えていたのですが、別ツールのほうがいいと思いやめましたw
■不具合
・IE7でimg要素とcanvas要素が少しずれる(imgのopacity=0でもいいかも)
・IE9のDOCTYPE無指定で動作しない←IE判定部分をかえれば多分いけます
・IE6のHTML5で動作しない
■注意事項
・img要素はz-index:1以上であること
・usemap属性名は小文字(useMapはだめ)かつ属性値にピリオドなし(usemap="#***.***"はだめ)
・img要素の親要素(liやdivなど)にposition:relativeがかかります。
・area要素の属性にcolor='rgba(赤, 緑, 青, 0.7)'を入れればhover時に部分ごとに色を変えることもできます。
(ここは勝手に属性でっちあげてるので、HTMLの仕様に反していると思いますが・・・使い勝手を考えると外せません。)
■更新履歴
2012-06-04 特定環境でのエラー現象(ChromeとWindowsとIntel Atomの組み合わせでcanvasの描画がおかしいとか〜 - w7工廠)
2012-03-14
・shape.toLowerCase();を移動(取得時に変換・・・あたりまえですね)
・canvasのcss設定でposition:absolute;わすれてましたw(これをつけるととんでもないことにw)
・動作チェックしました。
・記事を整理しました。
2012-02-18
・コードに解説(コメント)追加しました。
2012-01-23
・Rect描画はIEでもできてました(汗)→RectのIE処理削除
・beginPath(),fill()の位置を変更。
・IE判定をjQueryのみにしました。
・coordsを文字列で渡していたので数値変換を追加しました。(これをしないとIE6で円が半円になるという・・・)
・上記を確認するためにhtml(地図版)の左上に四角・右上に丸のareaを追加。
・「_引数」を「引数」に修正←分かる人には分かる勘違い
2012-01-08
・クラスっぽくしたついでにタイトルも変更しました
(area mapとjQueryとcanvasを使ってクリッカブルマップロールオーバーとか〜 - w7工廠)
2011-10-05
・IE6対応(areaの値が大文字(poly→POLYなど)で渡されていたのでtoLowerCaseを追加しました)
■内容
XHTML(head)
<script type="text/javascript" src="jquery.js"></script> <!--[if lte IE8]><script type="text/javascript" src="excanvas.js"></script><![endif]--> <script type="text/javascript" src="jq_imgMapToCanvas.js"></script>
XHTML(body)
<div> <img class="imgMapToCanvas" usemap="#***" src="画像" width="幅" height="高さ" border="0"/> </div> <map name="***" id="***"> <area shape="rectまたはcircleまたはpoly" color='rgba(200, 200, 0, 0.7)' //色を付けたいとき coords="座標" href="リンク" /> </map>
JavaScript (jq_imgMapToCanvas.js)
/* jq_imgMapToCanvas.js 2010-12-15→2012-01-23*/ $(function(){ imgMapToCanvasInit(); $("area").hover( //図形の形・座標取得→描画・消去 (ここから先thisはarea要素を示す) function(e){//area:hover時 var id="canvas_"+$(this).parent().attr("name");//hoverになったareaのmapのname属性からidを取得 var shape=$(this).attr("shape").toLowerCase();//circleまたはpolyまたはrect、IE6は大文字取得なので小文字変換 var coords=$(this).attr("coords").split(",");//areaのcoords(座標)をカンマ区切りで配列に格納 for(i in coords){coords[i]=parseInt(coords[i]);}//文字列→数値 //areaから色取得(area色情報無しの場合初期値) var color=$(this).attr("color");//色取得 if(!color){color='rgba(255, 100, 0, 0.7)';}//areaに色指定していない場合の初期値 imgMapToCanvasDraw(id,shape,coords,color);//値をdrawする }, function(e){//area:hover解除時にid指定→クリア var id="canvas_"+$(this).parent().attr("name");//hoverになったareaのmapのname属性からidを取得 imgMapToCanvasClear(id);//値をclearする } ); }); function imgMapToCanvasInit(){ $("img.imgMapToCanvas").each(function(){//すべてのimgMapToCanvas設定されたimg要素を処理 //親(divやliなど)をrelative $(this).parent().css("position","relative");//div要素をposition:relativeに設定 //イメージ属性 var position=$(this).position(); var height=$(this).attr("height");//img高さ=canvas高さ var width=$(this).attr("width");//img幅=canvas幅 var src="url("+$(this).attr("src")+")";//img画像名=canvas背景 var useMap=$(this).attr("usemap").split("#")[1];//usemap属性から#をとる var id="canvas_"+useMap;//上記をcanvasのidとする(canvas_***) //canvas設置 var canvas = document.createElement("canvas");//canvas要素生成 $(canvas).attr({"id":id,"width":width,"height":height});//canvasの幅・高さ設定 $(this).before(canvas);//img要素の前にcanvasを設置 if (!jQuery.support.opacity) {//IEの場合 canvas = G_vmlCanvasManager.initElement(canvas);//IEの場合のcanvas初期化 } //canvasに透明度1,z-indexを背面,positionを設定,背景にimg要素 $("canvas#"+id) .css({"opacity":"1.0","zIndex":"1","position":"absolute","top":position.top,"left":position.left,"backgroundImage":src}); //img要素を透明度0.1(うっすらと),z-indexを前面,positionを設定 $(this) .css({"opacity":"0.1","zIndex":"100","position":"absolute","top":position.top,"left":position.left}); }); } function imgMapToCanvasDraw(id,shape,coords,color){ var canvas = document.getElementById(id); if (!canvas || !canvas.getContext) {return false;} var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = color; switch(shape){ case "rect"://矩形の場合 ctx.fillRect(coords[0],coords[1],coords[2]-coords[0],coords[3]-coords[1]);//(x1,y1,x2,y2) break; case "circle"://円の場合 ctx.arc(coords[0],coords[1],coords[2],0,Math.PI*2,false);//(x,y,r,開始角度,終了角度,描画方向) break; case "poly"://不定形の場合 ctx.moveTo(coords[0],coords[1]);//最初の点 for(var i=2;i<coords.length;i=i+2){//(x,y)を繰り返す ctx.lineTo(coords[i],coords[i+1]); } ctx.closePath(); break; } ctx.fill(); } function imgMapToCanvasClear(id){ var canvas = document.getElementById(id); if (!canvas || !canvas.getContext) {return false;} var ctx = canvas.getContext('2d'); var width=$(canvas).attr("width"); var height=$(canvas).attr("height"); ctx.clearRect(0,0,width,height); //全カンバス図形消去(0,0,幅,高さ) }