From 1fd5eb5ca7e2b4cfa1f1e373a3602825d8fa07c0 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Thu, 27 Oct 2016 10:33:22 +0500 Subject: Implement live routes --- web/app/Application.js | 8 ++++++ web/app/Style.js | 4 ++- web/app/view/Map.js | 15 +++++++++++ web/app/view/MapController.js | 63 +++++++++++++++++++++++++++++++++++++++---- web/l10n/en.json | 1 + 5 files changed, 85 insertions(+), 6 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..36092cad 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,13 @@ 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, geometry, device, deviceId, marker, style, + liveMarker, liveStyle, liveLine, lastLiveCoordinates; if (!Ext.isArray(data)) { data = [data]; @@ -166,6 +182,43 @@ Ext.define('Traccar.view.MapController', { if (marker === this.selectedMarker && this.followSelected()) { this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates()); } + + if (deviceId in this.liveRoutes) { + lastLiveCoordinates = this.liveRoutes[deviceId][this.liveRoutes[deviceId].length - 1].getGeometry().getCoordinates(); + if (lastLiveCoordinates[0] === geometry.getCoordinates()[0] && + lastLiveCoordinates[1] === geometry.getCoordinates()[1]) { + continue; + } + if (this.liveRoutes[deviceId].length >= this.liveRouteLength * 2) { + this.getView().getLiveRouteSource().removeFeature(this.liveRoutes[deviceId].shift()); + this.getView().getLiveRouteSource().removeFeature(this.liveRoutes[deviceId].shift()); + } + liveLine = new ol.Feature({ + geometry: new ol.geom.LineString([ + lastLiveCoordinates, + ol.proj.fromLonLat([ + position.get('longitude'), + position.get('latitude') + ]) + ]) + }); + liveLine.setStyle(this.getRouteStyle(position.get('deviceId'))); + this.liveRoutes[deviceId].push(liveLine); + this.getView().getLiveRouteSource().addFeature(liveLine); + } else { + this.liveRoutes[deviceId] = []; + } + + liveMarker = new ol.Feature(geometry); + + this.liveRoutes[deviceId].push(liveMarker); + this.getView().getLiveRouteSource().addFeature(liveMarker); + + liveStyle = this.getReportMarker(position.get('deviceId')); + liveStyle.getImage().setRotation(position.get('course') * Math.PI / 180); + + liveMarker.setStyle(liveStyle); + } } }, 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", -- cgit v1.2.3