diff --git a/application/src/main/data/json/system/widget_bundles/maps.json b/application/src/main/data/json/system/widget_bundles/maps.json index 1f4807c7d4..66c87e1536 100644 --- a/application/src/main/data/json/system/widget_bundles/maps.json +++ b/application/src/main/data/json/system/widget_bundles/maps.json @@ -130,7 +130,7 @@ "controllerScript": " self.onInit = function() {\n var $scope = self.ctx.$scope;\n $scope.self = self;\n }\n \n \n self.actionSources = function () {\n return {\n 'tooltipAction': {\n name: 'widget-action.tooltip-tag-action',\n multiple: false\n }\n }\n };\n", "settingsSchema": "{\r\n \"schema\": {\r\n \"title\": \"Openstreet Map Configuration\",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"mapProvider\": {\r\n \"title\": \"Map provider\",\r\n \"type\": \"string\",\r\n \"default\": \"OpenStreetMap.Mapnik\"\r\n },\r\n \"defaultZoomLevel\": {\r\n\t\t\t\t\t\"title\": \"Default map zoom level (1 - 20)\",\r\n\t\t\t\t\t\"type\": \"number\"\r\n\t\t\t\t},\r\n\t\t\t\"fitMapBounds\": {\r\n\t\t\t\t\"title\": \"Fit map bounds to cover all markers\",\r\n\t\t\t\t\"type\": \"boolean\",\r\n\t\t\t\t\"default\": true\r\n\t\t\t},\r\n \"latKeyName\": {\r\n \"title\": \"Latitude key name\",\r\n \"type\": \"string\",\r\n \"default\": \"latitude\"\r\n },\r\n \"lngKeyName\": {\r\n \"title\": \"Longitude key name\",\r\n \"type\": \"string\",\r\n \"default\": \"longitude\"\r\n },\r\n \"showLabel\": {\r\n \"title\": \"Show label\",\r\n \"type\": \"boolean\",\r\n \"default\": true\r\n },\r\n \"label\": {\r\n \"title\": \"Label (pattern examples: '${entityName}', '${entityName}: (Text ${keyName} units.)' )\",\r\n \"type\": \"string\",\r\n \"default\": \"${entityName}\"\r\n },\r\n \"useLabelFunction\": {\r\n \"title\": \"Use label function\",\r\n \"type\": \"boolean\",\r\n \"default\": false\r\n },\r\n \"labelFunction\": {\r\n \"title\": \"Label function: f(data, dsData, dsIndex)\",\r\n \"type\": \"string\"\r\n },\r\n \"showTooltip\": {\r\n \"title\": \"Show tooltip\",\r\n \"type\": \"boolean\",\r\n \"default\": true\r\n },\r\n \"tooltipColor\": {\r\n \"title\": \"Tooltip background color\",\r\n \"type\": \"string\",\r\n \"default\": \"#fff\"\r\n },\r\n \"tooltipFontColor\": {\r\n \"title\": \"Tooltip font color\",\r\n \"type\": \"string\",\r\n \"default\": \"#000\"\r\n },\r\n \"tooltipOpacity\": {\r\n \"title\": \"Tooltip opacity (0-1)\",\r\n \"type\": \"number\",\r\n \"default\": 1 \r\n },\r\n \"tooltipPattern\": {\r\n \"title\": \"Tooltip (for ex. 'Text ${keyName} units.' or Link text')\",\r\n \"type\": \"string\",\r\n \"default\": \"${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
End Time: ${maxTime}
Start Time: ${minTime}\"\r\n },\r\n \"useTooltipFunction\": {\r\n \"title\": \"Use tooltip function\",\r\n \"type\": \"boolean\",\r\n \"default\": false\r\n },\r\n \"tooltipFunction\": {\r\n \"title\": \"Tooltip function: f(data, dsData, dsIndex)\",\r\n \"type\": \"string\"\r\n },\r\n \"color\": {\r\n \"title\": \"Stroke color\",\r\n \"type\": \"string\"\r\n },\r\n \"strokeWeight\": {\r\n \"title\": \"Stroke weight\",\r\n \"type\": \"number\",\r\n \"default\": 2\r\n },\r\n \"strokeOpacity\": {\r\n \"title\": \"Stroke opacity\",\r\n \"type\": \"number\",\r\n \"default\": 1\r\n },\r\n \"useColorFunction\": {\r\n \"title\": \"Use stroke color function\",\r\n \"type\": \"boolean\",\r\n \"default\": false\r\n },\r\n \"colorFunction\": {\r\n \"title\": \"Stroke color function: f(data, dsData, dsIndex)\",\r\n \"type\": \"string\"\r\n },\r\n \"showPoints\": {\r\n \"title\": \"Show points\",\r\n \"type\": \"boolean\",\r\n \"default\": false\r\n },\r\n \"pointColor\": {\r\n \"title\": \"Point color\",\r\n \"type\": \"string\"\r\n },\r\n \"pointSize\": {\r\n \"title\": \"Point size (px)\",\r\n \"type\": \"number\",\r\n \"default\": 10\r\n },\r\n \"defaultMarkerColor\": {\r\n \"title\": \"color for default marker\",\r\n \"type\": \"string\"\r\n },\r\n \"markerImage\": {\r\n \"title\": \"Custom marker image\",\r\n \"type\": \"string\"\r\n },\r\n \"markerImageSize\": {\r\n \"title\": \"Custom marker image size (px)\",\r\n \"type\": \"number\",\r\n \"default\": 34\r\n },\r\n \"rotationAngle\": {\r\n \"title\": \"Set additional rotation angle for marker (deg)\",\r\n \"type\": \"number\",\r\n \"default\": 180\r\n },\r\n \"useMarkerImageFunction\":{\r\n \"title\":\"Use marker image function\",\r\n \"type\":\"boolean\",\r\n \"default\":false\r\n },\r\n \"markerImageFunction\":{\r\n \"title\":\"Marker image function: f(data, images, dsData, dsIndex)\",\r\n \"type\":\"string\"\r\n },\r\n \"markerImages\":{\r\n \"title\":\"Marker images\",\r\n \"type\":\"array\",\r\n \"items\":{\r\n \"title\":\"Marker image\",\r\n \"type\":\"string\"\r\n }\r\n }\r\n },\r\n \"required\": []\r\n },\r\n \"form\": [{\r\n \"key\": \"mapProvider\",\r\n \"type\": \"rc-select\",\r\n \"multiple\": false,\r\n \"items\": [{\r\n \"value\": \"OpenStreetMap.Mapnik\",\r\n \"label\": \"OpenStreetMap.Mapnik (Default)\"\r\n }, {\r\n \"value\": \"OpenStreetMap.BlackAndWhite\",\r\n \"label\": \"OpenStreetMap.BlackAndWhite\"\r\n }, {\r\n \"value\": \"OpenStreetMap.HOT\",\r\n \"label\": \"OpenStreetMap.HOT\"\r\n }, {\r\n \"value\": \"Esri.WorldStreetMap\",\r\n \"label\": \"Esri.WorldStreetMap\"\r\n }, {\r\n \"value\": \"Esri.WorldTopoMap\",\r\n \"label\": \"Esri.WorldTopoMap\"\r\n }, {\r\n \"value\": \"CartoDB.Positron\",\r\n \"label\": \"CartoDB.Positron\"\r\n }, {\r\n \"value\": \"CartoDB.DarkMatter\",\r\n \"label\": \"CartoDB.DarkMatter\"\r\n }]\r\n },\"defaultZoomLevel\", \"fitMapBounds\", \"latKeyName\", \"lngKeyName\", \"showLabel\", \"label\", \"useLabelFunction\", {\r\n \"key\": \"labelFunction\",\r\n \"type\": \"javascript\"\r\n }, \"showTooltip\", {\r\n \"key\": \"tooltipColor\",\r\n \"type\": \"color\"\r\n }, {\r\n \"key\": \"tooltipFontColor\",\r\n \"type\": \"color\"\r\n },\"tooltipOpacity\", {\r\n \"key\": \"tooltipPattern\",\r\n \"type\": \"textarea\"\r\n }, \"useTooltipFunction\", {\r\n \"key\": \"tooltipFunction\",\r\n \"type\": \"javascript\"\r\n }, {\r\n \"key\": \"color\",\r\n \"type\": \"color\"\r\n }, \"useColorFunction\", {\r\n \"key\": \"colorFunction\",\r\n \"type\": \"javascript\"\r\n }, \"strokeWeight\", \"strokeOpacity\", \"showPoints\",{\r\n \"key\": \"pointColor\",\r\n \"type\": \"color\"\r\n }, \"pointSize\", {\r\n \"key\": \"defaultMarkerColor\",\r\n \"type\": \"color\"\r\n }, {\r\n \"key\": \"markerImage\",\r\n \"type\": \"image\"\r\n }, \"markerImageSize\", \"rotationAngle\",\"useMarkerImageFunction\",\r\n {\r\n \"key\":\"markerImageFunction\",\r\n \"type\":\"javascript\"\r\n }, {\r\n \"key\":\"markerImages\",\r\n \"items\":[\r\n {\r\n \"key\":\"markerImages[]\",\r\n \"type\":\"image\"\r\n }\r\n ]\r\n }]\r\n}", "dataKeySettingsSchema": "{}", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var lats = [37.7696499,\\n37.7699074,\\n37.7699536,\\n37.7697242,\\n37.7695189,\\n37.7696889,\\n37.7697153,\\n37.7701244,\\n37.7700604,\\n37.7705491,\\n37.7715705,\\n37.771752,\\n37.7707533,\\n37.769866];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lats[i];\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var lons = [-122.4261215,\\n-122.4219157,\\n-122.4199623,\\n-122.4179074,\\n-122.4155876,\\n-122.4155521,\\n-122.4163203,\\n-122.4193876,\\n-122.4210496,\\n-122.422284,\\n-122.4232717,\\n-122.4235138,\\n-122.4247605,\\n-122.4258812];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lons[i];\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
End Time: ${maxTime}
Start Time: ${minTime}\",\"strokeWeight\":3,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"Route\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var lats = [37.7696499,\\n37.7699074,\\n37.7699536,\\n37.7697242,\\n37.7695189,\\n37.7696889,\\n37.7697153,\\n37.7701244,\\n37.7700604,\\n37.7705491,\\n37.7715705,\\n37.771752,\\n37.7707533,\\n37.769866];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lats[i];\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var lons = [-122.4261215,\\n-122.4219157,\\n-122.4199623,\\n-122.4179074,\\n-122.4155876,\\n-122.4155521,\\n-122.4163203,\\n-122.4193876,\\n-122.4210496,\\n-122.422284,\\n-122.4232717,\\n-122.4235138,\\n-122.4247605,\\n-122.4258812];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lons[i];\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"mapProvider\":\"OpenStreetMap.Mapnik\",\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"showTooltip\":true,\"tooltipColor\":\"#fff\",\"tooltipFontColor\":\"#000\",\"tooltipOpacity\":1,\"tooltipPattern\":\"${entityName}\\n
\\nTime: ${formattedTs}\\nLatitude: ${latitude:7}\\nLongitude: ${longitude:7}\",\"strokeWeight\":3,\"strokeOpacity\":1,\"pointSize\":10,\"markerImageSize\":34,\"rotationAngle\":180},\"title\":\"Trip Animation\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" } } ] diff --git a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js index 311efebf24..e7dcad6299 100644 --- a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js +++ b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.js @@ -17,10 +17,8 @@ import './trip-animation-widget.scss'; import template from "./trip-animation-widget.tpl.html"; import TbOpenStreetMap from '../openstreet-map'; import L from 'leaflet'; -//import tinycolor from 'tinycolor2'; import tinycolor from "tinycolor2"; import {fillPatternWithActions, isNumber, padValue, processPattern} from "../widget-utils"; -//import {fillPatternWithActions, isNumber, padValue, processPattern, fillPattern} from "../widget-utils"; (function () { // save these original methods before they are overwritten @@ -121,20 +119,17 @@ function tripAnimationWidget() { } /*@ngInject*/ -function tripAnimationController($document, $scope, $http, $timeout, $filter) { +function tripAnimationController($document, $scope, $http, $timeout, $filter, $sce) { let vm = this; - //const varsRegex = /\$\{([^\}]*)\}/g; - //let icon; vm.initBounds = true; vm.markers = []; vm.index = 0; vm.dsIndex = 0; - vm.isPlaying = false; vm.minTime = 0; vm.maxTime = 0; - vm.isPLaying = false; + vm.isPlaying = false; vm.trackingLine = { "type": "FeatureCollection", features: [] @@ -163,7 +158,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { function initializeCallbacks() { vm.self.onDataUpdated = function () { - createUpdatePath(); + createUpdatePath(true); }; vm.self.onResize = function () { @@ -192,26 +187,54 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } vm.playMove = function (play) { - if (play && vm.isPLaying) return; - if (play || vm.isPLaying) vm.isPLaying = true; - if (vm.isPLaying) { - if (vm.index + 1 > vm.maxTime) return; - vm.index++; - vm.trips.forEach(function (trip) { - moveMarker(trip); - }); + if (play && vm.isPlaying) return; + if (play || vm.isPlaying) vm.isPlaying = true; + if (vm.isPlaying) { + moveInc(1); vm.timeout = $timeout(function () { vm.playMove(); }, 1000 / vm.speed) } }; + vm.moveNext = function () { + vm.stopPlay(); + moveInc(1); + } + + vm.movePrev = function () { + vm.stopPlay(); + moveInc(-1); + } + + vm.moveStart = function () { + vm.stopPlay(); + moveToIndex(vm.minTime); + } + + vm.moveEnd = function () { + vm.stopPlay(); + moveToIndex(vm.maxTime); + } vm.stopPlay = function () { - vm.isPLaying = false; - $timeout.cancel(vm.timeout); + if (vm.isPlaying) { + vm.isPlaying = false; + $timeout.cancel(vm.timeout); + } }; + function moveInc(inc) { + let newIndex = vm.index + inc; + moveToIndex(newIndex); + } + + function moveToIndex(newIndex) { + if (newIndex > vm.maxTime || newIndex < vm.minTime) return; + vm.index = newIndex; + recalculateTrips(); + } + function recalculateTrips() { vm.trips.forEach(function (value) { moveMarker(value); @@ -233,7 +256,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { vm.utils = vm.self.ctx.$scope.$injector.get('utils'); vm.showTimestamp = vm.settings.showTimestamp !== false; - vm.ctx.$element = angular.element("#heat-map", vm.ctx.$container); + vm.ctx.$element = angular.element("#trip-animation-map", vm.ctx.$container); vm.defaultZoomLevel = 2; if (vm.ctx.settings.defaultZoomLevel) { if (vm.ctx.settings.defaultZoomLevel > 0 && vm.ctx.settings.defaultZoomLevel < 21) { @@ -257,6 +280,8 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { let staticSettings = {}; vm.staticSettings = staticSettings; //Calculate General Settings + staticSettings.buttonColor = tinycolor(vm.widgetConfig.color).setAlpha(0.54).toRgbString(); + staticSettings.disabledButtonColor = tinycolor(vm.widgetConfig.color).setAlpha(0.3).toRgbString(); staticSettings.mapProvider = vm.ctx.settings.mapProvider || "OpenStreetMap.Mapnik"; staticSettings.latKeyName = vm.ctx.settings.latKeyName || "latitude"; staticSettings.lngKeyName = vm.ctx.settings.lngKeyName || "longitude"; @@ -268,10 +293,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { staticSettings.useLabelFunction = vm.ctx.settings.useLabelFunction || false; staticSettings.showLabel = vm.ctx.settings.showLabel || false; staticSettings.useTooltipFunction = vm.ctx.settings.useTooltipFunction || false; - staticSettings.tooltipPattern = vm.ctx.settings.tooltipPattern || "${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
Start Time: ${maxTime}
End Time: ${minTime}"; - staticSettings.tooltipOpacity = vm.ctx.settings.tooltipOpacity || 1; - staticSettings.tooltipColor = vm.ctx.settings.tooltipColor ? tinycolor(vm.ctx.settings.tooltipColor).toHexString() : "#ffffff"; - staticSettings.tooltipFontColor = vm.ctx.settings.tooltipFontColor ? tinycolor(vm.ctx.settings.tooltipFontColor).toHexString() : "#000000"; + staticSettings.tooltipPattern = vm.ctx.settings.tooltipPattern || "${entityName}\n" + + "
\n" + + "Time: ${formattedTs}\n" + + "Latitude: ${latitude:7}\n" + + "Longitude: ${longitude:7}"; + staticSettings.tooltipOpacity = angular.isNumber(vm.ctx.settings.tooltipOpacity) ? vm.ctx.settings.tooltipOpacity : 1; + staticSettings.tooltipColor = vm.ctx.settings.tooltipColor ? tinycolor(vm.ctx.settings.tooltipColor).toRgbString() : "#ffffff"; + staticSettings.tooltipFontColor = vm.ctx.settings.tooltipFontColor ? tinycolor(vm.ctx.settings.tooltipFontColor).toRgbString() : "#000000"; staticSettings.pathColor = vm.ctx.settings.color ? tinycolor(vm.ctx.settings.color).toHexString() : "#ff6300"; staticSettings.pathWeight = vm.ctx.settings.strokeWeight || 1; staticSettings.pathOpacity = vm.ctx.settings.strokeOpacity || 1; @@ -351,16 +380,23 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } } - function configureTripSettings(trip) { + function configureTripSettings(trip, index, apply) { trip.settings = {}; trip.settings.color = calculateColor(trip); trip.settings.strokeWeight = vm.staticSettings.pathWeight; trip.settings.strokeOpacity = vm.staticSettings.pathOpacity; trip.settings.pointColor = vm.staticSettings.pointColor; trip.settings.pointSize = vm.staticSettings.pointSize; - trip.settings.labelText = calculateLabel(trip); - trip.settings.tooltipText = calculateTooltip(trip); trip.settings.icon = calculateIcon(trip); + if (apply) { + $timeout(() => { + trip.settings.labelText = calculateLabel(trip); + trip.settings.tooltipText = $sce.trustAsHtml(calculateTooltip(trip)); + },0,true); + } else { + trip.settings.labelText = calculateLabel(trip); + trip.settings.tooltipText = $sce.trustAsHtml(calculateTooltip(trip)); + } } function calculateLabel(trip) { @@ -464,7 +500,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { return icon; } - function createUpdatePath() { + function createUpdatePath(apply) { if (vm.trips && vm.map) { vm.trips.forEach(function (trip) { if (trip.marker) { @@ -486,7 +522,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } let normalizedTimeRange = createNormalizedTime(vm.data, 1000); createNormalizedTrips(normalizedTimeRange, vm.datasources); - createTripsOnMap(); + createTripsOnMap(apply); if (vm.initBounds && !vm.initTrips) { vm.trips.forEach(function (trip) { vm.map.extendBounds(vm.map.bounds, trip.polyline); @@ -501,7 +537,6 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { vm.map.fitBounds(vm.map.bounds); } - } function fillPattern(pattern, replaceInfo, currentNormalizedValue) { @@ -549,12 +584,20 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } }); for (let i = min_time; i < max_time; i += step) { - normalizedArray.push({ts: i}) + normalizedArray.push({ts: i, formattedTs: $filter('date')(i, 'medium')}); + } - if (normalizedArray[normalizedArray.length - 1] && normalizedArray[normalizedArray.length - 1].ts !== max_time) normalizedArray.push({ts: max_time}); + if (normalizedArray[normalizedArray.length - 1] && normalizedArray[normalizedArray.length - 1].ts !== max_time) { + normalizedArray.push({ts: max_time, formattedTs: $filter('date')(max_time, 'medium')}); + } } vm.maxTime = normalizedArray.length - 1; - vm.minTime = 0; + vm.minTime = vm.maxTime > 1 ? 1 : 0; + if (vm.index < vm.minTime) { + vm.index = vm.minTime; + } else if (vm.index > vm.maxTime) { + vm.index = vm.maxTime; + } return normalizedArray; } @@ -611,27 +654,43 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } el.latLngs.push(data.latLng); }); - addAngleForTip(el); + addAngleForTrip(el); }) } - function addAngleForTip(trip) { + function addAngleForTrip(trip) { if (trip.timeRange && trip.timeRange.length > 0) { trip.timeRange.forEach(function (point, index) { let nextPoint, prevPoint; nextPoint = index === (trip.timeRange.length - 1) ? trip.timeRange[index] : trip.timeRange[index + 1]; prevPoint = index === 0 ? trip.timeRange[0] : trip.timeRange[index - 1]; - point.h = findAngle(prevPoint[vm.staticSettings.latKeyName], prevPoint[vm.staticSettings.lngKeyName], nextPoint[vm.staticSettings.latKeyName], nextPoint[vm.staticSettings.lngKeyName]); - point.h += vm.staticSettings.rotationAngle; + let nextLatLng = { + lat: nextPoint[vm.staticSettings.latKeyName], + lng: nextPoint[vm.staticSettings.lngKeyName] + }; + let prevLatLng = { + lat: prevPoint[vm.staticSettings.latKeyName], + lng: prevPoint[vm.staticSettings.lngKeyName] + }; + if (nextLatLng.lat === prevLatLng.lat && nextLatLng.lng === prevLatLng.lng) { + if (angular.isNumber(prevPoint.h)) { + point.h = prevPoint.h; + } else { + point.h = vm.staticSettings.rotationAngle; + } + } else { + point.h = findAngle(prevLatLng.lat, prevLatLng.lng, nextLatLng.lat, nextLatLng.lng); + point.h += vm.staticSettings.rotationAngle; + } }); } } - function createTripsOnMap() { + function createTripsOnMap(apply) { if (vm.trips.length > 0) { vm.trips.forEach(function (trip) { if (trip.timeRange.length > 0 && trip.latLngs.every(el => angular.isDefined(el))) { - configureTripSettings(trip, vm.index); + configureTripSettings(trip, vm.index, apply); if (vm.staticSettings.showPoints) { trip.points = []; trip.latLngs.forEach(function (latLng) { @@ -648,14 +707,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { } if (trip.timeRange && trip.timeRange.length && angular.isUndefined(trip.marker)) { - trip.marker = L.marker(trip.timeRange[vm.index].latLng).addTo(vm.map.map); + trip.marker = L.marker(trip.timeRange[vm.index].latLng); trip.marker.setZIndexOffset(1000); trip.marker.setIcon(vm.staticSettings.icon); trip.marker.setRotationOrigin('center center'); - // trip.marker.addTo(vm.map.map); - trip.marker.on('click', function () { - showHideTooltip(trip); - }); + trip.marker.on('click', function () { + showHideTooltip(trip); + }); + trip.marker.addTo(vm.map.map); moveMarker(trip); } } @@ -675,10 +734,10 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { trip.marker.setZIndexOffset(1000); trip.marker.setIcon(vm.staticSettings.icon); trip.marker.setRotationOrigin('center center'); + trip.marker.on('click', function () { + showHideTooltip(trip); + }); trip.marker.addTo(vm.map.map); - trip.marker.on('click', function () { - showHideTooltip(trip); - }); trip.marker.update(); } diff --git a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.scss b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.scss index 1b6ae956c3..b4616214fc 100644 --- a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.scss +++ b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.scss @@ -14,93 +14,123 @@ * limitations under the License. */ -.heat-map-widget { +.trip-animation-widget { + position: relative; width: 100%; height: 100%; font-size: 16px; line-height: 24px; -} -.heat-map-info-panel { - position: absolute; - top: 0; - right: 0; - z-index: 2; - background-color: rgba(0, 0, 0, .3); - border-bottom-left-radius: 5px; - - .md-button { - min-width: auto; + .trip-animation-label-container { + height: 24px; } -} -.heat-map-tooltip { - position: absolute; - top: 47px; - right: 0; - z-index: 2; - padding: 10px; - background-color: #fff; - border-top-left-radius: 10px; - border-bottom-left-radius: 10px; - transition: .3s ease-in-out; + .trip-animation-container { + position: relative; + z-index: 1; + flex: 1; + width: 100%; - &-hidden { - transform: translateX(100%); - } -} + #trip-animation-map { + z-index: 1; + width: 100%; + height: 100%; -.heat-map-title { - padding: 10px; -} + .pointsLayerMarkerIcon { + border-radius: 50%; + } + } -.heat-map-control-panel { - position: absolute; - bottom: 0; - z-index: 2; - box-sizing: border-box; - width: 100%; - padding-right: 70px; - padding-left: 20px; - background: rgba(0, 0, 0, .3); + .trip-animation-info-panel { + position: absolute; + top: 0; + right: 0; + z-index: 2; + pointer-events: none; - md-slider-container { - button { - max-width: none; + .md-button { + top: 0; + left: 0; + width: 32px; + min-width: 32px; + height: 32px; + min-height: 32px; + padding: 0 0 2px; + margin: 2px; + line-height: 24px; - ng-md-icon { - width: 36px; - height: 36px; + ng-md-icon { + width: 24px; + height: 24px; - svg { - width: inherit; - height: inherit; + svg { + width: inherit; + height: inherit; + } } } } + .trip-animation-tooltip { + position: absolute; + top: 38px; + right: 0; + z-index: 2; + padding: 10px; + background-color: #fff; + transition: .3s ease-in-out; + + &-hidden { + transform: translateX(110%); + } + } + } + + .trip-animation-control-panel { + position: relative; + box-sizing: border-box; + width: 100%; + padding-left: 10px; + + md-slider-container { + md-slider { + min-width: 80px; + } + + button.md-button.md-icon-button { + width: 44px; + min-width: 44px; + height: 44px; + min-height: 44px; + margin: 0; + line-height: 28px; + + md-icon { + width: 28px; + height: 28px; + font-size: 28px; + + svg { + width: inherit; + height: inherit; + } + } + } + + md-select { + margin: 0; + } + } + .panel-timer { max-width: none; - font-size: 20px; - font-weight: 600; + padding-right: 250px; + padding-left: 90px; + margin-top: -20px; + font-size: 12px; + font-weight: 500; + text-align: center; } } } - -.heat-map-container { - position: relative; - z-index: 1; - flex: 1; - width: 100%; -} - -#heat-map { - z-index: 1; - width: 100%; - height: 100%; - - .pointsLayerMarkerIcon { - border-radius: 50%; - } -} diff --git a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.tpl.html b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.tpl.html index 5ffc6d56f9..498ca5cb71 100644 --- a/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.tpl.html +++ b/ui/src/app/widget/lib/tripAnimation/trip-animation-widget.tpl.html @@ -15,40 +15,53 @@ limitations under the License. --> -
-
+
{{vm.trips[vm.activeTripIndex].settings.labelText}}
-
+
+
+
+ + + +
+
+
+
+
+ + fast_rewind + + + skip_previous + - - + + skip_next + + + fast_forward + + + + play_circle_outline + {{ speed}} - - + + + pause_circle_outline + -
{{vm.trips[vm.activeTripIndex].timeRange[vm.index].ts | date:'medium'}} -
-
-
-
-
- - - - - - -
-
+
{{vm.trips[vm.activeTripIndex].timeRange[vm.index].ts | date:'medium'}}
-
\ No newline at end of file +