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
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.
-->
-