map + area + excanvas.js で RollOver効果/Ver.2.0(複数要素対応板)
Ver.1.0 では、1ページに1つの<map>要素が存在する場合のみに対応していますが、実際にサイトを構築する場合は、複数の異なるベース画像を使い、複数の<map>要素が1ページ内に混在するケースの方が多いと思います。
Ver.2.0では1ページに複数の<map>要素が存在してもRollOver効果が得られる様、Ver.1.0に手を加えています。JavaScripでの処理部分が長くなるので、別ファイル(map2canvas.js)にして呼び出しています。
※Ver.1.0と同じく HTML4.01 でも動作すると思いますが未検証です。
複数要素対応版
HTML5では、<canvas>が標準でサポートされる事がほぼ確実なので excanvas.js は必要ありません。(IE8など、HTML5に対応していないブラウザもブラウジング対象にする場合は必要)
map_area_2.html : Sample Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>CANVAS TEST for MAP+AREA Ver.2</title>
<script type="text/javascript" src="map2canvas.js" ></script>
<!--[if lte IE 8]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
</head>
<body>
<h1><map> + <area> + excanvas.js で RollOver効果/Ver.2.0</h1>
<h2>::: 1 on Nx :::</h2>
<h3><map>画像1</h3>
<div id="plan_F1">
<img src="planA.png" alt="MasterPlan" width="600" height="600" border="0" usemap="#Map1" id="floor1" name="floor1" />
<map name="Map1" id="Map1">
<area shape="poly" coords="16,16,266,16,266,200,200,200,200,383,16,383" href="#" alt="room 1" title="Room No.1" />
<area shape="poly" coords="283,16,583,16,583,267,401,267,401,200,283,200" href="#" alt="room 2" title="Room No.2" />
<area shape="rect" coords="400,283,584,584" href="#" alt="room 3" title="Room No.3" />
<area shape="rect" coords="18,399,267,584" href="#" alt="room B" title="Room No.B" />
<area shape="rect" coords="283,398,383,583" href="#" alt="room i" title="Room No.i" />
<area shape="rect" coords="217,216,384,383" href="#" alt="Home" title="Room No.0 / Home" />
</map>
</div>
<h3><map>画像2</h3>
<div id="plan_room1">
<img src="planB.png" alt="Plan Room No.1" width="374" height="524" border="0" usemap="#Map2" id="room1" name="room1" />
<map name="Map2" id="Map2">
<area shape="rect" coords="19,19,174,123" href="../../index.php" alt="HTML" title="HTML" />
<area shape="rect" coords="19,129,173,239" href="#" alt="CSS" title="CSS" />
<area shape="rect" coords="20,246,173,357" href="#" alt="PHP" title="PHP" />
<area shape="rect" coords="20,363,173,474" href="#" alt="JavaScript" title="JavaScript" />
<area shape="rect" coords="181,21,315,152" href="#" alt="MySQL" title="MySQL" />
<area shape="rect" coords="192,183,303,223" href="#" alt="Room No.1" />
</map>
</div>
</body>
</html>
<div> や <map>タグに"id"を付与する際、各id名が重複しないように注意する必要があります。
また<img>の"usemap"の値と各map要素のname と id名は、先頭の#を除いた部分が同じである点に注意して下さい。
この値が異なると、どの<img>がどの<map>に対応するのか、ブラウザから見えなくなり正常に動作しません。Adobe の Dreamweaver(Webオーサリングソフト)などを使うと<img>と<map>の関係を自動で設定してくれますが、事前にCSSのセレクタとして設定した他の要素のid名と重複していないか確認して下さい。
map2canvas.js:サンプルコード
window.onload = function area_event(){
var map_tag = document.getElementsByTagName("map"); //文書内<map>全取得
for( h=0; h<map_tag.length; h++ ){ //<map>タグ全走査
var area_tag = map_tag[h].getElementsByTagName("area"); //<map>の<area>全取得
for( i=0; i< area_tag.length; i++ ){
if( area_tag[i].addEventListener ){
area_tag[i].addEventListener('mouseover', draw_img, false );
area_tag[i].addEventListener('mouseout', dele_img, false );
}else if( area_tag[i].attachEvent ){ //for under IE9
area_tag[i].attachEvent('onmouseover', draw_img );
area_tag[i].attachEvent('onmouseout', dele_img );
}else{
area_tag[i].onmouseover = draw_img;
area_tag[i].onmouseout = dele_img;
}
}
}
}
/*図形描画*/
function draw_img(evt){
var area_obj = new Object(); //初期化
if( evt.currentTarget ){
area_obj.mapid = evt.currentTarget.parentNode.id; //対象<map>:id取得
area_obj.id = evt.currentTarget.id;
area_obj.shape = evt.currentTarget.shape;
area_obj.coords = evt.currentTarget.coords;
}else{
area_obj.mapid = evt.srcElement.parentNode.id;
area_obj.id = evt.srcElement.id;
area_obj.shape = evt.srcElement.shape.toLowerCase();
area_obj.coords = evt.srcElement.coords;
}
xy = area_obj.coords.split(","); //座標配列化
for( i in xy ){
xy[i] = parseInt(xy[i]); //文字列 -> 数値化
}
var img_Usemap = "#"+area_obj.mapid; //相関<img>のusemap属性値
var img_tag = document.getElementsByTagName("img"); //文書内<img>全取得
for( i=0; i< img_tag.length; i++ ){
var usemap_Val = img_tag[i].getAttribute("usemap"); //<img>のusemap属性値取得
if( img_Usemap == usemap_Val ){ //一致判定
img_ID = img_tag[i].getAttribute("id");
img_SRC = img_tag[i].getAttribute("src");
img_ALT = img_tag[i].getAttribute("alt");
img_W = img_tag[i].getAttribute("width");
img_H = img_tag[i].getAttribute("height");
img_TOP = img_tag[i].offsetTop;
img_LEFT = img_tag[i].offsetLeft;
new_ID = "new_"+img_ID; //<img>:id属性値 -> <canvas>:id生成
var div_ID = document.getElementById(img_ID).parentNode.id; //<img>の親<div>:id
var div_ELE = document.getElementById(div_ID);
break;
}
}
var canvas = document.getElementById(new_ID); //<canvas>:id取得 -> 多重生成防止
if( !canvas ){
var canvas = document.createElement("canvas"); //canvas要素生成
div_ELE.appendChild(canvas);
if( document.uniqueID ){
canvas = G_vmlCanvasManager.initElement(canvas);
}
}
if( !canvas.getContext ){
return false;
}else{
canvas.setAttribute("id", new_ID);
canvas.setAttribute("width", img_W);
canvas.setAttribute("height", img_H);
canvas.style.zIndex = "-100";
canvas.style.top = img_TOP+"px";
canvas.style.left= img_LEFT+"px";
canvas.style.position = "absolute";
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle = 'rgba(0,0,255,0.4)'; //図形:色指定
if( area_obj.shape == "rect" ){
ctx.fillRect( xy[0], xy[1], xy[2]-xy[0], xy[3]-xy[1] );
}else if( area_obj.shape == "circle" ){
ctx.arc( xy[0], xy[1], xy[2], 0, Math.PI*2, false );
}else if( area_obj.shape == "poly" ){
ctx.moveTo( xy[0], xy[1] ); //始点指示
for( i=2; i<xy.length; i=i+2 ){ //(x,y)座標Loop
ctx.lineTo( xy[i], xy[i+1] );
}
ctx.closePath();
}
ctx.fill();
}
}
/*図形消去*/
function dele_img(evt){
var canvas = document.getElementById(new_ID); //<canvas>:id取得
if ( ! canvas || ! canvas.getContext ) {
return false;
}else{
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,img_W,img_H); //全カンバス図形消去(0,0,幅,高さ)
canvas.style.backgroundColor = "";
}
}
複数要素対応としていますが、同一ページ内に1つのmap要素しか存在しない場合でも動作するので、Ver.1.0より実用的かもしれません…(´・ω・`)