リーフレット-CloudmadeのAPIをマップします。 復習

喪に服して -あなたの欲望を恐れて、彼らは叶うかもしれません。 冗談。

最初から始める



メインのLeaflet APIで、クイックスタートの例に迎えられます 。 彼から始めます。

// create a CloudMade tile layer var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/YOUR-API-KEY/997/256/{z}/{x}/{y}.png', cloudmadeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade', cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttribution}); // initialize the map on the "map" div var map = new L.Map('map'); // set the map view to a given center and zoom and add the CloudMade layer map.setView(new L.LatLng(51.505, -0.09), 13).addLayer(cloudmade); // create a marker in the given location and add it to the map var marker = new L.Marker(new L.LatLng(51.5, -0.09)); map.addLayer(marker); // attach a given HTML content to the marker and immediately open it marker.bindPopup("A pretty CSS3 popup.<br />Easily customizable.").openPopup(); 


例は、cloudmadeからタイルレイヤーを作成することから始まります。 API自体も「by cloudmade」のようなものです。 注意、質問は次のとおりです。親/友好的なプロジェクトにとって、タイルレイヤーを追加する便利な方法を作成できないのは何ですか? そのようなタイプ:

 var cloudmade = new L.CloudMade.TileLayer(YOUR-API-KEY); 

またはこれでさえ:
 map.addLayer('cloudmade', { apiKey: YOUR-API-KEY }); 


LeafletとCloudmadeの関係はわかりませんが、Cloudmadeは間違いなくLeaflet APIの最後のタスクではありません。 ユーザーが自分でCloudmadeに著作権を追加することを強制することは、常識に対するある種の暴力です。

チニング





Google Maps API v2 / OpenLayersとは異なり、リーフレットはjQueryのようなパラダイムを提供します(ほとんどのアクションは歓迎です)。 では、何が恥ずかしがり屋ですか?

 var marker, map = (new L.Map('map')) .setView(new L.LatLng(51.505, -0.09), 13) .addLayer('cloudmade', { apiKey: YOUR-API-KEY }) .addLayer((marker = new L.Marker(new L.LatLng(51.5, -0.09))) .bindPopup("A pretty CSS3 popup.<br />Easily customizable.") ); marker.openPopup(); 


ちなみに、上記の例から、オブジェクトアプローチとチニングを混合することの不便さははっきりと見えます-(新しいX())。Y()はJSで最も美しい構造ではありません。

ところで、addLayerでマーカーを追加するのはなぜですか? LeafletのL.Layerは、完全に理解可能な独立したエンティティ、つまりレイヤーです。 addLayerが他のエンティティ(マーカー、ジオメトリ)を追加するのはなぜですか?

そして、addLayerとaddMarkerに違いがない場合(つまり、追加のロジック全体がオブジェクト自体で保護されている場合)、このメソッドをオブジェクト自体に複製するのは論理的ではありませんか?

 var map = (new L.Map('map')) .setView(new L.LatLng(51.505, -0.09), 13) .addLayer('cloudmade', { apiKey: YOUR-API-KEY }), marker = (new L.Marker(new L.LatLng(51.5, -0.09))) .appendTo(map) .bindPopup("A pretty CSS3 popup.<br />Easily customizable.") .openPopup(); 


さて、コンストラクタをファクトリに置き換えると、非常にうまくいきます:

 var map = L.map('map') .setView(L.latLng(51.505, -0.09), 13)) .addLayer('cloudmade', { apiKey: YOUR-API-KEY }), marker = L.marker(L.latLng(51.5, -0.09)) .appendTo(map) .bindPopup("A pretty CSS3 popup.<br />Easily customizable.") .openPopup(); 


元の例と比較してください。

ちなみに、先を見て、setViewとaddLayersはコンストラクターで直接行うことができます。この機能をクイックスタートで正しく作成してみませんか?

洗っていない手をいじる



わかりました、あなたのIPAを使いたいと思います。 私はコードを見て...不思議に思う。 接続方法は? さて、理解しました-なぜあらゆる種類のhtmlタグなどでサンプルをオーバーロードしますが、APIを接続する方法を示す必要があります。 チェックして、例として行きましょう。

マップのコードを記述する前に、ページで次の準備手順を実行する必要があります。
ドキュメントのヘッドセクションにLeaflet CSSファイルを含めます。
 <link rel="stylesheet" href="leaflet/leaflet.css" /> <!--[if lte IE 8]><link rel="stylesheet" href="leaflet/leaflet.ie.css" /><![endif]--> 

Leaflet JavaScriptファイルをページ上のどこかに(できればbody closeタグの前に)含めます。
 <script src="leaflet/leaflet.js"></script> 

マップを配置する場所に特定のIDを持つdiv要素を配置し、幅と高さが定義されていることを確認します。
 <div id="map" style="height: 200px"></div> <!-- width equals available horizontal space by default --> 

これで、マップを初期化し、それを使って何かを行う準備ができました。


この時点まで(例に入る前に既にドックを読んでいた)、リーフレットは非常に心地よい印象を残しました。 しかし、この小さな例では、すべてのドキュメントをまとめるよりも多くの疑問が生じます。

まず第一に、リーフレットコードを含むリーフレットフォルダは私のページのどこから来たのですか? これは単なるライブラリコードの受け取りであり、「ページの準備」セクションで説明する必要があるようです。 もしリンクがどこにも通じないことにウェブマスターが簡単に気づくと思うなら、githubに登ってコードをダウンロードしてください-あなたは非常に深く間違えられています。 「コードをコピーしました-何も機能しません-どうすればいいですか?」という質問があなたのサポートにあふれていると確信しています。

さらに、なぜウェブマスターにCSS接続コードを自分で投稿させるのですか? この作業をjsスクリプトに任せてみませんか? (ちなみに、IEでの正常な劣化は私の敬意です。)

しかし、このコメントは「幅はデフォルトで利用可能な水平スペースに等しい」-誰のためですか? HTMLについて全く知らない人のために? まあ、このコメントはそれらを混乱させるだけです。 (a)ページ上のleaflet / leaflet.jsがどこから来るのか、githubからコードをダウンロードする方法、(b)CSS接続のこれらの魔法のコメントは何で、単純に削除できない理由を説明する必要があります。

このコードがmap divとleaflet.jsの両方のインクルードの下、またはwindow.loadまたはdocument.readyイベントハンドラー内にあることを確認してください。


あなたはディーバがデフォルトで100%デフォルトであることをウェブマスターに説明しますが、獣のwindow.loadの種類とそのハンドラにコードを追加する方法を報告する必要はないと考えていますか?

ウェブマスターがあなたからただ一つのことを望んでいることを理解してください:コードの一部をコピーして、それを機能させる。 どこでも動作します-少なくともwindow.onloadの前、さらには後でも、少なくとも頭に、少なくとも身体に入れてください。 そして、どうすればそれらを完全に理解できますか?突然サードパーティのライブラリを使用する必要がある場合、最後にしたいことは参考例を選び、それが私の環境で機能しない理由を理解することです。

さて、私は脱線します。 firebugを調べます。 皆さん、不正行為者です! 25 Kb JS APIは、ある種の魔術です。 ここに、堅実で無条件の5つがあります。 ところで、_leaflet_resize3関数は、varを忘れた場所のグローバル名前空間(v0.3)で輝いています。

もう1つ驚くべきことです。このライブラリを自分でホストして、ユーザーのドメインから強制的に接続してみませんか。 まあ、なんて負荷で、パートナーと同意することは可能です。 しかし、ユーザーはバージョンの更新(および遅かれ早かれ表示される古いバージョンの重大なバグ)に問題はありません+ライブラリの配布により、ほとんどのユーザーはすぐにキャッシュに格納されます。

デザート



さて、例を終了して、おいしい- ドキュメントに移動します 。 そしてすぐに質問-なぜいくつかのリンクは灰色でどこにも通じないのですか? ドキュメントの準備ができていませんか? 何か壊れましたか? ロードマップ? ところで、このドキュメントのどのバージョンに-安定した0.2またはdev 0.3ですか?

読み始めます。

 // initialize the map on the "map" div with a given center and zoom var map = new L.Map('map', { center: new L.LatLng(51.505, -0.09), zoom: 13 }); // create a CloudMade tile layer var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/YOUR-API-KEY/997/256/{z}/{x}/{y}.png', cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18}); // add the CloudMade layer to the map map.addLayer(cloudmade); 


中央のマップとズームマップをデザイナーで設定できることがわかりました。 そして、あなたは尋ねることができません。 そして、センターのみが設定されている場合はどうなりますか? それとも単にズーム? そして最も重要なのは、誰が初期化されていないカードを必要としているのか? どのような機能がありますか?

繰り返しになりますが、クラウドで作成されたレイヤーの作成は非常に最初の段階にあります。 ところで、現在著作権を表示することはできませんか?

マップパラメータを調べ始めます。
レイヤーILayer [] []最初にマップに追加されるレイヤー。

レイヤーはデザイナーで直接設定できることがわかりました。 それでは、あなたの例では何を聞かないのですか?
minZoom Number 0マップの最小ズームレベル。 マップレイヤーに設定されたminZoomをオーバーライドします。
maxZoom Number 18マップの最大ズームレベル。 これは、マップレイヤーに設定されたmaxZoomをオーバーライドします。

あの マップオプションが常にレイヤーオプションとオーバーラップし、デフォルト値がある場合-レイヤーオプションが必要な理由 明確ではありません...
dragging Boolean trueマップをマウス/タッチでドラッグ可能にするかどうか。
touchZoom Boolean true 2本の指でタッチドラッグすることでマップをズームできるかどうか。
scrollWheelZoom Boolean trueマウスホイールを使用してマップをズームできるかどうか。
doubleClickZoom Boolean trueマップをダブルクリックしてズームインできるかどうか。

4つのオプションのうち3つは不定詞で、1つは動名詞です。 次に、ドラッグするか、(タッチ| scrollWheel |ダブルクリック)ズームします。

さらに興味深いのは、ILayerが個別のレイヤー配列オプションを授与されるのに対し、IHandlersおよびIControlsは授与されない理由です。 それはもっと論理的ではないですか?

 handlers IHandler[] ['drag', 'touchZoom', 'scrollWheel', 'doucleClick'] Map handlers that will be enabled initially 


まあ、コントロールについても同じように。

同じ考慮事項がカードのプロパティに適用されます。 単純に書いてみませんか:
 map.hadlers('drag').enable() 


このようなソリューションは、(a)多くの不要なオプションとプロパティからクラスインターフェイスをオフロードし、(b)新しいコントロールとハンドラーをより正式で便利に追加します。

カードに定規を追加し、IHandlerの形式で正しく設計したいとします。 L.Mapを継承し、次のようなことをする必要があります。

 var MyMap = function (id, options) { L.Map.call(this, id, options); this.ruler = new MyRulerHandlerClass(map); if (options && options.ruler) { this.ruler.enable(); } } 


私がしなければならないのは、次のようなことをすることです
 L.handlers.register('ruler', MyRulerHandlerClass) 

エイリアスによってカードのIHandlerの静的ストレージを取得する場合。

イベントに移りましょう。

mouseEventユーザーがマップをクリック(またはタップ)したときに発生します。
dblclick MouseEventユーザーがマップをダブルクリック(またはダブルタップ)したときに発生します。
mousedown MouseEventユーザーがマップ上でマウスボタンを押すと発生します。

mouseup、contextmenu、mouseenter、mouseleaveはどうですか? mousedownイベントを提供し、mouseupにリッスンさせないことは、どういうわけか非常に奇妙です。

loadイベントマップが初期化されるとき(中心とズームが初めて設定されるとき)に発生します。
viewresetイベントマップがコンテンツを再描画する必要があるときに発生します(これは通常、マップのズームまたはロードで発生します)。 カスタムオーバーレイの作成に非常に便利です。


カードの初期化されていない状態を削除すると、これら2つのイベントは消えます。 ちなみに、すべてのタイルが読み込まれたことを示す読み込みイベントは、はるかに便利です。

movestartイベントマップのビューの変更が開始されると発生します(たとえば、ユーザーがマップのドラッグを開始します)。
マップビューの任意の動きで発生するイベント。
moveendイベントマップのビューの変更が終了したときに発生します(たとえば、ユーザーがマップのドラッグを停止した)。
dragstartイベントユーザーがマップのドラッグを開始すると発生します。
dragイベントユーザーがマップをドラッグしている間に繰り返し発生します。
dragendイベントユーザーがマップのドラッグを停止すると発生します。
zoomendイベントマップのズームが変更されたときに発生します。


移動イベントの2つのセット-move *とdrag *が必要な理由は何ですか? ユーザーアクションとプログラムアクションを区別するには? では、なぜズームも行われないのですか? zoomstart、zoom、scrollzoomstart、scrollzoom、scrollzoomendを試してみませんか? 明確ではありません。

layeradd LayerEvent新しいレイヤーがマップに追加されると発生します。
layerremove LayerEventレイヤーがマップから削除されると発生します。


マーカーを追加すると、これらの同じイベントがスローされることを理解していますか? どうやって見つけるのですか? レイヤーの概念はまだ導入されていません。単語はプログラムエンティティとしてフォントで強調表示されていません。リンクはありません。

locationfound LocationEventジオロケーション(locateまたはLocateAndSetViewメソッドを使用)が正常に完了したときに発生します。
locationerror ErrorEventジオロケーション(locateまたはLocateAndSetViewメソッドを使用)が失敗したときに発生します。


そして、問題のこれらの魔法の方法をどこで見ることができますか? 説明内のイベントの後、いくつかの予測が行われ、リンクはありません。 ところで、マップインターフェイスの説明で投影が行うことは、私にはまったく理解できません。

地図ペイン

カスタムオーバーレイを配置するために使用できるさまざまなマップペインを含むオブジェクトリテラル。 違いは、主にそのようなオーバーレイが取得するzIndexの順序にあります。


かっこいい。 これは何ですか これにアクセスする方法は? これはフィールドでもメソッドでもイベントでもありません。どんな動物ですか? 例はありません。

メソッドに渡します。 地図の状態を変更する方法/地図の状態を取得する方法/レイヤーとコントロールの方法/変換方法/その他の方法(「すべての動物はa)皇帝に属する、b)防腐、c)飼いならされた、d)ミルク豚、 e)サイレン、e)素晴らしい、g)野良犬、h)この分類に含まれる、および)狂ったように走る、k)数えられない、k)ラクダの毛で作られた最高のブラシで描かれた、m)その他、n)水差しを折った、o)遠くからハエに似ています...))メソッドの主な問題を示唆しているため、メソッドが多すぎます。 そして、最も重要なことは、さらにもっとあることです。 メインクラスのインターフェイスに「時々役立つ」メソッドを配置すると、何かを見つけることができないため、すぐにそれらはまったく役に立たなくなります。 何かする必要があります:)たとえば、メソッドが内部オブジェクトのプロキシである場合、メソッドをプロキシする代わりにこのオブジェクトを開くことは価値がありますか? さて、多くのメソッドは単純に冗長です-たとえば、locateメソッドオプションでsetViewフラグを回避することができるのに、なぜどうしてLocateおよびLocateAndSetViewメソッドが必要なのでしょうか? setZoomがあるときにzoomIn / zoomOutメソッドが必要なのはなぜですか?

(追加|削除)レイヤーメソッドには、レイヤーとは何のヒントもありません。 奇妙なことに、コントロールメソッドは(追加|削除)ありますが、ハンドラメソッドはありません(追加|削除)。 そして、新しいコントロールを追加するとどうなりますか-.controlNameフィールドがマップに表示されますか? どうやら-いいえ。

合計で、マップエンティティを追加、削除、アクセスするための4つの矛盾した方法が既にあります。

1)レイヤーの場合:オプションのレイヤーの配列、(追加|削除)メソッドのレイヤー。
2)IHandlerの場合:名前付きオプションのセット、名前付きプロパティのセット、新しいオプションの追加方法はまったく明確ではありません。
3)IControlの場合:名前付きオプション/プロパティのセットと、名前のないコントロールのインターフェイス(追加|削除)コントロールの両方。
4)MapPanesの場合、ペインのリストを含むリテラルを返すマップメソッド。

量が多すぎて、ドキュメントが不十分です。

マーカー



マーカーインターフェイスは、マップの暴動に比べると劣っていますが、出生時の損傷を.draggingの形で継承しています。 アイコンを無効にできないことは喜ばしいことではありませんが、さらにいくつかのデータをマーカーに関連付けるネイティブ機能がないことは喜ばしいことではありません。 マーカーはある種の地理的エンティティに対応し、ほとんどの場合、ある種の識別子、名前、説明、住所などを持ちます。クラスを継承して拡張するか、クロージャーでトリックするか、すべてを吐き出して書くだけでユーザーに強制しますmarker.id = 'myid'。 すべてのオプションはあまり美しくなく、潜在的に危険です。

clickable Boolean true falseの場合、マーカーはマウスイベントを発生せず、基になるマップの一部として機能します。


間違った解決策は、オブジェクトの対話性を「クリック可能」と呼ぶことです。

しかし、クリックをこのイベントをスキップするかどうかを決定したい場合はどうすればよいですか? ハウスノードへのアクセスはありません。

クリックでバランを開き、ドラッグでマップをドラッグする場合はどうすればよいですか? これはごく普通のケースです。たとえば、Googleマップの公共交通機関の停留所をご覧ください。

draggable Boolean falseマーカーがマウス/タッチでドラッグ可能かどうか。


私が理解しているように、マーカー.draggingフィールドは、ドラッグ可能なオプションに関係なく、どのような場合でもありますか? そして、.dragging.enable()の呼び出しを強制するとどうなりますか? カードにドラッグと呼ばれるこのオプションがあるのはなぜですか? 結局のところ、これはカードとまったく同じIHandlerをドラッグするためのものです-なぜ他のオプションがあるのですか?

mousedownイベントはどこに行きましたか?

ちなみに、私はマーカーがレイヤーであるという事実を認識していませんでした。 この奇妙なアイデンティティを示唆するのはまだ例だけです。 ドキュメントでは、「オーバーレイ」という用語も使用されますが、これもどこにも定義されておらず、エンティティ名にも含まれていません。

ポップアップ



発生する最初の質問は、エンティティL.Popupがある場合、L.PopupクラスのインスタンスをbindPopupに渡すことはできますか? ドキュメントによると、それはないことが判明しました。 そして、ポップアップをバインドせず、データとオプションのみをバインドする場合、bindPopupと呼ばれるメソッドはなぜですか?

autoPan Boolean trueマップで開かれたポップアップに合わせてパンアニメーションを行わない場合は、falseに設定します。
closeButton Boolean trueポップアップ内の閉じるボタンの存在を制御します。

その他のオプション名。 autoPan =自動的に移動する場合、closeButton =ボタンを閉じますが、「閉じるボタンの存在」ではありません。

ところで、DOMへのアクセスがない場合、htmlコンテンツを設定するポイントは何ですか? リッチなhtmlコンテンツバルーンを設定するため、インタラクティブ機能も追加したいのですが、htmlにもポップアップイベントにもアクセスできません。

ポップアップのインタラクティブな設定はありませんが、無駄ではありませんが、マーカーよりも必要です。 たとえば、スクロールは常にマップに無条件で渡されます。つまり、スクロールされたコンテンツをポップアップに配置することはできません。

レイヤー



クラウドメイドレイヤーの悲しみについてはすでに言及しました。 何らかの理由で、他のサービス(WMS)には、便宜上、別個のクラスが設定されていますが、ネイティブクラスは設定されていません。

minZoomとmaxZoomとは何であり、マップ設定がそれらをオーバーライドする方法は説明されていません。 「タイルサイズ」設定が導入された理由も不明です。 典型的なユーザーの場合-別の投影(wgs84など)にレイヤーを適用し、最後の縮尺のタイルをストレッチし、マップに+1または+2縮尺を追加します-この設定は解決しません。

「すべてのタイルが読み込まれた」イベントの有用性については既に述べました。

TileLayer.Canvasとは何なのか理解できませんでした。 ドキュメンテーションには、彼との1つの方法が正確に記載されており、この例では、なぜ彼が必要なのかわかりません。

グラフィックス



グラフィック要素は、マーカーとしてクリック可能な同じ印刷を継承します。 ところで、なぜドラッグ可能にねじ込まれていないのですか? オブジェクトがスローするイベントの数は、ドキュメントを深く掘り下げるにつれて減少します:)

オプションを設定するsetStyleメソッドは奇妙です。

ジオメトリはポイントの配列によって定義されます-どういうわけか一貫性がありません。 ポイント自体は新しいLatLngで指定する必要があり、ジオメトリは特別な配列ではなく、通常の配列を使用してポリラインにプッシュできます。 オブジェクト。 しかし、ユーザーがこのメソッドをAPIメソッドの周りに分割するとどうなりますか? グラフィックスには更新メソッドがありません。

「ポリラインクリッピングを無効にします」というコメントが付いたnoClipオプション。 特に、他のジオメトリには同じオプションがありません。

サークルについて何を知っていますか?



ライン上のラインキャップを通して描かれた円は楽しいアイデアです。 唯一の問題は、メルカトル図法の半径がnメートルの「正直な」円がまったく円ではなく、楕円ではなく、複雑な図形であることです。 さて、誰も必要としない「誠実な」サークルを作りましょう。 それでも、計算にはどの半径が選択されますか? 北、南、西、東?

ところで、円の中心の位置は変更できますが、半径は変更できません。 なんで?

L.CircleMarker
半径がピクセルで指定された固定サイズの円。 Circeを拡張します(ここではタイプミスを忘れています) 。 Map#addLayerを使用して、マップに追加します。


ポイントブランクサークルだけと違いはありません。 「CircleMarker」という名前では、これは円+マーカーだと思いますが、説明にはヒントがありません。

デフォルトの半径は10で、パスオプションオブジェクトに「半径」メンバーを渡すことで変更できます。


なぜこれが行われるのですか? 署名の半径は誰に干渉しましたか? それとも、半径の変更を利用可能にするような方法ですか? では、なぜサークルが必要なのですか? 良い方法では、追加のフィールドがオプションに表示されるため、Circle-> CircleMarkerではなく、Options-> CircleOptionsを展開する必要があります。

グループ



レイヤーだけでなくマーカー/グラフィックも配置できるLayerGroupは非常に奇妙です。 ILayerリンクはまだどこにもつながりません。 グループのすべての子を削除するclearLayersメソッド(および名前から私が個人的に考えたように、タイルレイヤーをクリアしない)も非常に奇妙です。

しかし、イベントのプロパガンダとポップアップをLayerGroupに追加するFeatureGroupは、すでにかなり奇妙です。 フィーチャーという名前は誰が言うべきですか? この機能を基本グループに追加できず、レイヤー/機能の分割ができないのはなぜですか?

ジオソン



まず、「累積」GeoJSONのまさにその解決策は、どこか奇妙に見えます。 または、addGeoJSONを2回呼び出すことはできませんか? ドキュメントには答えがありません。

 var geojson = new L.GeoJSON(); geojson.on('featureparse', function(e) { // do something with e.layer depending on e.properties }); geojson.addGeoJSON(geojsonObj); map.addLayer(geojson); 


最も興味深く、隠れているのは「何かをする」ことです。 そして、何ができますか? このグループは、子オブジェクトへのアクセサーを提供しません。 geojson経由でFeatureCollectionを追加した場合-それで何ができますか? またはFeatureCollectionを追加できず、累積addGeoJSONですか?

ところで、JSONがどこでも大きく、geojsonで小さいのはなぜですか? また、タイプミスもあります。coordsToLatlngおよびcoordsToLatlngsでは、大きな「Lng」である必要があります。

最後に



最後に何がありますか?

機能の弱さは、たとえば、ライブラリのサイズが小さいことに起因すると簡単に考えられます(25Kbはレコードです)。 (ただし、ライブラリの重量が1つの標準タイル未満の場合、何を節約できますか?)

異なるエンティティをマップに追加するための一貫性のないインターフェイス-成長病だと思います。 結局のところ、単一のインターフェイスでリリースするには、それらを減らす必要があると思います。

視覚的および美的に、ライブラリ(およびCloud Maid基板)は非常に快適な印象を残し、それに対して多くのことが許されます。 さて、著者は、ファイルとの不整合と不整合を最終決定することを望んでいます。これまでのところバージョンはわずか0.3なので、後方互換性を引き裂く余裕があります。

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


All Articles