2016-07-02 5 views
1

は基本的に、私はHTML/CSS/JavaScriptでこれを作成する必要があります。 enter image description here<img>に、矩形ではないクリック可能な「押しピン」要素を配置する方法は?

あなたが見ることができるように、それはニューヨークのマップです。マップの下のアイコンの1つをクリックすると、地図の左下のピンなどが特定の場所に表示されます。ユーザーはそれをクリックして、他のdivが何らかのテキストでポップアップするようにする必要があります。これは私が迷っている場所です。

-すべてのパワープラントピン、すべての造船所ピン、すべてのスチールミルピンを含む別の3つの画像を作成し、それらをZ-インデックス付きマップの上に配置します。唯一の問題は、ユーザーが最高のZインデックスを持つ画像をクリックできることです。たとえば、造船所と製鉄所の両方を有効にすると、最後に追加されたピンのみをクリックすることができます。これは私がこの考えを落としたところです。

- 絶対位置のdivを使用して地図の細分を複製します。しかし、divは長方形であり、細分はそうではありません。だからこれも良いことではありません。

- イメージマップを使用します。私は1990年代からこれらを使っている人は誰も聞いていない。とにかく、私はマップが私を助けてくれる方法はわかりません。私はそれらのハイパーリンクではなく、それらを配置する必要があります。

私は任意の提案/プラグインにオープンしています。

+0

答えが有用な場合は、受け入れるかコメントするのを忘れないでください! –

答えて

3

あなたはこの回答を愛していないかもしれませんが、他に誰も何も示唆していないので、ここで私はそれをやっていますか(実際には複数のレイヤーを持つ画像マップを使用していますが、 ):

オプション1:SVGとしてマップとピン全体を行い、svgコードをhtmlに貼り付けて、javascriptクリックイベントを貼り付けます。 SVG要素はhtml要素と同じDOMイベントを使用でき、配置、拡大縮小、および整形できます。あなたはCSSルールとクラスでそれらを隠すことさえできます!

SVGは実に洗練されたブラウザで、非常に洗練されたソリューションであり、あなたのアート資産をその形にすることができれば、それはおそらく私がやる方法でしょう。あなたはsvgのための様々なツールとチュートリアルをオンラインで手に入れることができるので、これを残しておきます。ちょうどjavascriptのイベントがそれを処理することを覚えておいてください!

オプション2:HTMLで自分でやってください。それはデスクトップアプリケーションで使用されているのと同じアイデアですが、ウェブではあまり標準ではないので、もう少し詳しく説明してください。

  1. 4つのイメージ(マップとピン)を作成します。

  2. 透明でクリック可能な部分を示すピンのビットマップであるデータ配列を作成します。これは、1をクリックすることができ、0はできないところで形状を形成する矩形です。この技術は、マウスカーソルやそのようなもののためにデスクトッププログラムで多く使用されています。それを作る最も簡単な方法は、おそらく画像エディタを使用して白と黒にクリアしてから書き出すことです。 GIMPはxpmにエクスポートすることができます。これは手動で修正してJavascriptを簡単に作成することができます。

  3. 各ピンの位置のデータ配列を作成します。 (理想的には、これは絶対的に配置されたHTMLリンク要素のリストとしてこれを行います。なぜなら、それは正常に劣化するデータ形式であるからです(不完全な場合はJavascriptを使わずにイベントを待ちます)。)

  4. すべての画像を含むdiv にイベントリスナーを置き、クリックの座標を使用してデータ配列のピンを検索します。必要に応じてビットマップを使用して下降させます。可能なオブジェクトをループして、境界の矩形内にあるかどうかを確認します。その場合は、ビットマップを確認してください。クリック可能な場合はヒットします!そうでない場合は、次のものに進みます。必要に応じて

リニア検索を使用すると、四分木のような他のアルゴリズム/データ構造のためにウェブを検索することができ、実装するのが最も簡単です、あなたは何千ものアイテムを持っている場合は、この小さなを最適化する必要があるかもしれませんが、かなりうまく動作します。しかし、多くのオブジェクトを持っているなら、おそらくマップはおそらくユーザーにとっては使えないでしょう!

基本的に、クリックはすべてオフになるのではなく、データ配列を調整します。画像はユーザー専用です。

私はあなたのイメージを使用してテクニックのデモを打ちました。ピンをカット+ペーストして怠惰にハッキングしました。元の画像があれば、はるかに良い仕事をすることができます。

ライブリンク(一時的でもよい)後世のためのコードの http://arsdnet.net/demo.html

コピー/貼り付け:

<!DOCTYPE html> 
<html> 
<head> 
<title>Demo of map idea</title> 
<script> 
     window.onload = function() { 
       var map = document.querySelector(".ny-map"); 
       // on each click on the map, we need to loop through 
       // the bounding boxes of the pins and see which one we hit. 
       map.addEventListener("click", function(event) { 
         var pins = map.querySelectorAll(".pin"); 
         var i; 
         // we are searching BACKWARD so it checks 
         // for clicks on the topmost pin first, then 
         // proceeds down to the bottom ones. 
         for(i = pins.length - 1; i >= 0; i--) { 
           var rect = pins[i].getBoundingClientRect(); 
           if (event.clientX >= rect.left 
           && event.clientX < rect.right 
           && event.clientY >= rect.top 
           && event.clientY < rect.bottom) 
           { 
             // if we're inside the bounding box, 
             // next we need to check the transparency 
             // bitmap to see if it is an actual hit 

             var x = event.clientX - rect.left; 
             var y = event.clientY - rect.top; 

             // pinBitmap is defined below 
             // "." happens to be the char my Gimp export 
             // gave to the clickable region, so we check for it 
             if(pinBitmap[y].charAt(x) == ".") { 
               // we hit this one! 
               // toggle class "showing" 
               if(pins[i].className.indexOf(" showing") == -1) 
                 pins[i].className += " showing"; 
               else 
                 pins[i].className = pins[i].className.replace(" showing", ""); 
               break; // all done 
             } 
             // if we didn't hit on the bitmap, continue 
             // searching the one below by proceeding with the loop 
           } 
         } 
       }); 
     }; 
</script> 
</head> 
<body> 
<div class="ny-map"> 
     <div class="shipyard pin" style="left: 140px; top: 450px;"> 
       <p>This is information about shipyard #1.</p> 
     </div> 
     <div class="shipyard pin" style="left: 150px; top: 450px;"> 
       <p>This is information about shipyard #2, which overlaps shipyard #1.</p> 
     </div> 
     <div class="shipyard pin" style="left: 460px; top: 350px;"> 
       <p>This is information about a shipyard pin in the Syracuse area.</p> 
     </div> 
</div> 

<script> 
var pinBitmap = [ 
"+++++++++++.++.............++++++++++++++", 
"+++++++++++..................++++++++++++", 
"++++++++++.....................++++++++++", 
"+++++++..........................++++++++", 
"+++++................................++++", 
"++.......................................", 
"....+...............................+++++", 
".+++.................................++++", 
"+++...................................+++", 
"+++...................................+++", 
"++.....................................++", 
"++.....................................++", 
"+.......................................+", 
"+.......................................+", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
".........................................", 
"+.......................................+", 
"+.......................................+", 
"+.......................................+", 
"++.....................................++", 
"++.....................................++", 
"+++...................................+++", 
"+++...................................+++", 
"+++...................................+++", 
"++++.................................++++", 
"++++.................................++++", 
"+++++...............................+++++", 
"+++++...............................+++++", 
"++++++.............................++++++", 
"++++++.............................++++++", 
"+++++++...........................+++++++", 
"+++++++...........................+++++++", 
"++++++++.........................++++++++", 
"+++++++++.......................+++++++++", 
"+++++++++.......................+++++++++", 
"++++++++++.....................++++++++++", 
"++++++++++.....................++++++++++", 
"+++++++++++....................++++++++++", 
"+++++++++++....................++++++++++", 
"++++++++++++...................++++++++++", 
"+++++++++++++...............+..++++++++++", 
"+++++++++++++...............+..++++++++++", 
"++++++++++++++.............++..++++++++++", 
"+++++++++++++++...........+++..++++++++++", 
"+++++++++++++++...........+++..++++++++++", 
"++++++++++++++++.........++++..++++++++++", 
"++++++++++++++++.........++++..++++++++++", 
"+++++++++++++++++.......+++++..++++++++++", 
"++++++++++.................++..++++++++++", 
"++++++.........................++++++++++", 
"++++..............................+++++++", 
"+++................................++++++", 
"+++................................++++++", 
"++++..............................+++++++", 
"++++++..........................+++++++++", 
"++++++++++..................+..++++++++++"]; 
</script> 

<style> 

.ny-map { 
     width: 985px; 
     height: 815px; 
     background-image: url('demo/qDOGS-fs8.png'); 
     position: relative; 
} 

.pin { 
     width: 41px; 
     height: 66px; 
     margin-left: -20px; 
     margin-top: -66px; 
     position: absolute; 
} 

.shipyard.pin { 
     background-image: url('demo/pin.png'); 
     background-repeat: no-repeat; 
} 

.pin:not(.showing) > * { 
     display: none; 
} 

.pin.showing { 
     background-color: rgba(255, 255, 255, 0.8); 
     padding-left: 48px; 
     padding-right: 4px; 
     width: auto; 
} 

</style> 

</body> 
</html> 

ここで私はそれをやった方法です。まず、pinBitmap部分が奇妙な形状を処理する部分:

ピン画像を取り出し、GIMPで開きます。色選択ツールを使用して、すべての透明部分をクリックして選択します。バケツの塗りつぶしを使用し、「全体選択を塗りつぶす」を選択してすべて黒にします。 「選択」 - >「反転」を押して画像の残りの部分を選択し、バケットを白く塗りつぶします。

ファイルをXPMとしてエクスポートします。これをテキストエディタで開き、7行目(画像データを持つ最初の長いもの、それがあなたのものであればどんなものでも)を最後までコピーして、それをJavascriptに貼り付けます。

pinBitmapを変数にするために配列の角括弧を置き、Gimpで生成された文字列のため、関数内に文字列を使用しました。

ファイルの下部にあるCSSは、マップとピン画像を作成します。 showingクラスが詳細情報の表示を管理します。あなたはもちろん、物の表示を切り替えるために.ny-map .powerplant { display: none; }などのようなことをすることもできます。クリックするアイテムを検索するときは、それらがcomputedStyleのいずれかで表示されているか、いくつかのフラグ変数とともに表示されているかどうかを確認し、そうでない場合は続行してください。

あなたはそれらを配置するだけで、インラインスタイルで、ピン自体はHTMLで半セマンティックていることがわかります。 CSSでは、私は座標を欲しかったところでピンポイントをもっと見せるためにいくつかのマイナスマージントリックを行いましたが、これを調整することは可能です - JSはこのCSSの調整をすべて行い、それを信じていますか?ちょうどgimpか何かからイメージに相対的な座標を取得してください。

ピンの詳細をHTMLに書いてありますので、内容もうまくグループ化されています。

そして最後に、ファイルの先頭にマジック機能、。これは、ピンをループする通常のイベントリスナーです。 getBoundingClientRect関数は標準DOMの一部であり、アイテムが内部にある矩形を生成します。シンプルな4つの部分からなるチェックは、私たちがその箱にいるかどうかを調べます。

もしそうなら、私たちは単純な減算によって得られた矩形に相対的な座標を求め、それが実際にクリック可能ならチェックします。それだけです!そうでない場合、我々はそれを欠場と見なし、ループを継続する。もしそうなら、私はshowingクラスをトグルして残りの作業を行います。

このコードは、プラグインやライブラリスクリプトを必要とせずにIE9 +ブラウザで確実に動作するはずです。

私のアプローチ/コードに関するご質問がありましたら教えてください。

EDIT:笑私はそれを「造船所」と呼びましたが、発電所の画像は切り取っていました。ああ、あなたは私が何を意味しているか知っています。

関連する問題