diff options
Diffstat (limited to 'web/app/view/map')
-rw-r--r-- | web/app/view/map/BaseMap.js | 243 | ||||
-rw-r--r-- | web/app/view/map/GeofenceMap.js | 150 | ||||
-rw-r--r-- | web/app/view/map/GeofenceMapController.js | 85 | ||||
-rw-r--r-- | web/app/view/map/Map.js | 158 | ||||
-rw-r--r-- | web/app/view/map/MapController.js | 101 | ||||
-rw-r--r-- | web/app/view/map/MapMarkerController.js | 687 |
6 files changed, 0 insertions, 1424 deletions
diff --git a/web/app/view/map/BaseMap.js b/web/app/view/map/BaseMap.js deleted file mode 100644 index 9192a53b..00000000 --- a/web/app/view/map/BaseMap.js +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2016 - 2021 Anton Tananaev (anton@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.BaseMap', { - extend: 'Ext.panel.Panel', - xtype: 'baseMapView', - - layout: 'fit', - - getMap: function () { - return this.map; - }, - - getMapView: function () { - return this.mapView; - }, - - initMap: function () { - var server, layer, type, bingKey, locationIqKey, lat, lon, zoom, maxZoom, target, poiLayer, self = this; - - server = Traccar.app.getServer(); - - type = Traccar.app.getPreference('map', null); - bingKey = server.get('bingKey'); - locationIqKey = Traccar.app.getAttributePreference('locationIqKey', 'pk.0f147952a41c555a5b70614039fd148b'); - - layer = new ol.layer.Group({ - title: Strings.mapLayer, - layers: [ - new ol.layer.Tile({ - title: Strings.mapCustom, - type: 'base', - visible: type === 'custom', - source: new ol.source.XYZ({ - url: Ext.String.htmlDecode(server.get('mapUrl')), - attributions: '' - }) - }), - new ol.layer.Tile({ - title: Strings.mapCustomArcgis, - type: 'base', - visible: type === 'customArcgis', - source: new ol.source.TileArcGISRest({ - url: Ext.String.htmlDecode(server.get('mapUrl')) - }) - }), - new ol.layer.Tile({ - title: Strings.mapBingRoad, - type: 'base', - visible: type === 'bingRoad', - source: new ol.source.BingMaps({ - key: bingKey, - imagerySet: 'Road' - }) - }), - new ol.layer.Tile({ - title: Strings.mapBingAerial, - type: 'base', - visible: type === 'bingAerial', - source: new ol.source.BingMaps({ - key: bingKey, - imagerySet: 'Aerial' - }) - }), - new ol.layer.Tile({ - title: Strings.mapBingHybrid, - type: 'base', - visible: type === 'bingHybrid', - source: new ol.source.BingMaps({ - key: bingKey, - imagerySet: 'AerialWithLabels' - }) - }), - new ol.layer.Tile({ - title: Strings.mapCarto, - type: 'base', - visible: type === 'carto', - source: new ol.source.XYZ({ - url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', - attributions: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> ' + - 'contributors, © <a href="https://carto.com/attributions">CARTO</a>' - }) - }), - new ol.layer.Tile({ - title: Strings.mapAutoNavi, - type: 'base', - visible: type === 'autoNavi' || type === 'baidu', - source: new ol.source.OSM({ - url: 'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}' - }) - }), - new ol.layer.Tile({ - title: Strings.mapYandexMap, - type: 'base', - visible: type === 'yandexMap', - source: new ol.source.XYZ({ - url: 'https://core-renderer-tiles.maps.yandex.net/tiles?l=map&x={x}&y={y}&z={z}', - projection: 'EPSG:3395', - attributions: '© <a href="https://yandex.com/maps/">Yandex</a>' - }) - }), - new ol.layer.Tile({ - title: Strings.mapYandexSat, - type: 'base', - visible: type === 'yandexSat', - source: new ol.source.XYZ({ - url: 'https://core-sat.maps.yandex.net/tiles?l=sat&x={x}&y={y}&z={z}', - projection: 'EPSG:3395', - attributions: '© <a href="https://yandex.com/maps/">Yandex</a>' - }) - }), - new ol.layer.Tile({ - title: Strings.mapOsm, - type: 'base', - visible: type === 'osm', - source: new ol.source.OSM({}) - }), - new ol.layer.Tile({ - title: Strings.mapLocationIqStreets, - type: 'base', - visible: type === 'locationIqStreets' || type === 'wikimedia' || !type, - source: new ol.source.XYZ({ - url: 'https://{a-c}-tiles.locationiq.com/v3/streets/r/{z}/{x}/{y}.png?key=' + locationIqKey, - attributions: '© <a href="https://locationiq.com/">LocationIQ</a>' - }) - }) - ] - }); - - lat = Traccar.app.getPreference('latitude', Traccar.Style.mapDefaultLat); - lon = Traccar.app.getPreference('longitude', Traccar.Style.mapDefaultLon); - zoom = Traccar.app.getPreference('zoom', Traccar.Style.mapDefaultZoom); - maxZoom = Traccar.app.getAttributePreference('web.maxZoom', Traccar.Style.mapMaxZoom); - - this.mapView = new ol.View({ - center: ol.proj.fromLonLat([lon, lat]), - zoom: zoom, - maxZoom: maxZoom - }); - - this.map = new ol.Map({ - target: this.body.dom.id, - layers: [layer], - view: this.mapView - }); - - poiLayer = Traccar.app.getPreference('poiLayer', null); - - if (poiLayer) { - this.map.addLayer(new ol.layer.Vector({ - source: new ol.source.Vector({ - url: poiLayer, - format: new ol.format.KML() - }) - })); - } - - switch (Traccar.app.getAttributePreference('distanceUnit', 'km')) { - case 'mi': - this.map.addControl(new ol.control.ScaleLine({ - units: 'us' - })); - break; - case 'nmi': - this.map.addControl(new ol.control.ScaleLine({ - units: 'nautical' - })); - break; - default: - this.map.addControl(new ol.control.ScaleLine()); - break; - } - - this.map.addControl(new ol.control.LayerSwitcher()); - - target = this.map.getTarget(); - if (typeof target === 'string') { - target = Ext.get(target).dom; - } - - this.map.on('pointermove', function (e) { - var hit = this.forEachFeatureAtPixel(e.pixel, function () { - return true; - }); - if (hit) { - target.style.cursor = 'pointer'; - } else { - target.style.cursor = ''; - } - }); - - this.map.on('click', function (e) { - var i, features = self.map.getFeaturesAtPixel(e.pixel, { - layerFilter: function (layer) { - return !layer.get('name'); - } - }); - if (features) { - for (i = 0; i < features.length; i++) { - self.fireEvent('selectfeature', features[i]); - } - } else { - self.fireEvent('deselectfeature'); - } - }); - - this.map.once('postrender', function () { - self.fireEvent('mapready'); - }); - }, - - listeners: { - afterrender: function () { - this.initMap(); - }, - - resize: function () { - this.map.updateSize(); - } - } -}, function () { - var projection; - proj4.defs('EPSG:3395', '+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'); - ol.proj.proj4.register(proj4); - projection = ol.proj.get('EPSG:3395'); - if (projection) { - projection.setExtent([-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244]); - } -}); diff --git a/web/app/view/map/GeofenceMap.js b/web/app/view/map/GeofenceMap.js deleted file mode 100644 index cc1b7efe..00000000 --- a/web/app/view/map/GeofenceMap.js +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2016 - 2021 Anton Tananaev (anton@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.GeofenceMap', { - extend: 'Traccar.view.map.BaseMap', - xtype: 'geofenceMapView', - - requires: [ - 'Traccar.view.map.GeofenceMapController', - 'Traccar.GeofenceConverter' - ], - - controller: 'geofenceMap', - bodyBorder: true, - - tbar: { - items: [{ - xtype: 'combobox', - store: 'GeofenceTypes', - valueField: 'key', - displayField: 'name', - editable: false, - listeners: { - select: 'onTypeSelect' - } - }, '-', { - xtype: 'tbtext', - html: Strings.sharedImport - }, { - xtype: 'filefield', - name: 'file', - buttonConfig: { - glyph: 'xf093@FontAwesome', - text: '', - tooltip: Strings.sharedSelectFile, - tooltipType: 'title' - }, - listeners: { - change: 'onFileChange', - afterrender: function (fileField) { - fileField.fileInputEl.set({ - accept: '.gpx' - }); - } - } - }, { - xtype: 'tbfill' - }, { - glyph: 'xf00c@FontAwesome', - tooltip: Strings.sharedSave, - tooltipType: 'title', - minWidth: 0, - handler: 'onSaveClick' - }, { - glyph: 'xf00d@FontAwesome', - tooltip: Strings.sharedCancel, - tooltipType: 'title', - minWidth: 0, - handler: 'onCancelClick' - }] - }, - - getFeatures: function () { - return this.features; - }, - - initMap: function () { - var map, mapView, featureOverlay, geometry, fillColor; - this.callParent(); - - map = this.map; - mapView = this.mapView; - - this.features = new ol.Collection(); - if (this.area) { - geometry = Traccar.GeofenceConverter.wktToGeometry(mapView, this.area); - this.features.push(new ol.Feature(geometry)); - this.map.once('postrender', function () { - mapView.fit(geometry, { - padding: [20, 20, 20, 20] - }); - }); - } else { - this.controller.fireEvent('mapstaterequest'); - } - fillColor = ol.color.asArray(Traccar.Style.mapGeofenceColor); - fillColor[3] = Traccar.Style.mapGeofenceOverlayOpacity; - featureOverlay = new ol.layer.Vector({ - source: new ol.source.Vector({ - features: this.features - }), - style: new ol.style.Style({ - fill: new ol.style.Fill({ - color: fillColor - }), - stroke: new ol.style.Stroke({ - color: Traccar.Style.mapGeofenceColor, - width: Traccar.Style.mapGeofenceWidth - }), - image: new ol.style.Circle({ - radius: Traccar.Style.mapGeofenceRadius, - fill: new ol.style.Fill({ - color: Traccar.Style.mapGeofenceColor - }) - }) - }) - }); - featureOverlay.setMap(map); - - map.addInteraction(new ol.interaction.Modify({ - features: this.features, - deleteCondition: function (event) { - return ol.events.condition.shiftKeyOnly(event) && ol.events.condition.singleClick(event); - } - })); - }, - - addInteraction: function (type) { - var self = this; - this.draw = new ol.interaction.Draw({ - features: this.features, - type: type - }); - this.draw.on('drawstart', function () { - self.features.clear(); - }); - this.map.addInteraction(this.draw); - }, - - removeInteraction: function () { - if (this.draw) { - this.map.removeInteraction(this.draw); - this.draw = null; - } - } -}); diff --git a/web/app/view/map/GeofenceMapController.js b/web/app/view/map/GeofenceMapController.js deleted file mode 100644 index 31ab586c..00000000 --- a/web/app/view/map/GeofenceMapController.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.GeofenceMapController', { - extend: 'Ext.app.ViewController', - alias: 'controller.geofenceMap', - - requires: [ - 'Traccar.GeofenceConverter' - ], - - config: { - listen: { - controller: { - '*': { - mapstate: 'setMapState' - } - } - } - }, - - onFileChange: function (fileField) { - var reader, view = this.getView(); - if (fileField.fileInputEl.dom.files.length > 0) { - reader = new FileReader(); - reader.onload = function () { - var parser, xml, segment, projection, points = []; - parser = new DOMParser(); - xml = parser.parseFromString(reader.result, 'text/xml'); - segment = xml.getElementsByTagName('trkseg')[0]; - projection = view.mapView.getProjection(); - Array.from(segment.getElementsByTagName('trkpt')).forEach(function (point) { - var lat, lon; - lat = Number(point.getAttribute('lat')); - lon = Number(point.getAttribute('lon')); - points.push(ol.proj.transform([lon, lat], 'EPSG:4326', projection)); - }); - view.getFeatures().clear(); - view.getFeatures().push(new ol.Feature(new ol.geom.LineString(points))); - }; - reader.onerror = function (event) { - Traccar.app.showError(event.target.error); - }; - reader.readAsText(fileField.fileInputEl.dom.files[0]); - } - }, - - onSaveClick: function (button) { - var geometry, projection; - if (this.getView().getFeatures().getLength() > 0) { - geometry = this.getView().getFeatures().pop().getGeometry(); - projection = this.getView().getMapView().getProjection(); - this.fireEvent('savearea', Traccar.GeofenceConverter.geometryToWkt(projection, geometry)); - button.up('window').close(); - } - }, - - onCancelClick: function (button) { - button.up('window').close(); - }, - - onTypeSelect: function (combo) { - this.getView().removeInteraction(); - this.getView().addInteraction(combo.getValue()); - }, - - setMapState: function (lat, lon, zoom) { - this.getView().getMapView().setCenter(ol.proj.fromLonLat([lon, lat])); - this.getView().getMapView().setZoom(zoom); - } -}); diff --git a/web/app/view/map/Map.js b/web/app/view/map/Map.js deleted file mode 100644 index 36e81de7..00000000 --- a/web/app/view/map/Map.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.Map', { - extend: 'Traccar.view.map.BaseMap', - xtype: 'mapView', - - requires: [ - 'Traccar.view.map.MapController', - 'Traccar.view.SettingsMenu' - ], - - controller: 'map', - - title: Strings.mapTitle, - tbar: { - componentCls: 'toolbar-header-style', - defaults: { - xtype: 'button', - tooltipType: 'title', - stateEvents: ['toggle'], - enableToggle: true, - stateful: { - pressed: true - } - }, - items: [{ - xtype: 'tbtext', - html: Strings.mapTitle, - baseCls: 'x-panel-header-title-default' - }, { - xtype: 'tbfill' - }, { - handler: 'showReports', - reference: 'showReportsButton', - glyph: 'xf0f6@FontAwesome', - stateful: false, - enableToggle: false, - tooltip: Strings.reportTitle - }, { - handler: 'showEvents', - reference: 'showEventsButton', - glyph: 'xf27b@FontAwesome', - stateful: false, - enableToggle: false, - tooltip: Strings.reportEvents - }, { - handler: 'updateGeofences', - reference: 'showGeofencesButton', - glyph: 'xf21d@FontAwesome', - pressed: true, - stateId: 'show-geofences-button', - tooltip: Strings.sharedGeofences - }, { - handler: 'showAccuracy', - reference: 'showAccuracyButton', - glyph: 'xf140@FontAwesome', - pressed: true, - stateId: 'show-accuracy-button', - tooltip: Strings.positionAccuracy - }, { - handler: 'showCurrentLocation', - glyph: 'xf124@FontAwesome', - tooltip: Strings.mapCurrentLocation - }, { - handler: 'showLiveRoutes', - reference: 'showLiveRoutes', - glyph: 'xf1b0@FontAwesome', - stateId: 'show-live-routes-button', - tooltip: Strings.mapLiveRoutes - }, { - reference: 'deviceFollowButton', - glyph: 'xf05b@FontAwesome', - tooltip: Strings.deviceFollow, - stateId: 'device-follow-button', - toggleHandler: 'onFollowClick' - }, { - xtype: 'settingsMenu', - enableToggle: false - }] - }, - - getMarkersSource: function () { - return this.markersSource; - }, - - getAccuracySource: function () { - return this.accuracySource; - }, - - getAccuracyLayer: function () { - return this.accuracyLayer; - }, - - getRouteSource: function () { - return this.routeSource; - }, - - getGeofencesSource: function () { - return this.geofencesSource; - }, - - getLiveRouteSource: function () { - return this.liveRouteSource; - }, - - getLiveRouteLayer: function () { - return this.liveRouteLayer; - }, - - initMap: function () { - this.callParent(); - - this.geofencesSource = new ol.source.Vector({}); - this.map.addLayer(new ol.layer.Vector({ - name: 'geofencesLayer', - source: this.geofencesSource - })); - - this.liveRouteSource = new ol.source.Vector({}); - this.liveRouteLayer = new ol.layer.Vector({ - source: this.liveRouteSource, - visible: this.lookupReference('showLiveRoutes').pressed - }); - this.map.addLayer(this.liveRouteLayer); - - this.routeSource = new ol.source.Vector({}); - this.map.addLayer(new ol.layer.Vector({ - source: this.routeSource - })); - - this.accuracySource = new ol.source.Vector({}); - this.accuracyLayer = new ol.layer.Vector({ - name: 'accuracyLayer', - source: this.accuracySource - }); - this.map.addLayer(this.accuracyLayer); - - this.markersSource = new ol.source.Vector({}); - this.map.addLayer(new ol.layer.Vector({ - source: this.markersSource - })); - } -}); diff --git a/web/app/view/map/MapController.js b/web/app/view/map/MapController.js deleted file mode 100644 index f6d88eed..00000000 --- a/web/app/view/map/MapController.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.MapController', { - extend: 'Traccar.view.map.MapMarkerController', - alias: 'controller.map', - - requires: [ - 'Traccar.GeofenceConverter' - ], - - config: { - listen: { - controller: { - '*': { - mapstaterequest: 'getMapState', - zoomtoalldevices: 'zoomToAllDevices' - } - }, - store: { - '#Geofences': { - load: 'updateGeofences', - add: 'updateGeofences', - update: 'updateGeofences', - remove: 'updateGeofences' - } - } - } - }, - - init: function () { - this.callParent(); - this.lookupReference('showReportsButton').setVisible( - Traccar.app.isMobile() && !Traccar.app.getPreference('disableReports', false)); - this.lookupReference('showEventsButton').setVisible( - Traccar.app.isMobile() && !Traccar.app.getBooleanAttributePreference('ui.disableEvents')); - }, - - showReports: function () { - Traccar.app.showReports(true); - }, - - showEvents: function () { - Traccar.app.showEvents(true); - }, - - onFollowClick: function (button, pressed) { - if (pressed && this.selectedMarker) { - this.getView().getMapView().setCenter(this.selectedMarker.getGeometry().getCoordinates()); - } - }, - - showLiveRoutes: function (button) { - this.getView().getLiveRouteLayer().setVisible(button.pressed); - }, - - showAccuracy: function (button) { - this.getView().getAccuracyLayer().setVisible(button.pressed); - }, - - getMapState: function () { - var zoom, center, projection; - projection = this.getView().getMapView().getProjection(); - center = ol.proj.transform(this.getView().getMapView().getCenter(), projection, 'EPSG:4326'); - zoom = this.getView().getMapView().getZoom(); - this.fireEvent('mapstate', center[1], center[0], zoom); - }, - - updateGeofences: function () { - this.getView().getGeofencesSource().clear(); - if (this.lookupReference('showGeofencesButton').pressed) { - Ext.getStore('Geofences').each(function (geofence) { - var feature = new ol.Feature( - Traccar.GeofenceConverter.wktToGeometry(this.getView().getMapView(), geofence.get('area'))); - feature.setStyle(this.getAreaStyle( - Ext.String.htmlDecode(geofence.get('name')), - geofence.get('attributes') ? geofence.get('attributes').color : null)); - this.getView().getGeofencesSource().addFeature(feature); - return true; - }, this); - } - }, - - zoomToAllDevices: function () { - this.zoomToAllPositions(Ext.getStore('LatestPositions').getData().items); - } -}); diff --git a/web/app/view/map/MapMarkerController.js b/web/app/view/map/MapMarkerController.js deleted file mode 100644 index 2fef4870..00000000 --- a/web/app/view/map/MapMarkerController.js +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) - * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -Ext.define('Traccar.view.map.MapMarkerController', { - extend: 'Ext.app.ViewController', - alias: 'controller.mapMarker', - - requires: [ - 'Traccar.model.Position', - 'Traccar.model.Device', - 'Traccar.DeviceImages' - ], - - config: { - listen: { - controller: { - '*': { - selectdevice: 'selectDevice', - selectreport: 'selectReport', - selectevent: 'selectEvent' - }, - 'devices': { - deselectfeature: 'deselectDevice' - } - }, - store: { - '#Devices': { - add: 'updateDevice', - update: 'updateDevice', - remove: 'removeDevice' - }, - '#VisibleDevices': { - add: 'updateVisibleDevices', - update: 'updateVisibleDevices', - remove: 'updateVisibleDevices', - refresh: 'filterDevices' - }, - '#LatestPositions': { - add: 'updateLatest', - update: 'updateLatest' - }, - '#ReportRoute': { - add: 'addReportMarkers', - load: 'loadReport', - clear: 'clearReport' - }, - '#Events': { - remove: 'clearEvent', - clear: 'clearEvent' - } - }, - component: { - '#': { - mapready: 'initGeolocation', - selectfeature: 'selectFeature', - deselectfeature: 'deselectFeature' - } - } - } - }, - - init: function () { - this.latestMarkers = {}; - this.reportMarkers = {}; - this.accuracyCircles = {}; - this.liveRoutes = {}; - this.liveRouteLength = Traccar.app.getAttributePreference('web.liveRouteLength', 10); - this.selectZoom = Traccar.app.getAttributePreference('web.selectZoom', 0); - }, - - initGeolocation: function () { - var geolocation, accuracyFeature, positionFeature; - - geolocation = new ol.Geolocation({ - trackingOptions: { - enableHighAccuracy: true - }, - projection: this.getView().getMapView().getProjection() - }); - - geolocation.on('error', function (error) { - Traccar.app.showError(error.message); - }); - - accuracyFeature = new ol.Feature(); - geolocation.on('change:accuracyGeometry', function () { - accuracyFeature.setGeometry(geolocation.getAccuracyGeometry()); - }); - - positionFeature = new ol.Feature(); - positionFeature.setStyle(new ol.style.Style({ - image: new ol.style.Circle({ - radius: 6, - fill: new ol.style.Fill({ - color: '#3399CC' - }), - stroke: new ol.style.Stroke({ - color: '#fff', - width: 2 - }) - }) - })); - - geolocation.on('change:position', function () { - var coordinates = geolocation.getPosition(); - positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null); - }); - - this.getView().getAccuracySource().addFeature(accuracyFeature); - this.getView().getMarkersSource().addFeature(positionFeature); - - this.geolocation = geolocation; - }, - - showCurrentLocation: function (view) { - this.geolocation.setTracking(view.pressed); - }, - - getAreaStyle: function (label, color) { - var fillColor, strokeColor, styleConfig; - if (color) { - fillColor = ol.color.asArray(color); - strokeColor = color; - } else { - fillColor = ol.color.asArray(Traccar.Style.mapGeofenceColor); - strokeColor = Traccar.Style.mapGeofenceColor; - } - fillColor[3] = Traccar.Style.mapGeofenceOverlayOpacity; - styleConfig = { - fill: new ol.style.Fill({ - color: fillColor - }), - stroke: new ol.style.Stroke({ - color: strokeColor, - width: Traccar.Style.mapGeofenceWidth - }) - }; - if (label) { - styleConfig.text = new ol.style.Text({ - text: label, - overflow: true, - fill: new ol.style.Fill({ - color: Traccar.Style.mapGeofenceTextColor - }), - stroke: new ol.style.Stroke({ - color: Traccar.Style.mapTextStrokeColor, - width: Traccar.Style.mapTextStrokeWidth - }), - font: Traccar.Style.mapTextFont - }); - } - return new ol.style.Style(styleConfig); - }, - - getDeviceColor: function (device) { - switch (device.get('status')) { - case 'online': - return Traccar.Style.mapColorOnline; - case 'offline': - return Traccar.Style.mapColorOffline; - default: - return Traccar.Style.mapColorUnknown; - } - }, - - updateDevice: function (store, data) { - var i, device, deviceId, deviceName, marker, style; - - if (!Ext.isArray(data)) { - data = [data]; - } - - for (i = 0; i < data.length; i++) { - device = data[i]; - deviceId = device.get('id'); - - if (deviceId in this.latestMarkers) { - marker = this.latestMarkers[deviceId]; - style = marker.getStyle(); - if (style.getImage().fill !== this.getDeviceColor(device) || - style.getImage().category !== device.get('category')) { - this.updateDeviceMarker(style, this.getDeviceColor(device), device.get('category')); - marker.changed(); - } - deviceName = Ext.String.htmlDecode(device.get('name')); - if (style.getText().getText() !== deviceName) { - style.getText().setText(deviceName); - marker.changed(); - } - } - } - }, - - removeDevice: function (store, data) { - var i, deviceId, markersSource; - if (!Ext.isArray(data)) { - data = [data]; - } - - markersSource = this.getView().getMarkersSource(); - - for (i = 0; i < data.length; i++) { - deviceId = data[i].get('id'); - if (this.latestMarkers[deviceId]) { - if (markersSource.getFeatureById(this.latestMarkers[deviceId].getId())) { - markersSource.removeFeature(this.latestMarkers[deviceId]); - } - delete this.latestMarkers[deviceId]; - } - if (this.accuracyCircles[deviceId]) { - if (markersSource.getFeatureById(this.accuracyCircles[deviceId].getId())) { - markersSource.removeFeature(this.accuracyCircles[deviceId]); - } - delete this.accuracyCircles[deviceId]; - } - if (this.liveRoutes[deviceId]) { - if (markersSource.getFeatureById(this.liveRoutes[deviceId].getId())) { - markersSource.removeFeature(this.liveRoutes[deviceId]); - } - delete this.liveRoutes[deviceId]; - } - } - }, - - animateMarker: function (marker, geometry, course) { - var start, end, duration, timeout, line, updatePosition, self, follow; - - start = marker.getGeometry().getCoordinates(); - end = geometry.getCoordinates(); - line = new ol.geom.LineString([start, end]); - duration = Traccar.Style.mapAnimateMarkerDuration; - timeout = Traccar.Style.mapAnimateMarkerTimeout; - self = this; - follow = this.lookupReference('deviceFollowButton').pressed; - - updatePosition = function (position, marker) { - var coordinate, style; - coordinate = marker.get('line').getCoordinateAt(position / (duration / timeout)); - style = marker.getStyle(); - marker.setGeometry(new ol.geom.Point(coordinate)); - if (marker === self.selectedMarker && follow) { - self.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); - } - if (position < duration / timeout) { - setTimeout(updatePosition, timeout, position + 1, marker); - } else { - if (style.getImage().angle !== marker.get('nextCourse')) { - self.rotateMarker(style, marker.get('nextCourse')); - } - marker.set('animating', false); - } - }; - - marker.set('line', line); - marker.set('nextCourse', course); - if (!marker.get('animating')) { - marker.set('animating', true); - updatePosition(1, marker); - } - }, - - updateLatest: function (store, data) { - var i, position, device, deviceStore; - - if (!Ext.isArray(data)) { - data = [data]; - } - - deviceStore = Ext.getStore('Devices'); - - for (i = 0; i < data.length; i++) { - position = data[i]; - device = deviceStore.getById(position.get('deviceId')); - - if (device) { - this.updateAccuracy(position, device); - this.updateLatestMarker(position, device); - this.updateLiveRoute(position, device); - } - } - }, - - updateAccuracy: function (position, device) { - var center, radius, feature; - feature = this.accuracyCircles[position.get('deviceId')]; - - if (position.get('accuracy')) { - center = ol.proj.fromLonLat([position.get('longitude'), position.get('latitude')]); - radius = Ext.getStore('DistanceUnits').convertValue( - position.get('accuracy'), Traccar.app.getAttributePreference('distanceUnit'), true); - - if (feature) { - feature.getGeometry().setCenter(center); - feature.getGeometry().setRadius(radius); - } else { - feature = new ol.Feature(new ol.geom.Circle(center, radius)); - feature.setStyle(this.getAreaStyle(null, Traccar.Style.mapAccuracyColor)); - feature.setId(position.get('deviceId')); - this.accuracyCircles[position.get('deviceId')] = feature; - if (this.isDeviceVisible(device)) { - this.getView().getAccuracySource().addFeature(feature); - } - } - } else { - if (feature && this.getView().getAccuracySource().getFeatureById(feature.getId())) { - this.getView().getAccuracySource().removeFeature(feature); - } - delete this.accuracyCircles[position.get('deviceId')]; - } - }, - - updateLatestMarker: function (position, device) { - var geometry, deviceId, marker, style; - geometry = new ol.geom.Point(ol.proj.fromLonLat([ - position.get('longitude'), - position.get('latitude') - ])); - deviceId = position.get('deviceId'); - if (deviceId in this.latestMarkers) { - marker = this.latestMarkers[deviceId]; - this.animateMarker(marker, geometry, position.get('course')); - } else { - marker = new ol.Feature(geometry); - marker.set('record', device); - - style = this.getLatestMarker(this.getDeviceColor(device), - position.get('course'), - device.get('category')); - style.getText().setText(Ext.String.htmlDecode(device.get('name'))); - marker.setStyle(style); - marker.setId(device.get('id')); - this.latestMarkers[deviceId] = marker; - if (this.isDeviceVisible(device)) { - this.getView().getMarkersSource().addFeature(marker); - } - if (marker === this.selectedMarker && this.lookupReference('deviceFollowButton').pressed) { - this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); - } - } - }, - - updateLiveRoute: function (position, device) { - var deviceId, liveLine, liveCoordinates, lastLiveCoordinates, newCoordinates; - deviceId = position.get('deviceId'); - if (deviceId in this.liveRoutes) { - liveCoordinates = this.liveRoutes[deviceId].getGeometry().getCoordinates(); - lastLiveCoordinates = liveCoordinates[liveCoordinates.length - 1]; - newCoordinates = ol.proj.fromLonLat([position.get('longitude'), position.get('latitude')]); - if (lastLiveCoordinates[0] === newCoordinates[0] && - lastLiveCoordinates[1] === newCoordinates[1]) { - return; - } - if (liveCoordinates.length >= this.liveRouteLength) { - liveCoordinates.shift(); - } - liveCoordinates.push(newCoordinates); - this.liveRoutes[deviceId].getGeometry().setCoordinates(liveCoordinates); - } else { - liveLine = new ol.Feature({ - geometry: new ol.geom.LineString([ - ol.proj.fromLonLat([ - position.get('longitude'), - position.get('latitude') - ]) - ]) - }); - liveLine.setStyle(this.getRouteStyle(deviceId)); - liveLine.setId(deviceId); - this.liveRoutes[deviceId] = liveLine; - if (this.isDeviceVisible(device)) { - this.getView().getMarkersSource().addFeature(liveLine); - } - } - }, - - loadReport: function (store, data) { - var i, position, point, routeSource; - if (data) { - this.addReportMarkers(store, data); - routeSource = this.getView().getRouteSource(); - - this.reportRoute = []; - for (i = 0; i < data.length; i++) { - position = data[i]; - point = ol.proj.fromLonLat([ - position.get('longitude'), - position.get('latitude') - ]); - if (i === 0 || data[i].get('deviceId') !== data[i - 1].get('deviceId')) { - this.reportRoute.push(new ol.Feature({ - geometry: new ol.geom.LineString([]) - })); - this.reportRoute[this.reportRoute.length - 1].setStyle(this.getRouteStyle(data[i].get('deviceId'))); - routeSource.addFeature(this.reportRoute[this.reportRoute.length - 1]); - } - this.reportRoute[this.reportRoute.length - 1].getGeometry().appendCoordinate(point); - } - } - }, - - addReportMarker: function (position) { - var geometry, marker, style, point = ol.proj.fromLonLat([ - position.get('longitude'), - position.get('latitude') - ]); - geometry = new ol.geom.Point(point); - marker = new ol.Feature(geometry); - marker.set('record', position); - style = this.getReportMarker(position.get('deviceId'), position.get('course')); - marker.setStyle(style); - this.getView().getMarkersSource().addFeature(marker); - return marker; - }, - - addReportMarkers: function (store, data) { - var i; - this.clearReport(); - for (i = 0; i < data.length; i++) { - if (store.showMarkers) { - this.reportMarkers[data[i].get('id')] = this.addReportMarker(data[i]); - } - } - this.zoomToAllPositions(data); - }, - - clearReport: function () { - var key, i, reportSource, markersSource; - - reportSource = this.getView().getRouteSource(); - - if (this.reportRoute) { - for (i = 0; i < this.reportRoute.length; i++) { - reportSource.removeFeature(this.reportRoute[i]); - } - this.reportRoute = null; - } - - if (this.reportMarkers) { - markersSource = this.getView().getMarkersSource(); - for (key in this.reportMarkers) { - if (this.reportMarkers.hasOwnProperty(key)) { - markersSource.removeFeature(this.reportMarkers[key]); - } - } - this.reportMarkers = {}; - } - - if (this.selectedMarker && !this.selectedMarker.get('event') && - this.selectedMarker.get('record') instanceof Traccar.model.Position) { - this.selectedMarker = null; - } - }, - - clearEvent: function () { - if (this.selectedMarker && this.selectedMarker.get('event')) { - this.selectMarker(null, false); - } - }, - - getRouteStyle: function (deviceId) { - return new ol.style.Style({ - stroke: new ol.style.Stroke({ - color: Traccar.app.getReportColor(deviceId), - width: Traccar.Style.mapRouteWidth - }) - }); - }, - - getMarkerStyle: function (zoom, color, angle, category) { - var image = Traccar.DeviceImages.getImageIcon(color, zoom, angle, category); - return new ol.style.Style({ - image: image, - text: new ol.style.Text({ - textBaseline: 'bottom', - fill: new ol.style.Fill({ - color: Traccar.Style.mapTextColor - }), - stroke: new ol.style.Stroke({ - color: Traccar.Style.mapTextStrokeColor, - width: Traccar.Style.mapTextStrokeWidth - }), - offsetY: -image.getSize()[1] / 2 - Traccar.Style.mapTextOffset, - font: Traccar.Style.mapTextFont - }) - }); - }, - - getLatestMarker: function (color, angle, category) { - return this.getMarkerStyle(false, color, angle, category); - }, - - getReportMarker: function (deviceId, angle) { - return this.getMarkerStyle(false, Traccar.app.getReportColor(deviceId), angle, 'arrow'); - }, - - resizeMarker: function (style, zoom) { - var image, text; - image = Traccar.DeviceImages.getImageIcon( - style.getImage().fill, zoom, style.getImage().angle, style.getImage().category); - text = style.getText(); - text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset); - style.setText(text); - style.setImage(image); - }, - - rotateMarker: function (style, angle) { - style.setImage(Traccar.DeviceImages.getImageIcon( - style.getImage().fill, style.getImage().zoom, angle, style.getImage().category)); - }, - - updateDeviceMarker: function (style, color, category) { - var image, text; - image = Traccar.DeviceImages.getImageIcon( - color, style.getImage().zoom, style.getImage().angle, category); - text = style.getText(); - text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset); - style.setText(text); - style.setImage(image); - }, - - selectMarker: function (marker, center) { - if (this.selectedMarker) { - if (this.selectedMarker.get('event')) { - this.getView().getMarkersSource().removeFeature(this.selectedMarker); - } else if (!Ext.getStore('ReportRoute').showMarkers && - this.selectedMarker.get('record') instanceof Traccar.model.Position) { - this.getView().getMarkersSource().removeFeature(this.selectedMarker); - delete this.reportMarkers[this.selectedMarker.get('record').get('id')]; - } else { - this.resizeMarker(this.selectedMarker.getStyle(), false); - this.selectedMarker.getStyle().setZIndex(0); - this.selectedMarker.changed(); - } - } - - if (marker) { - this.resizeMarker(marker.getStyle(), true); - marker.getStyle().setZIndex(1); - marker.changed(); - if (center) { - this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); - if (this.selectZoom !== 0 && this.selectZoom > this.getView().getMapView().getZoom()) { - this.getView().getMapView().setZoom(this.selectZoom); - } - } - } - - this.selectedMarker = marker; - }, - - selectDevice: function (device, center) { - this.selectMarker(this.latestMarkers[device.get('id')], center); - }, - - selectReport: function (position, center) { - if (position instanceof Traccar.model.Position) { - if (!Ext.getStore('ReportRoute').showMarkers) { - this.reportMarkers[position.get('id')] = this.addReportMarker(position); - } - this.selectMarker(this.reportMarkers[position.get('id')], center); - } else if (this.selectedMarker) { - this.selectMarker(null, false); - } - }, - - selectEvent: function (position) { - var marker; - if (position) { - marker = this.addReportMarker(position); - marker.set('event', true); - this.selectMarker(marker, true); - } else if (this.selectedMarker && this.selectedMarker.get('event')) { - this.selectMarker(null, false); - } - }, - - selectFeature: function (feature) { - var record = feature.get('record'); - if (record) { - if (record instanceof Traccar.model.Device) { - this.fireEvent('selectdevice', record, false); - } else { - this.fireEvent('selectreport', record, false); - } - } - }, - - deselectFeature: function () { - this.deselectDevice(); - this.fireEvent('deselectfeature'); - }, - - deselectDevice: function () { - this.selectMarker(null, false); - }, - - zoomToAllPositions: function (data) { - var i, point, minx, miny, maxx, maxy; - for (i = 0; i < data.length; i++) { - point = ol.proj.fromLonLat([ - data[i].get('longitude'), - data[i].get('latitude') - ]); - if (i === 0) { - minx = maxx = point[0]; - miny = maxy = point[1]; - } else { - minx = Math.min(point[0], minx); - miny = Math.min(point[1], miny); - maxx = Math.max(point[0], maxx); - maxy = Math.max(point[1], maxy); - } - } - if (minx !== maxx || miny !== maxy) { - this.getView().getMapView().fit([minx, miny, maxx, maxy]); - } else if (point) { - this.getView().getMapView().fit(new ol.geom.Point(point)); - } - }, - - updateVisibleDevices: function (store, data) { - var i, device; - - if (!Ext.isArray(data)) { - data = [data]; - } - - for (i = 0; i < data.length; i++) { - device = data[i]; - if (device.get('id') in this.latestMarkers) { - this.updateDeviceVisibility(device); - } - } - }, - - isDeviceVisible: function (device) { - return Ext.getStore('VisibleDevices').contains(device); - }, - - updateDeviceVisibility: function (device) { - var deviceId, accuracy, liveLine, marker; - deviceId = device.get('id'); - marker = this.latestMarkers[deviceId]; - accuracy = this.accuracyCircles[deviceId]; - liveLine = this.liveRoutes[deviceId]; - if (this.isDeviceVisible(device)) { - if (marker && !this.getView().getMarkersSource().getFeatureById(marker.getId())) { - this.getView().getMarkersSource().addFeature(marker); - } - if (accuracy && !this.getView().getAccuracySource().getFeatureById(accuracy.getId())) { - this.getView().getAccuracySource().addFeature(accuracy); - } - if (liveLine && !this.getView().getLiveRouteSource().getFeatureById(liveLine.getId())) { - this.getView().getLiveRouteSource().addFeature(liveLine); - } - } else { - if (marker && this.getView().getMarkersSource().getFeatureById(marker.getId())) { - this.getView().getMarkersSource().removeFeature(marker); - } - if (accuracy && this.getView().getAccuracySource().getFeatureById(accuracy.getId())) { - this.getView().getAccuracySource().removeFeature(accuracy); - } - if (liveLine && this.getView().getLiveRouteSource().getFeatureById(liveLine.getId())) { - this.getView().getLiveRouteSource().removeFeature(liveLine); - } - } - }, - - filterDevices: function () { - Ext.getStore('Devices').each(this.updateDeviceVisibility, this, false); - } -}); |