目的
目標は、彼の完全に自由なケンタウロスを盲目にすることでした。 私は常にYandexカードが好きでしたが、APIは好きではありませんでした。 したがって、Yandex-mapsをLeafletのレイヤーとして導入する問題に興味を持ちました。
完成したアプリケーションの例。 リポジトリには48 MBのダンプベースがあります。
作業例 。 Habraeffectで生き残れない可能性があります。
大まかな研究
正当なYandexカードのリクエストを調べて、通信があるタイルサーバーを計算しました。
'http://vec{s}.maps.yandex.net/tiles?l=map&v=4.55.2&z={z}&x={x}&y={y}&scale=2&lang=ru_RU' {s} - (subdomain), , . , 01, 02, 03, 04 {z} - (zoom) {x - (latitude) {y} - (longitude)
これは、リーフレット内でYandexマップタイルを使用するために必要なすべてのデータです。
実装
バックエンドについては、 Ruby On Railsを使用して、レールが遅いという神話を少し払拭します。 結局、地図上に10万個のマーカーを表示します!
まず、マーカーモデルを作成します。
rails g model marker
移行コンテンツ
class CreateMarkers < ActiveRecord::Migration def change create_table :markers do |t| t.float :lat t.float :lng t.string :name t.string :avatar t.string :website t.string :email t.string :city t.string :address t.string :phone t.text :about t.timestamps null: false end end end
rake db:create rake db:migrate
私は、Fakerで埋められたフィールドを持つ100,000のマーカーを生成する小さな工場を書きました。 PostgreSQLを使用しています 。 ベースダンプはdb / db.dumpにあります。
工場
# test/factories/markers.rb FactoryGirl.define do factory :marker do lat {Faker::Address.latitude} lng {Faker::Address.longitude} avatar {Faker::Avatar.image} name {Faker::Name.name} website {Faker::Internet.url} email {Faker::Internet.email} city {Faker::Address.city} address {Faker::Address.street_address} about {Faker::Hipster.paragraph} phone {Faker::PhoneNumber.cell_phone} end end # db/seeds.rb 100000.times do |num| FactoryGirl.create(:marker) ap "#{num}" end
マーカーモデルを制御するには、マーカーコントローラーを生成します。
rails g controller markers
コントローラーコード
class MarkersController < ApplicationController before_action :set_marker, only: [:show] def index respond_to do |format| format.html format.json { pluck_fields = Marker.pluck(:id, :lat, :lng) render json: Oj.dump(pluck_fields) } end end def show render "show", layout: false end private def set_marker @marker = Marker.find(params[:id]) end end
ARオブジェクトの作成に時間を無駄にしないために、 pluckメソッドを呼び出します。pluckメソッドは、必要なフィールドに対してのみSELECTリクエストを実行します。 これにより、生産性が大幅に向上します。 結果は配列の配列です:
[ [1,68.324,-168.542], [2,55.522,59.454], [3,-19.245,-79.233] ]
また、 Oj gemを使用してjsonをすばやく生成します。 ビューでの損失は、100,000個のオブジェクトに対して2msを超えません。
routes.rbで新しいリソースを指定することを忘れないでください:
Rails.application.routes.draw do root to: "markers#index" resources :markers, only: [:index, :show] end
マップ自体にアクセスします。
このような多数のマーカーには、クラスタリングが必要です。 Leafletには、必要な機能を追加するさまざまなプラグインが豊富に揃っています。 PruneClusterに決めました 。
必要なすべてのライブラリを接続します。
application.css
/* *= normalize *= require leaflet *= require prune_cluster *= require_tree . *= require_self */
application.js
//= require jquery //= require leaflet //= require prune_cluster //= require_self //= require_tree .
マップを描画するには、基本的なマークアップを作成する必要があります。
マーカー/ index.html.slim
#map
application.css
#map { position: fixed; left: 0; right: 0; top: 0; bottom: 0; }
これで、リーフレットマップを描画できます。
var map = L.map('map').setView([54.762,37.375], 8), // #map leafletView = new PruneClusterForLeaflet(); // ,
マップには単一のレイヤーがないため、灰色の背景のみが表示されます。 マップへのレイヤーの追加は非常に簡単です。
L.tileLayer( 'http://vec{s}.maps.yandex.net/tiles?l=map&v=4.55.2&z={z}&x={x}&y={y}&scale=2&lang=ru_RU', { subdomains: ['01', '02', '03', '04'], attribution: '<a http="yandex.ru" target="_blank"></a>', reuseTiles: true, updateWhenIdle: false } ).addTo(map);
これで、 #mapコンテナー内に、通常のYandexマップが表示されます。 ただし、地図投影を球形メルカトールから楕円形に再定義する必要があります。再定義しないと、座標に顕著なシフトが生じます。 同時に、リーフレットがマーカーのデフォルトアイコンを取得する場所を示します。
map.options.crs = L.CRS.EPSG3395; L.Icon.Default.imagePath = "/leaflet";
すべてのマーカーを要求し、それらをマップに描画することは残ります。
jQuery.getJSON("/markers.json", {}, function(res){ res.forEach(function (item) { leafletView.RegisterMarker(new PruneCluster.Marker(item[1], item[2], {id: item[0]})); }); map.addLayer(leafletView); })
マーカーに関する情報を取得できないため、マップは意味をなしません。 ポップアップを追加します。これは、マーカーをクリックしてサーバーからコンテンツを取得するときに呼び出されます。
leafletView.PrepareLeafletMarker = function (marker, data) { marker.on('click', function () { jQuery.ajax({ url: "/markers/"+data.id }).done(function (res) { if (marker.getPopup()) { marker.setPopupContent(res) } else { marker.bindPopup(res); marker.openPopup(); } }) }) }
Popupに適切なマークアップを作成します。
マーカー/ show.html.slim
h1 | #{@marker.name} .popup__address | #{@marker.city}, #{@marker.address} .nowrap .popup__avatar img src="#{@marker.avatar}" width="120" height="120" .popup__contacts .popup__contact b : div | #{@marker.phone} .popup__contact b . : div a href="mailto:#{@marker.email}" | #{@marker.email} .popup__contact b : div a href=" #{@marker.website}" target="_blank" | #{@marker.website} p | #{@marker.about}
まとめ
LeafletをYandex-cardsと統合しました。つまり、 leaflet-cardsのすべてのプラグインが利用可能になりました。 作成されたアプリケーションは、100,000個のマーカーの負荷に耐えるだけでなく、非常に便利な機能も備えています。
完成したアプリケーションの例。 リポジトリには48 MBのダンプベースがあります。