diff options
-rw-r--r-- | web/app/Application.js | 8 | ||||
-rw-r--r-- | web/app/Style.js | 4 | ||||
-rw-r--r-- | web/app/view/Map.js | 15 | ||||
-rw-r--r-- | web/app/view/MapController.js | 109 | ||||
-rw-r--r-- | web/l10n/en.json | 1 |
5 files changed, 107 insertions, 30 deletions
diff --git a/web/app/Application.js b/web/app/Application.js index be75a609..743f8b11 100644 --- a/web/app/Application.js +++ b/web/app/Application.js @@ -106,6 +106,14 @@ Ext.define('Traccar.Application', { } }, + getAttributePreference: function (key, defaultValue) { + if (this.getServer().get('forceSettings')) { + return this.getServer().get('attributes')[key] || this.getUser().get('attributes')[key] || defaultValue; + } else { + return this.getUser().get('attributes')[key] || this.getServer().get('attributes')[key] || defaultValue; + } + }, + showError: function (response) { var data; if (Ext.isString(response)) { diff --git a/web/app/Style.js b/web/app/Style.js index a8e16f9f..674fe8ff 100644 --- a/web/app/Style.js +++ b/web/app/Style.js @@ -77,5 +77,7 @@ Ext.define('Traccar.Style', { coordinatePrecision: 6, numberPrecision: 2, - reportTagfieldWidth: 375 + reportTagfieldWidth: 375, + + headerButtonsMargin: '0 5' }); diff --git a/web/app/view/Map.js b/web/app/view/Map.js index 2cbd1714..a19ac7d5 100644 --- a/web/app/view/Map.js +++ b/web/app/view/Map.js @@ -43,6 +43,14 @@ Ext.define('Traccar.view.Map', { return this.geofencesSource; }, + getLiveRouteSource: function () { + return this.liveRouteSource; + }, + + getLiveRouteLayer: function () { + return this.liveRouteLayer; + }, + initMap: function () { this.callParent(); @@ -51,6 +59,13 @@ Ext.define('Traccar.view.Map', { source: this.geofencesSource })); + this.liveRouteSource = new ol.source.Vector({}); + this.liveRouteLayer = new ol.layer.Vector({ + source: this.liveRouteSource, + visible: false + }); + this.map.addLayer(this.liveRouteLayer); + this.latestSource = new ol.source.Vector({}); this.map.addLayer(new ol.layer.Vector({ source: this.latestSource diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js index c2477860..050adce1 100644 --- a/web/app/view/MapController.js +++ b/web/app/view/MapController.js @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * 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 @@ -65,18 +65,29 @@ Ext.define('Traccar.view.MapController', { init: function () { this.latestMarkers = {}; this.reportMarkers = {}; + this.liveRoutes = {}; + this.liveRouteLength = Traccar.app.getAttributePreference('web.liveRouteLength', 10); this.getView().header = { xtype: 'header', title: Strings.mapTitle, - items: [{ + defaults: { xtype: 'button', + tooltipType: 'title', + margin: Traccar.Style.headerButtonsMargin + }, + items: [{ handler: 'showGeofences', reference: 'showGeofencesButton', glyph: 'xf21d@FontAwesome', enableToggle: true, pressed: true, - tooltip: Strings.sharedGeofences, - tooltipType: 'title' + tooltip: Strings.sharedGeofences + }, { + handler: 'showLiveRoutes', + reference: 'showLiveRoutes', + glyph: 'xf1b0@FontAwesome', + enableToggle: true, + tooltip: Strings.mapLiveRoutes }] }; }, @@ -129,8 +140,12 @@ Ext.define('Traccar.view.MapController', { return Ext.getCmp('deviceFollowButton') && Ext.getCmp('deviceFollowButton').pressed; }, + showLiveRoutes: function (button) { + this.getView().getLiveRouteLayer().setVisible(button.pressed); + }, + updateLatest: function (store, data) { - var i, position, geometry, device, deviceId, marker, style; + var i, position, device; if (!Ext.isArray(data)) { data = [data]; @@ -138,35 +153,71 @@ Ext.define('Traccar.view.MapController', { for (i = 0; i < data.length; i++) { position = data[i]; - deviceId = position.get('deviceId'); - device = Ext.getStore('Devices').findRecord('id', deviceId, 0, false, false, true); + device = Ext.getStore('Devices').findRecord('id', position.get('deviceId'), 0, false, false, true); if (device) { - geometry = new ol.geom.Point(ol.proj.fromLonLat([ - position.get('longitude'), - position.get('latitude') - ])); - - if (deviceId in this.latestMarkers) { - marker = this.latestMarkers[deviceId]; - marker.setGeometry(geometry); - } else { - marker = new ol.Feature(geometry); - marker.set('record', device); - this.latestMarkers[deviceId] = marker; - this.getView().getLatestSource().addFeature(marker); - - style = this.getLatestMarker(this.getDeviceColor(device)); - style.getText().setText(device.get('name')); - marker.setStyle(style); - } + this.updateLatestMarker(position, device); + this.updateLiveRoute(position); + } + } + }, + + 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]; + marker.setGeometry(geometry); + } else { + marker = new ol.Feature(geometry); + marker.set('record', device); + this.latestMarkers[deviceId] = marker; + this.getView().getLatestSource().addFeature(marker); + + style = this.getLatestMarker(this.getDeviceColor(device)); + style.getText().setText(device.get('name')); + marker.setStyle(style); + } - marker.getStyle().getImage().setRotation(position.get('course') * Math.PI / 180); + marker.getStyle().getImage().setRotation(position.get('course') * Math.PI / 180); - if (marker === this.selectedMarker && this.followSelected()) { - this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); - } + if (marker === this.selectedMarker && this.followSelected()) { + this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); + } + }, + + updateLiveRoute: function (position) { + 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)); + this.liveRoutes[deviceId] = liveLine; + this.getView().getLiveRouteSource().addFeature(liveLine); } }, diff --git a/web/l10n/en.json b/web/l10n/en.json index ff9a7c47..23bfbf73 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -105,6 +105,7 @@ "mapBingAerial": "Bing Maps Aerial", "mapShapePolygon": "Polygon", "mapShapeCircle": "Circle", + "mapLiveRoutes": "Live Routes", "stateTitle": "State", "stateName": "Attribute", "stateValue": "Value", |