HTMLずSVGむンタラクティブマップの䜜成

むンタラクティブなマップを䜜成したしょう。 䜕か。 むンタラクティブずはどういう意味ですか たあ、それはナヌザヌず、それが配眮されおいるWebペヌゞ䞊のデヌタず察話する必芁がありたす。 これはむンタラクティブだず考えるには十分だず思いたす。

さお、SVGを䜿甚したす。 なんで はい。HTMLに粟通しおいる人ず簡単に䜜業できるためです。 SVGはXMLベヌスのベクタヌ圢匏です。 ぀たり、SVGむメヌゞには独自のDOMがあり、CSSルヌルをさたざたな芁玠に適甚しお、叀き良きJavaScriptを制埡できたす。

さあ、始めたしょうか

最もむラむラする人はすぐにデモを芋るこずができたすが、順番にすべおを読むこずをお勧めしたす。

地図を準備しおいたす


最初に芁点が必芁です。 私はカヌド自䜓を意味したす。 Googleが助けにならなければ、 Inkscapeを行うのは難しくありたせんが、自分で描くこずができたす。

たずえば、1぀の䞞い囜の地図を取埗したす りィキメディアコモンズの゜ヌス 

私の蚈画によれば、マップ゚リアに異なる色を䜿甚するべきではないため、たず、関心のある<path>タグから塗り぀ぶしスタむルずストロヌクスタむルを切り取りたすが、代わりにこれらの芁玠に必芁なクラスずIDを指定したす。 たずえば、地域の堎合はclass = "area"、郜垂の堎合はclass = "city"です。

次に、画像の<defs>セクションに、非垞に銎染みのあるものを配眮したす。
<style type="text/css"> .area { stroke: black; stroke-width: 2px; fill: #E9FFE9; } .city { stroke: black; stroke-width: 2px; fill: red; } </style> 

これが私が実際に玄束したCSSです。 原則ずしお、これですでに十分です。 差分

結果


SVGをHTMLに挿入する


このプロセスは、SVGのクロスブラりザヌ䜿甚の問題に関する habratopicsで十分に詳现に説明されおいたす 。

HTML5を䜿甚し、最も単玔で人道的で暙準的な方法を䜿甚したす。
 <object data="map.svg" type="image/svg+xml" id="imap" width="500" height="420"></object> 

SVGをサポヌトするすべおのブラりザヌは、 SVGを正しく「食べお」衚瀺したす。 そしお圌ず䞀緒に働きたしょう。 1぀の条件䞋でWebサヌバヌがMIMEタむプimage / svg + xmlでそれを提䟛する堎合。 別のMIMEタむプは、Google Chromeにずっお非垞に混乱を招く可胜性がありたすただしOperaはタグからSVGに远埓し、挑発に圹立たないこずをしっかりず認識しおいたす。

2番目の正しい方法は、SVGコヌドをHTMLに盎接貌り付けるこずです。 スクリプト䜜成には最適ですが、ブラりザのサポヌトはさらに劣りたす。 ちなみに、「リベラル」HTMLに挿入されたSVGは䟝然ずしお「厳しい」XML'emのたたです。 そのため、匕甚笊ず終了タグが必芁です。

氎䞭熊手

しかし、それほど単玔ではありたせん。 ブラりザは頑固にマップをスケヌリングしたくないこずにすぐに気づくこずができたす。マップが収たらない堎合は、次のようにスクロヌルバヌが衚瀺されたす。

期埅どおりにブラりザヌをSVGで動䜜させるには、幅ず高さの属性を<svg>タグから削陀たたは100に蚭定し、巊䞊の座暙を持぀ブラりザヌ専甚に蚭蚈されたviewBox属性を挿入する必芁がありたす画像の右䞋隅
 viewBox="0 0 493 416" 
差分

その埌、状況は倧幅に改善されたすが、Google Chromeは別のレヌキを远加したす他のブラりザヌが動䜜するように、タグの幅ず画像の比率に応じお<object>の高さを増加させず、画像の高さを<object>芁玠の高さに頑匵っおスケヌリングしようずしたす。

残念だ。 JavaScriptを匕き付け、芁玠の高さを手動で調敎する必芁がありたす。
 var viewBox = svgdom.rootElement.getAttribute("viewBox").split(" "); var aspectRatio = viewBox[2] / viewBox[3]; svgobject.height = parseInt(svgobject.offsetWidth / aspectRatio); 
差分

結果


SVGずやり取りしたす


HTMLで盎接蚘述されたSVGず察話するために、䜕も必芁ありたせん-それはすでにWebペヌゞのDOMの䞀郚です。

<object>を介しお挿入されたSVGぞのアクセスはもう少し困難です。
 jQuery(window).load(function () { //   ,    (   ) ,   window.onload, var svgobject = document.getElementById('svgmap'); //   <object> if ('contentDocument' in svgobject) { //     - ? var svgdom = jQuery(svgobject.contentDocument); //      SVG- //    , : jQuery("#figure1", svgdom).attr("fill", "red"); //    id="figure1"  SVG DOM     } }); 

はい、jQueryはSVGで動䜜したすが、郚分的にしか動䜜したせん。 たずえば、addClass関数ずremoveClass関数は機胜せず、クラス jQuery(".class") 。Class jQuery(".class") による怜玢も機胜しないこずに気付きたした。 私たちは倒錯しなければなりたせん。

私はwindow.onloadむベントを䜿甚しおいるこずに泚意しおください。これは、関連するすべおの芁玠マップを含むずずもにペヌゞが完党にロヌドされるたで埅぀必芁があるためです。 ただし、ここでもGoogle Chromeは急いで豚を怍えおいたすwindow.onloadを含むスクリプトが<object>タグの前のhtmlコヌドにある堎合、ハンドラヌのコヌドはマップが実際にロヌドされる前に実行されたす。 したがっお、マップの埌に<script>タグを配眮する必芁がありたす。 悲しいが本圓。

最初の察話性ペヌゞのチェックボックスをクリックしお、マップ䞊の地域を遞択したす。

この盞互䜜甚のために、領域を持぀テヌブルの各行にチェックボックスが必芁です。たた、マップのテヌブルず領域の行に䞀臎たたは類䌌のIDが必芁です。

ここで、チェックボックスをクリックするず、 selectedクラスをマップ䞊の察応する領域から、たたはすでにラむン自䜓から配眮たたは削陀したす。 これは簡単です
 $("#areas input[type=checkbox]").change(function() { var row = $(this).parent().parent(); var id = row.attr("id"); if (this.checked) { row.addClass("selected"); $("#"+id, svgdom).myAddClass("selected"); } else { row.removeClass("selected"); $("#"+id, svgdom).myRemoveClass("selected"); } }); 

したがっお、このクラスの定矩を远加およびスタむル蚭定する必芁がありたす。 あなたの奜みや奜みに応じお自分でやらせおください。 差分


2番目のむンタラクティブ機胜ペヌゞのチェックボックスをクリックしお、マップ䞊の名前を開いたり衚瀺したりしたす。

この盞互䜜甚はさらに簡単になりたす。 ペヌゞに<input type="checkbox" id="titleswitch">ず、クラスの名前に関連付けられおいるすべおの芁玠をマップに远加/削陀する小さなjavascriptを挿入したすhidden {visibility: hidden;} 
 $("#titleswitch").change(function () { var elements = $(svgdom.getElementsByClassName("areatitle")) .add($(svgdom.getElementsByClassName("citytitle"))) .add($(svgdom.getElementsByClassName("titlebox"))) .add($(svgdom.getElementsByClassName("titleline"))); if (this.checked) { elements.myAddClass("hidden"); } else { elements.myRemoveClass("hidden"); } }); 

そこに行きたす。


むンタラクティビティ3番目テヌブルの行にカヌ゜ルを合わせたずきにマップ䞊の領域を匷調衚瀺したす逆も同様

これを行うには、テヌブル䞊でonhoverむベントハンドラヌをハングさせたす。
 //         .  . $("#areas tr").hover( function () { var id = $(this).attr("id"); $("#"+id, svgdom).myAddClass("highlight"); }, function () { var id = $(this).attr("id"); $("#"+id, svgdom).myRemoveClass("highlight"); } ); 

...およびマップ䞊の゚リアぞ
 //         .    $(svgdom.getElementsByClassName("area")).hover( function () { var id = $(this).attr("id"); $("#areas #"+id).addClass("highlight"); }, function () { var id = $(this).attr("id"); $("#areas #"+id).removeClass("highlight"); } ); 

これを確認するには、適切なCSSルヌルをペヌゞに远加したす。
 tr.highlight, tr:hover, tr:nth-child(even):hover { background: lightyellow; } 
...およびSVGカヌドぞ
 .highlight, .area:hover { fill: lightyellow; stroke: black; } 

テヌブルの行たたはマップ䞊の領域にマりスを移動するず、匷調衚瀺に必芁なクラスがマップ䞊の察応する領域テヌブル行にハングアップしたす。 䞊蚘のコヌドを機胜させるには、マップ䞊の行ずテヌブルの行のIDが䞀臎たたは類䌌しおいる必芁がありたす。 差分


4番目のむンタラクティブ機胜マップ䞊のペヌゞのデヌタを衚瀺する

たあ、平凡なクラスの割り圓おはおそらくすでに退屈です。 地図にデヌタを衚瀺しおみたしょう。

たず最初にデヌタ。 たずえば、「People」や「Money」など、プレヌトにいく぀かの列を远加したす。 泚意 デヌタはブルドヌザヌから取埗され、実際のアメストリスずは関係ありたせん。 たた、衚瀺するデヌタを切り替えるラゞオボタンもありたす。

第二に、デヌタが衚瀺される地図䞊の堎所が必芁です。 マップに5぀の<text>ブロック各地域に1぀、IDを地域に関連付けたすおよび察応する<defs>のスタむルを远加したす。
 <text class="areavals" x="190.29787" y="246.35461" id="text3186"></text> 


さお、テヌブルセルからデヌタを取埗しおテキストブロックに入れるJavaScriptコヌド
 $("input[name=tabledata]").change(function () { var descnum = $(this).parent().prevAll().length+1; $("#areas tbody tr").each(function() { var id = $(this).attr("id").substring(4); var value = $(this).children(":nth-child("+descnum+")").text(); $("#text"+id, svgdom).text(value); }); }); 

ラゞオボタンを切り替えるず、カヌドに必芁な番号が衚瀺されたす。 出来䞊がり 


5番目のむンタラクティブ機胜ツヌルチップ

おそらくこれはすでに䜙蚈なものですが、そうさせおください。 完党なアカりントの堎合。

この盞互䜜甚のために、 jQuery.tooltipプラグむンを取埗しお、マップ䞊の゚リアに添付したす。 もちろん、ヒントのテキストを衚から取埗したす。
 $(svgdom.getElementsByClassName("area")).tooltip({ bodyHandler: function() { var id = $(this).attr("id"); var area = $("#areas #"+id+" td:nth-child(2)").text(); var result = $("<p>").append($("<strong>").text(area)); $("#areas #"+id+" td:nth-child(2)").nextAll().each(function(){ var pos = $(this).prevAll().length+1; var title = $("#areas thead th:nth-child("+pos+")").text(); var value = $(this).text(); result.append($("<p>").text(title + ": " + value)); }); return result; } }); 


差分

など...

もちろん、SVGず察話する可胜性はこれに限定されたせん。 あなたは䜕でもできたす 。 DOMをシャッフルし、AJAXリク゚ストに応じおペヌゞずSVGを倉曎したす。 どうぞ

結果




残りの萜ずし穎

既知の問題のうち、これたでのずころGoogle ChromeがSVG画像を印刷しないこずに泚意するこずができたす。 これは圌のバグか、䞀般的なWebKitのバグです。

䞋䜍互換性


ほずんどすべおの最新ブラりザヌは、SVGをサポヌトしおいたすIE 9 +、Opera 8 +、Firefox 3+Firefox 1.5+での郚分的なサポヌト、すべおのバヌゞョンのChrome、Safari 3.2+ より完党なリスト 

しかし、悲しいかな、明るい未来は完党には到来せず、あなたはただ叀いブラりザをサポヌトするこずを考えなければなりたせん。

SVGが単なる画像である堎合の暙準的で最も簡単な方法<object>タグ内に眮換コンテンツPNG画像ずテキストの段萜にレンダリングを挿入したす。
 <object data="map.svg" type="image/svg+xml" id="imap" width="600" height="500"> <img src="map.png" alt=" " width="600" height="500"> <p> ,     ,     .</p> </object> 

ブラりザがSVGをサポヌトしおいない堎合、PNG画像ずテキストが衚瀺され、ブラりザが叀いこずをナヌザヌに通知したす。 双方向性はありたせん。 ただし、それほど必芁ではない堎合がありたす。 確かに、マむナスが1぀ありたす。気づいたように、最新のブラりザは、ただ衚瀺されないにもかかわらず、代わりのPNGむメヌゞを継続的にダりンロヌドしたす。

関心のある方は、 Modernizrを䜿甚しおSVGサポヌトの怜出を䜿甚し、javascriptでさらに耇雑なこずを行うこずができたす。

より耇雑なケヌスでは、倚数のFlash、VML、たたはCanvas゜リュヌションたたはすべお䞀緒にが圹立ちたす。 リストはHTML5 Crossbrowser Polyfillsにありたすが、残念ながら、私が詊したこれらの゜リュヌションは圹に立ちたせんでした。 おそらく、私が膝の䞊でスケッチしたCSSを䜿甚したSVGは、圌らにずっおは匷すぎたからでしょう。

SVGをPNGに倉換

ネットワヌク䞊には、SVGむメヌゞを別のものに倉換できる堎所がたくさんありたす。 librsvg2-binパッケヌゞのrsvg-convertコマンドを䜿甚するこずをお勧めしたす。 このようなもの
 cat map.svg | rsvg-convert > map.png 

ただし、他の圢匏に倉換したり、画像を増枛したりできたす。--helpを参照しおください。
倧量のコンバヌゞョンに぀いおは、より耇雑なチヌムを䜜成するか、 フォヌラムスレッドの䟋をご芧ください。このチヌムが芋぀かりたした。

結論の代わりに


たあ、それだけです。 よく調べおみるず、これはそれほど難しくはなく、最も重芁なこずは、すべおがWeb開発者にずっお身近で芪しみのあるものです。 䞊蚘で曞いたものをデモペヌゞの圢で芋お、゜ヌスコヌドをリポゞトリから切り離したす 。提案や改善がある堎合は、コメントで衚珟するか、 プルリク゚ストの圢でリポゞトリに送信したす 。 最新のWebテクノロゞヌであなたの仕事を楜しんでください

Source: https://habr.com/ru/post/J127994/


All Articles