From 35a3712688cce90c27a2e7cea3335537cbdf1385 Mon Sep 17 00:00:00 2001 From: Krivchikov Dmitry Date: Mon, 23 Jun 2014 10:28:06 +0400 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=8B=D0=B1=D0=BE=D1=80=20=D1=81=D0=BB?= =?UTF-8?q?=D0=BE=D1=8F=20=D0=BA=D0=B0=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ground/controllers/IndexController.php | 9 +- ground/views/indexTemplate.php | 6 +- public/css/style.css | 3 + public/js/main.js | 67 +++------ public/js/tile/Google.js | 199 +++++++++++++++++++++++++ public/js/tile/Yandex.js | 190 +++++++++++++++++++++++ 6 files changed, 426 insertions(+), 48 deletions(-) create mode 100644 public/js/tile/Google.js create mode 100644 public/js/tile/Yandex.js diff --git a/ground/controllers/IndexController.php b/ground/controllers/IndexController.php index 0010718..4786285 100644 --- a/ground/controllers/IndexController.php +++ b/ground/controllers/IndexController.php @@ -11,7 +11,14 @@ class IndexController extends Controller self::addScript('/js/jquery-2.1.0.min.js'); self::addScript('/js/jquery-ui-1.10.4.custom.min.js'); self::addScript('http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js'); - self::addScript('/js/main.js?ver='.App::getConfig('version')); + + self::addScript('http://maps.google.com/maps/api/js?v=3&sensor=false'); + self::addScript('/js/tile/Google.js'); + + self::addScript('http://api-maps.yandex.ru/2.0/?load=package.map&lang=ru-RU'); + self::addScript('/js/tile/Yandex.js'); + + self::addScript('/js/main.js?ver='.App::getConfig('version')); self::addScript('/js/bootstrap.min.js'); self::addStyle('/css/style.css?ver='.App::getConfig('version')); self::addStyle('http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css'); diff --git a/ground/views/indexTemplate.php b/ground/views/indexTemplate.php index 8f7cbfd..a329822 100644 --- a/ground/views/indexTemplate.php +++ b/ground/views/indexTemplate.php @@ -30,7 +30,11 @@

Карты

- Layers +
map Quest
+
Open Street Map
+
Google maps
+
Яндекс.Карты
+
Яндекс.Карты (схема)

Фильтры и поиск

diff --git a/public/css/style.css b/public/css/style.css index ccb3dd8..e020960 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -47,5 +47,8 @@ div#box div {display: none;} div#box div div{display: block;} div#box h3 {margin-top: 10px;} +.layers {cursor: pointer;} +.layers.selected {font-weight: bold;} + /*Leaflet FIX*/ .leaflet-popup-content-wrapper .leaflet-popup-scrolled {border-bottom: none;border-top: none;} \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index 7804860..4524d06 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -43,6 +43,8 @@ var pointsSources = Array(); var search; var route = false; var addPointInProcess = false; +var layer; +var layers = Array(); // -------------------------------- Libs --------------------------------------- @@ -57,52 +59,14 @@ function getURLParameter(name) { * @returns true */ function init() { - myMap = L.map('map',{zoomControl: false}).setView([51.505, -0.09], 13); - L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', { - attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', - maxZoom: 18 - }).addTo(myMap); - -// -// questLayer = function () { -// return new ymaps.Layer( -// 'http://otile1.mqcdn.com/tiles/1.0.0/osm/%z/%x/%y.png', {projection: ymaps.projection.sphericalMercator}); -// }; -// ymaps.layer.storage.add('quest#layer', questLayer); -// ymaps.mapType.storage.add('quest#type', new ymaps.MapType('MapQuest', ['quest#layer'])); -// -// osmLayer = function () { -// return new ymaps.Layer( -// 'http://c.tile.openstreetmap.org/%z/%x/%y.png', {projection: ymaps.projection.sphericalMercator}); -// }; -// ymaps.layer.storage.add('osm#layer', osmLayer); -// ymaps.mapType.storage.add('osm#type', new ymaps.MapType('OpenStreetMap', ['osm#layer'])); -// -// googleLayer = function () { -// return new ymaps.Layer('http://mt0.google.com/vt/lyrs=s@176000000&hl=ru&%c', {projection: ymaps.projection.sphericalMercator,tileTransparent: true}); -// } -// ymaps.layer.storage.add('google#layer', googleLayer); -// ymaps.mapType.storage.add('google#type', new ymaps.MapType('Google Maps', ['google#layer'])); -// -// myMap = new ymaps.Map("map", { -// center: [ymaps.geolocation.latitude, ymaps.geolocation.longitude], -// zoom: 12, -// type:'quest#type', -// behaviors: ['default', 'scrollZoom'] -// }); -// -// myMap.controls.add('mapTools'); -// myMap.controls.add('smallZoomControl'); -// myMap.controls.add('scaleLine'); -// -// typeSelector = new ymaps.control.TypeSelector(); -// typeSelector.addMapType('quest#type', 0); -// typeSelector.addMapType('google#type', 1); -// typeSelector.addMapType('yandex#publicMap', 2); -// typeSelector.addMapType('osm#type', 3); -// myMap.controls.add(typeSelector); -// myMap.copyrights.add('Участники OpenStreetMap'); -// myMap.copyrights.add('Tiles courtesy of MapQuest'); + myMap = L.map('map',{zoomControl: false}).setView([57, 30], 4); + + layers['quest'] = L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',maxZoom: 18}); + layers['osm'] = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery ©',maxZoom: 18}); + layers['google'] = new L.Google('HYBRID'); + layers['yandexMap'] = new L.Yandex(); + layers['yandex'] = new L.Yandex('hybrid'); + setLayer('quest'); initCategories(); // getPoints внутри @@ -641,3 +605,14 @@ function closeBox() return true; } + +function setLayer(name) +{ + if (layer) + myMap.removeLayer(layers[layer]) + + layer = name; + myMap.addLayer(layers[layer]); + $('.layers').removeClass('selected'); + $('.'+layer+'Layer').addClass('selected'); +} diff --git a/public/js/tile/Google.js b/public/js/tile/Google.js new file mode 100644 index 0000000..353a14d --- /dev/null +++ b/public/js/tile/Google.js @@ -0,0 +1,199 @@ +/* + * Google layer using Google Maps API + */ + +/* global google: true */ + +L.Google = L.Class.extend({ + includes: L.Mixin.Events, + + options: { + minZoom: 0, + maxZoom: 18, + tileSize: 256, + subdomains: 'abc', + errorTileUrl: '', + attribution: '', + opacity: 1, + continuousWorld: false, + noWrap: false, + mapOptions: { + backgroundColor: '#dddddd' + } + }, + + // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN + initialize: function(type, options) { + L.Util.setOptions(this, options); + + this._ready = google.maps.Map !== undefined; + if (!this._ready) L.Google.asyncWait.push(this); + + this._type = type || 'SATELLITE'; + }, + + onAdd: function(map, insertAtTheBottom) { + this._map = map; + this._insertAtTheBottom = insertAtTheBottom; + + // create a container div for tiles + this._initContainer(); + this._initMapObject(); + + // set up events + map.on('viewreset', this._resetCallback, this); + + this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); + map.on('move', this._update, this); + + map.on('zoomanim', this._handleZoomAnim, this); + + //20px instead of 1em to avoid a slight overlap with google's attribution + map._controlCorners.bottomright.style.marginBottom = '20px'; + + this._reset(); + this._update(); + }, + + onRemove: function(map) { + map._container.removeChild(this._container); + + map.off('viewreset', this._resetCallback, this); + + map.off('move', this._update, this); + + map.off('zoomanim', this._handleZoomAnim, this); + + map._controlCorners.bottomright.style.marginBottom = '0em'; + }, + + getAttribution: function() { + return this.options.attribution; + }, + + setOpacity: function(opacity) { + this.options.opacity = opacity; + if (opacity < 1) { + L.DomUtil.setOpacity(this._container, opacity); + } + }, + + setElementSize: function(e, size) { + e.style.width = size.x + 'px'; + e.style.height = size.y + 'px'; + }, + + _initContainer: function() { + var tilePane = this._map._container, + first = tilePane.firstChild; + + if (!this._container) { + this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left'); + this._container.id = '_GMapContainer_' + L.Util.stamp(this); + this._container.style.zIndex = 'auto'; + } + + tilePane.insertBefore(this._container, first); + + this.setOpacity(this.options.opacity); + this.setElementSize(this._container, this._map.getSize()); + }, + + _initMapObject: function() { + if (!this._ready) return; + this._google_center = new google.maps.LatLng(0, 0); + var map = new google.maps.Map(this._container, { + center: this._google_center, + zoom: 0, + tilt: 0, + mapTypeId: google.maps.MapTypeId[this._type], + disableDefaultUI: true, + keyboardShortcuts: false, + draggable: false, + disableDoubleClickZoom: true, + scrollwheel: false, + streetViewControl: false, + styles: this.options.mapOptions.styles, + backgroundColor: this.options.mapOptions.backgroundColor + }); + + var _this = this; + this._reposition = google.maps.event.addListenerOnce(map, 'center_changed', + function() { _this.onReposition(); }); + this._google = map; + + google.maps.event.addListenerOnce(map, 'idle', + function() { _this._checkZoomLevels(); }); + //Reporting that map-object was initialized. + this.fire('MapObjectInitialized', { mapObject: map }); + }, + + _checkZoomLevels: function() { + //setting the zoom level on the Google map may result in a different zoom level than the one requested + //(it won't go beyond the level for which they have data). + // verify and make sure the zoom levels on both Leaflet and Google maps are consistent + if (this._google.getZoom() !== this._map.getZoom()) { + //zoom levels are out of sync. Set the leaflet zoom level to match the google one + this._map.setZoom( this._google.getZoom() ); + } + }, + + _resetCallback: function(e) { + this._reset(e.hard); + }, + + _reset: function(clearOldContainer) { + this._initContainer(); + }, + + _update: function(e) { + if (!this._google) return; + this._resize(); + + var center = this._map.getCenter(); + var _center = new google.maps.LatLng(center.lat, center.lng); + + this._google.setCenter(_center); + this._google.setZoom(this._map.getZoom()); + + this._checkZoomLevels(); + }, + + _resize: function() { + var size = this._map.getSize(); + if (this._container.style.width === size.x && + this._container.style.height === size.y) + return; + this.setElementSize(this._container, size); + this.onReposition(); + }, + + + _handleZoomAnim: function (e) { + var center = e.center; + var _center = new google.maps.LatLng(center.lat, center.lng); + + this._google.setCenter(_center); + this._google.setZoom(Math.round(e.zoom)); + }, + + + onReposition: function() { + if (!this._google) return; + google.maps.event.trigger(this._google, 'resize'); + } +}); + +L.Google.asyncWait = []; +L.Google.asyncInitialize = function() { + var i; + for (i = 0; i < L.Google.asyncWait.length; i++) { + var o = L.Google.asyncWait[i]; + o._ready = true; + if (o._container) { + o._initMapObject(); + o._update(); + } + } + L.Google.asyncWait = []; +}; diff --git a/public/js/tile/Yandex.js b/public/js/tile/Yandex.js new file mode 100644 index 0000000..afa0aa1 --- /dev/null +++ b/public/js/tile/Yandex.js @@ -0,0 +1,190 @@ +/* + * L.TileLayer is used for standard xyz-numbered tile layers. + */ + +/* global ymaps: true */ +/* global console: true */ + +L.Yandex = L.Class.extend({ + includes: L.Mixin.Events, + + options: { + minZoom: 0, + maxZoom: 18, + attribution: '', + opacity: 1, + traffic: false + }, + + possibleShortMapTypes: { + schemaMap: 'map', + satelliteMap: 'satellite', + hybridMap: 'hybrid', + publicMap: 'publicMap', + publicMapInHybridView: 'publicMapHybrid' + }, + + _getPossibleMapType: function (mapType) { + var result = 'yandex#map'; + if (typeof mapType !== 'string') { + return result; + } + for (var key in this.possibleShortMapTypes) { + if (mapType === this.possibleShortMapTypes[key]) { + result = 'yandex#' + mapType; + break; + } + if (mapType === ('yandex#' + this.possibleShortMapTypes[key])) { + result = mapType; + } + } + return result; + }, + + // Possible types: yandex#map, yandex#satellite, yandex#hybrid, yandex#publicMap, yandex#publicMapHybrid + // Or their short names: map, satellite, hybrid, publicMap, publicMapHybrid + initialize: function(type, options) { + L.Util.setOptions(this, options); + //Assigning an initial map type for the Yandex layer + this._type = this._getPossibleMapType(type); + }, + + onAdd: function(map, insertAtTheBottom) { + this._map = map; + this._insertAtTheBottom = insertAtTheBottom; + + // create a container div for tiles + this._initContainer(); + this._initMapObject(); + + // set up events + map.on('viewreset', this._resetCallback, this); + + this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); + map.on('move', this._update, this); + + map._controlCorners.bottomright.style.marginBottom = '3em'; + + this._reset(); + this._update(true); + }, + + onRemove: function(map) { + this._map._container.removeChild(this._container); + + this._map.off('viewreset', this._resetCallback, this); + + this._map.off('move', this._update, this); + + map._controlCorners.bottomright.style.marginBottom = '0em'; + }, + + getAttribution: function() { + return this.options.attribution; + }, + + setOpacity: function(opacity) { + this.options.opacity = opacity; + if (opacity < 1) { + L.DomUtil.setOpacity(this._container, opacity); + } + }, + + setElementSize: function(e, size) { + e.style.width = size.x + 'px'; + e.style.height = size.y + 'px'; + }, + + _initContainer: function() { + var tilePane = this._map._container, + first = tilePane.firstChild; + + if (!this._container) { + this._container = L.DomUtil.create('div', 'leaflet-yandex-layer leaflet-top leaflet-left'); + this._container.id = '_YMapContainer_' + L.Util.stamp(this); + this._container.style.zIndex = 'auto'; + } + + if (this.options.overlay) { + first = this._map._container.getElementsByClassName('leaflet-map-pane')[0]; + first = first.nextSibling; + // XXX: Bug with layer order + if (L.Browser.opera) + this._container.className += ' leaflet-objects-pane'; + } + tilePane.insertBefore(this._container, first); + + this.setOpacity(this.options.opacity); + this.setElementSize(this._container, this._map.getSize()); + }, + + _initMapObject: function() { + if (this._yandex) return; + + // Check that ymaps.Map is ready + if (ymaps.Map === undefined) { + if (console) { + console.debug('L.Yandex: Waiting on ymaps.load("package.map")'); + } + return ymaps.load(['package.map'], this._initMapObject, this); + } + + // If traffic layer is requested check if control.TrafficControl is ready + if (this.options.traffic) + if (ymaps.control === undefined || + ymaps.control.TrafficControl === undefined) { + if (console) { + console.debug('L.Yandex: loading traffic and controls'); + } + return ymaps.load(['package.traffic', 'package.controls'], + this._initMapObject, this); + } + //Creating ymaps map-object without any default controls on it + var map = new ymaps.Map(this._container, { center: [0, 0], zoom: 0, behaviors: [], controls: [] }); + + if (this.options.traffic) + map.controls.add(new ymaps.control.TrafficControl({shown: true})); + + if (this._type === 'yandex#null') { + this._type = new ymaps.MapType('null', []); + map.container.getElement().style.background = 'transparent'; + } + map.setType(this._type); + + this._yandex = map; + this._update(true); + + //Reporting that map-object was initialized + this.fire('MapObjectInitialized', { mapObject: map }); + }, + + _resetCallback: function(e) { + this._reset(e.hard); + }, + + _reset: function(clearOldContainer) { + this._initContainer(); + }, + + _update: function(force) { + if (!this._yandex) return; + this._resize(force); + + var center = this._map.getCenter(); + var _center = [center.lat, center.lng]; + var zoom = this._map.getZoom(); + + if (force || this._yandex.getZoom() !== zoom) + this._yandex.setZoom(zoom); + this._yandex.panTo(_center, {duration: 0, delay: 0}); + }, + + _resize: function(force) { + var size = this._map.getSize(), style = this._container.style; + if (style.width === size.x + 'px' && style.height === size.y + 'px') + if (force !== true) return; + this.setElementSize(this._container, size); + var b = this._map.getBounds(), sw = b.getSouthWest(), ne = b.getNorthEast(); + this._yandex.container.fitToViewport(); + } +});