2 日前、echarts でインスピレーションを探していたとき、地図や地図の位置などの同様の例をたくさん見ましたが、地下鉄の地図はないようだったので、このインタラクティブな地下鉄地図のデモをいじってみました。地下鉄のポイントはインターネットからランダムにダウンロードされたものであり、私が得た成果の一部とコードの実装を記録しています。これが友人の役に立つことを願っています。もちろん、ご意見がございましたら、直接言っていただければ幸いです。
レンダリング
http://www.hightopo.com/demo/subway/index.html
マップの内容が少し多すぎると、フォントが少し小さく表示されますが、必要に応じて拡大または縮小することができます。やっぱり全部ベクターで描いてますね~。
インターフェースの生成基になる div は ht.graph.GraphView コンポーネントを通じて生成されます。その後、HT for Web が提供する優れたメソッドを使用して、キャンバス ブラシを呼び出すだけで簡単に描画できます。まず、基になる div を生成する方法を見てみましょう。
var dm = new ht.DataModel();//データ コンテナ var gv = new ht.graph.GraphView(dm);//トポロジ コンポーネント gv.addToDOM();//ボディにトポロジ グラフ コンポーネントを追加します
addToDOM 関数は次のように宣言されます。
addToDOM = function(){ var self = this, view = self.getView(), style = view.style; document.body.appendChild(view); // コンポーネントの基になる div を body に追加します style.left = '0 ';//デフォルトのコンポーネントは絶対位置に設定されるため、位置を設定します style.right = '0'; style.bottom = '0'; window.addEventListener('resize', function) () { self.iv(); }, false); //ウィンドウ変更イベント}
これで、この div に落書きできるようになりました~ まず、ダウンロードした地下鉄路線図のポイントを取得し、subway.js に配置します。この js ファイルは、ダウンロードしたコンテンツのすべてです。私は何もしていません。その他の変更は、主にこれらを追加することです。次のような行に従って配列を指します。
mark_Point13 = [];//路線配列には路線の開始座標と終了座標、路線名が含まれます t_Point13 = [];//駅配列には路線内の乗換駅の座標と駅名が含まれます n_Point13 = [ ];//小さな駅の配列には、路線上の小さな駅の座標と小さな駅の名前が含まれています mark_Point13.push({ name: 'Line 13', value: [113.4973,23.1095]}); mark_Point13.push({ 名前: '行 13', 値: [113.4155,23.1080]}); t_Point13.push({ 名前: 'Yu Zhu', 値: [113.41548,23.10547 ]} ); n_Point13.push({ 名前: 'Yufengwei'、値: [113.41548,23.10004]});
次に、地下鉄の路線を描画するために、js ですべての地下鉄路線の番号を保持する配列 lineNum と、すべての地下鉄路線の色を保持する color 配列を宣言しました。これらの色のインデックスは地下鉄と同じです。 lineNum の行。番号付きインデックスは 1 対 1 に対応します。
var lineNum = ['1', '2', '3', '30', '4', '5', '6', '7', '8', '9', '13', '14 ', '32', '18', '21', '22', '60', '68'];var color = ['#f1cd44', '#0060a1', '#ed9b4f'、'#ed9b4f'、'#007e3a'、'#cb0447'、'#7a1a57'、'#18472c'、'#008193'、'#83c39e'、'#8a8c29'、'#82352b'、 '#82352b'、'#09a1e0'、 '#8a8c29'、'#82352b'、'#b6d300'、'#09a1e0'];
次に、lineNum をトラバースし、lineNum の要素と色を createLine 関数に渡し、これらの 2 つのパラメーターに従って地下鉄の路線とカラー マッチングを描画します。結局のところ、js ファイル内の命名方法も通常の Add の後に付けられます。対応する数値なので、js で対応する配列を取得するには、文字列とこの数値を組み合わせるだけです。
let lineName = 'Line' + num; let line = window[lineName]; 私のコードは多くのスタイルを設定しているので、少し複雑に見えます。 ht.Polyline パイプラインを作成するには、polyline.addPoint() 関数を使用してこの変数に特定のポイントを追加し、setSegments を使用してポイントの接続方法を設定します。 function createLine(num, color) {//マップ ラインを描画します var Polyline = new ht.Polyline();//ポリゴン パイプライン Polyline.setTag(num);//ノード タグ ラベルを唯一のラベルとして設定します if(num = == '68') Polyline.setToolTip('AP M');//プロンプト情報を設定します if(num === '60') Polyline.setToolTip('G F'); Polyline.setToolTip('Line' + num); if(color) { Polyline.s({//s は setStyle の略で、スタイルを設定します 'shape.border.width': 0.4,// 境界線の幅を設定しますポリゴン 'shape .border.color': color,//ポリゴンの境界線の色を設定します 'select.width': 0.2,//選択したノードの境界線の幅を設定します'select.color': color//選択したノードの境界線の色を設定します}) } let lineName = 'Line' + num; for(let i = 0; i < line.length; i++) { for(let j = 0; j < line[i].coords.length; j++) { Polyline.addPoint({x: line[i].coords[j][0]*300, y: -line[i].coords[j][1]*300}); if(num === '68'){//APM ライン(2 つありますが、点は同じ配列内にあります) if(i === 0 && j === 0) { Polyline.setSegments([1]) } else if(i === 1 &&); j === 0) { Polyline.getSegments().push(1); } else { Polyline.getSegments().push(2); } } } Polyline.setLayer('0');// ラインを設定します下層では上層の上に点を設定しますdm.add(polyline);//ストレージ用のデータ コンテナにパイプラインを追加します。そうでない場合、パイプラインは空き状態になり、トポロジ マップに表示されません。ポリラインが返されます。}
上記のコードでは、地下鉄の線にポイントを追加するいくつかの状況があります。これは、Line68 で線を設定するときにジャンプ ポイントがあるため、Line68 の特定の宣言にはスペースが限られているためです。配列については、subway.js を参照してください。
ここで注意すべき点は、addPoint 関数を使用してセグメントを設定しない場合、デフォルトでは追加された点が直線で結ばれることです。セグメントの定義は次のとおりです。
1: moveTo、1 つのポイント情報を占め、新しいパスの開始点を表します
2: lineTo は 1 つのポイント情報を占め、最後のポイントからこのポイントまでの接続を表します
3:quadraticCurveTo、2 つの点情報を占め、最初の点は曲線制御点として使用され、2 番目の点は曲線の終点として使用されます。
4: bezierCurveTo は 3 つの点情報を占め、最初と 2 番目の点は曲線制御点として使用され、3 番目の点は曲線の終点として使用されます。
5: closePath、ポイント情報を占有せず、このパス描画の終点を表し、パスの開始点に近づきます。
したがって、ジャンプ動作を実行したい場合は、セグメントを 1 に設定するだけです。
最後に、この部分もsubway.jsで分割されています。これらの配列は、前のjs表示部分で説明しました。中指を動かすとスクロールできます。見てみるまで。
これらのポイントに ht.Node ノードを追加します。dm データ コンテナにノードが追加されると、トポロジ マップ コンポーネント gv によって設定されたデータ コンテナがこの dm であることが前提になります。 。スペースが限られているため、地下鉄路線にポイントを追加するコード部分のみを示します。
var tName = 't_Point' + num;var tP = window[tName];//大きな駅 if(tP) {//一部の路線には乗換駅がありません for(let i = 0; i < tP.length; i++) { let node = createNode(tP[i].name, tP[i].value, color[index]);//ノードを追加しますnode.s({//ノードのスタイルを設定します 'label.scale': 0.05,//ブラウザの制限を回避するためにテキストのスケーリングを行います 最小フォント サイズの問題'label.font': 'ボールド 12px arial, sans-serif'//テキストのフォントを設定します }); node.setSize(0.6, 0.6);//ノードのサイズを設定します。 js の各ポイント間のオフセットが小さすぎるため、ノードを小さく設定する必要がありました。node.setImage('images/rotating arrow.json');//ノードの画像を設定しますnode.a('alarmColor1 ', ' rgb(150, 150, 150)'); //attr 属性、ここで任意に設定できます。alarmColor1 は、上記の画像セットの json にバインドされた属性です。詳しくは、HT for Web Vector マニュアル (http://www.hightopo) を参照してください。 .com/guide/guide/core/vector/ht-vector-guide.html#ref_binding)node.a('alarmColor2', 'rgb(150, 150, 150)');//上記と同じnode.a('tpNode', true);//このプロパティ設定は転送サイトと小規模サイトを区別するためにのみ使用され、後で使用されます}}
すべての地下鉄路線と駅が追加されました。しかし!描画したグラフが小さすぎるため、表示されない場合があります。このとき、graphView トポロジ コンポーネントの FitContent 関数を設定して、トポロジ グラフ上のすべてを移動不能に設定することもできます。
gv.fitContent(false, 0.00001);//適応サイズ、パラメータ 1 はアニメーション化するかどうか、パラメータ 2 は gv と境界線のパディング値 gv.setMovableFunc(function(){ return false;// gv 上のノードを次のように設定します不動であること });
これで、地下鉄の路線図が表示されるようになりました~ インタラクションを見てみましょう。
交流1 つ目は、マウス移動イベントです。マウスを特定の線の上に移動すると、その線が太くなり、マウスが転送サイトに移動すると、その線の番号も表示されます。小さいサイトでは、そのサイトに対応するアイコンが大きくなり、色が変わるとフォントも大きくなり、マウスを動かすとアイコンは元の色に戻り、フォントが小さくなります。違いは、マウスが転送ステーションに移動すると、転送ステーションが回転することです。
マウス スライド イベントの場合、gv の基になる div に基づいて Mousemove イベントを直接実行し、ht でカプセル化された getDataAt 関数を通じてイベント パラメーターを渡し、イベントの下に対応するノードを取得します。その後、ノードを自由に操作できます。 :
gv.getView().addEventListener('mousemove', function(e) { var data = gv.getDataAt(e);//論理座標点またはインタラクティブ イベント イベント パラメータを渡し、現在の点のプリミティブを返します。 if( name ) {originNode(name);//ノードを常に元のサイズに保つ} if (data instanceof ht.Polyline) {//イベント ノードのタイプを決定します dm.sm().ss(data);//パイプ名を選択 = ''; clearInterval(interval); } else if (data instanceof ht.Node) { if(data. getTag( ) !== name && data.a('tpNode')) {//同じノードではなく、mousemove イベント オブジェクトが ht.Node タイプの場合、ノードの回転間隔 = を設定します。 setInterval(function() { data.setRotation(data.getRotation() - Math.PI/16); //独自の回転に基づいて回転}, 100) } if(data.a('npNode')) {/ /マウスが小さいサイトに移動した場合、アニメーションを停止します。clearInterval(interval) } ExpandNode(data, name);////カスタマイズされたズーム ノード関数。比較的簡単です。もうコードにこだわる必要はありません。http://hightopo.com/ にアクセスして dm.sm().ss(data) を表示できます。 //選択したノード名を設定 = data.getTag();//前のノードのストレージ変数として、この値を通じてノードを取得できます} else {//それ以外の場合は、何も選択されておらず、アニメーションがオンになります転送サイトはクリアされます dm.sm( ).ss(null); ''; クリアインターバル(間隔);
マウスを地下鉄の路線上に置くと、ツールチップを設定して特定の路線の情報が表示されます (注: gv のツールチップ スイッチをオンにする必要があります)。
gv.enableToolTip();//ツールチップのスイッチをオンにする if(num === '68') Polyline.setToolTip('AP M');//プロンプト情報を設定する else if(num === '60')ポリライン.setToolTip('GF'); それ以外の場合はポリライン.setToolTip('ライン' + num);
次に、右下隅のフォームを使用してフォーム上の特定の行をクリックするか、トポロジ マップ上の任意のサイトまたは行をダブルクリックすると、トポロジ マップが対応する部分に適応し、ダブルクリックされた部分が表示されます。トポロジ マップの中央に表示されます。
フォームの宣言部分をまだ説明していないようです。 。 。つまり、新しい ht.widget.FomePane クラスを通じてフォーム フォーム コンポーネントを作成し、form.getView() を通じてフォーム コンポーネントの基になる div を取得し、この div を本文の右下隅に配置して、行を追加します。 addRow 関数を使用したフォーム フォーム項目。addRow を使用して、この行に任意の数の項目を追加できます。関数の 2 番目のパラメーター (配列) は追加されたフォーム項目の幅を設定し、3 番目のパラメーターは行の高さを設定します。
function createForm() {//右下隅にフォームを作成します var form = new ht.widget.FormPane(); form.setWidth(200);//フォームの幅を設定します form.setHeight(416);//フォームの高さを設定します let view = form.getView(); document.body.appendChild(view);// フォームを本文に追加します view.style.zIndex = 1000; view.style.bottom = '10px'; // ほとんどすべての ht コンポーネントは絶対パスを設定します view.style.right = '10px'; view.style.background = 'rgba(211, 211, 211, 0.8)'; forEach(function(nameString) { form.addRow([//フォームに行を追加します{//この行の最初のフォーム項目ボタン: {//フォームにボタン アイコンを追加します: 'images/Line'+nameString.value+'.json',//ボタン アイコンの背景を設定します: '',//ボタンの背景を設定します borderColor: '',//クリック可能なボタンの境界線の色: false//ボタンをクリック不可に設定します} }, {//2 番目のフォーム項目ボタン: { label: nameString.name, labelFont: 'bold 14px arial, sans-serif'、labelColor: '#fff'、background: ''、borderColor: ''、onClicked: function() {//ボタン クリック コールバック イベント gv.sm().ss(dm.getDataByTag(nameString.value) );//選択された押されたボタンに対応する行を設定します gv.fitData(gv.sm().ld(), true, 5);//選択した地下鉄路線をトポロジ マップの中心に表示します} } } ], [0.1, 0.2], 23);//2 番目のパラメータは、最初のパラメータの配列の幅を設定します。 1 より大きいのは比率、3 番目のパラメータは行の高さです。});}
サイトをクリックすると赤いマークが表示され、ノードをダブルクリックするとトポロジ マップの中心に配置され、空白スペースをダブルクリックすると赤いマークが非表示になります。コンテンツは、トポロジ コンポーネントのイベント監視によって制御されます。 gv. コードは次のとおりです。
var node = createRedLight();//赤色灯スタイルとして表示される新しいノードを作成します gv.mi(function(e) {//ht のトポロジ コンポーネントでのイベント監視 if(e.kind === 'clickData ' && (e.data.a('tpNode') || e.data.a('npNode'))) {//e.kind は現在のイベント タイプを取得し、e.data は現在のイベントの下のノードを取得します。node.s('2d.visible', true);//ノードを可視に設定します。node.setPosition(e. data.getPosition() .x, e.data.getPosition().y);//ノードの座標を現在のイベントの下のノードの位置に設定します} else if(e.kind === 'doubleClickData') {//ノードをダブルクリックします。 gv.fitData(e.data, false, 10);// イベントの下のノードをトポロジ マップの中心に適応させます。パラメータ 1 は適応ノード、パラメータ 2 はアニメーション化するかどうかです。 、パラメータ 3 は gv と border のパディングです } else if(e.kind === 'doubleClickBackground') {//空白スペースをダブルクリックします。node.s('2d.visible', false);//ノード ノードを非表示にする View HT for Webスタイル マニュアル (http://www.hightopo.com/guide/guide/core/theme/ht-theme-guide.html#ref_style) }});
s (style) と a (attr) は次のように定義されていることに注意してください。 s は ht によって事前に定義された一部の属性であり、 a は通常、文字列を呼び出すことによって呼び出されます。定数または関数にすることができ、非常に柔軟です。
最後に、小さなパーツが作成されます。サイトを選択すると、現在選択されているサイトを示す赤い呼吸アイコンがサイト上に表示されます。
呼吸部分は ht の setAnimation 関数を使用して完成します。この関数を使用する前に、まずデータ コンテナーのアニメーション スイッチをオンにしてから、アニメーションを設定する必要があります。
dm.enableAnimation();//データコンテナのアニメーション切り替え機能をオンにする createRedLight() { var node = new ht.Node(); node.setImage('images/RedLight.json');//画像を設定ノードのノード .setSize(1, 1);//ノードのサイズを設定しますnode.setLayer('firstTop');//gv の最上層に表示されるノードを設定しますnode.s('2d.visible', false);//ノードは非表示ですnode.s( 'select.width', 0);//ノードが選択されたときの境界線は 0 で非表示になりますnode.s('2d.selectable', false);//この属性を設定すると、ノードは選択できませんnode.setAnimation(//アニメーションの設定の詳細については、HT for Web アニメーションのマニュアル (http://www.hightopo.com/guide/guide) を参照してください。 /plugin/animation/ht-animation-guide.html) ExpandWidth: { property: width,// このプロパティを設定すると、accessType は設定されません。デフォルトでは、setWidth/getWidth を通じてプロパティを設定および取得します。 ここでの幅は次のとおりです。以下の高さが使用されます。これらはすべて、以前に設定したサイズによって取得されます: 0.5, //アニメーションの開始時の属性値 ~: 1,//アニメーションの終了時の属性値 next: CollapseWidth //String 型、その後に実行する内容を指定します現在のアニメーションが完了しました。次のアニメーションは複数のアニメーションを結合できます。}、collapseWidth: { property: width、from: 1、to: 0.5、next: ExpandWidth }、expandHeight: { property: height、from: 0.5、to: 1、次:collapseHeight }、collapseHeight: { property: height、from:1、to:0.5、next:expandHeight }、start:[expandWidth、expandHeight]//配列、開始する1つ以上のアニメーションを指定するために使用されます}) ; dm.add(ノード); }
すべてのコードが完成しました。
要約するこのデモは完了するまでに 2 日かかり、いつも少し気が進まなかったのですが、時々理解できずに時間がかかりましたが、全体的には多くのことを得ることができました。 getPoints().push を使用してポリゴンにポイントを追加するだけだと思います。マスターに助けを求めた後、このメソッドは回り道であるだけでなく、たとえば getPoints を取得する前にさまざまな問題を引き起こすことがわかりました。 、ポリゴン内にすでにポイントが存在している必要があります。可能ですが、多くの場合、初期化されたポイントを設定するのは簡単ではなく、コードは非常に煩雑になります。ポイントは addPoint メソッドを通じてポリゴン変数に直接追加され、デフォルトではポイントは直線で結ばれます。セグメントを設定する必要がない、なんと素晴らしい機能でしょう。
また、ht のデフォルトのズーム サイズは 20 で、デモの間隔が非常に狭いため、最大にズームすると地下鉄路線図の表示も非常に小さくなります。そのため、htconfig の ht のデフォルトのzoomMax 属性を変更しました。 htconfig で設定された値は後で変更できないため、この値はすべての ht 呼び出しの前に指定する必要があります。
上記は、編集者が紹介する HTML5 Canvas に基づくインタラクティブな地下鉄路線図です。ご質問がございましたら、メッセージを残してください。編集者がすぐに返信します。また、VeVb武道サイトを応援してくださった皆様、誠にありがとうございました!