Commit 2bc13b68122912fad60d78744cb110c1c2e9b713

Authored by Igor Kulikov
1 parent 2f06be1d

UI: Trip Animation Widget Improvements.

@@ -130,7 +130,7 @@ @@ -130,7 +130,7 @@
130 "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", 130 "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",
131 "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-act name='my-action'>Link text</link-act>')\",\r\n \"type\": \"string\",\r\n \"default\": \"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>End Time:</b> ${maxTime}<br/><b>Start Time:</b> ${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}", 131 "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-act name='my-action'>Link text</link-act>')\",\r\n \"type\": \"string\",\r\n \"default\": \"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>End Time:</b> ${maxTime}<br/><b>Start Time:</b> ${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}",
132 "dataKeySettingsSchema": "{}", 132 "dataKeySettingsSchema": "{}",
133 - "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\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>End Time:</b> ${maxTime}<br/><b>Start Time:</b> ${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}}" 133 + "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\":\"<span style=\\\"font-size: 26px; color: #666; font-weight: bold;\\\">${entityName}</span>\\n<br/>\\n<span style=\\\"font-size: 12px; color: #666; font-weight: bold;\\\">Time:</span><span style=\\\"font-size: 12px;\\\"> ${formattedTs}</span>\\n<span style=\\\"font-size: 12px; color: #666; font-weight: bold;\\\">Latitude:</span> ${latitude:7}\\n<span style=\\\"font-size: 12px; color: #666; font-weight: bold;\\\">Longitude:</span> ${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}}"
134 } 134 }
135 } 135 }
136 ] 136 ]
@@ -17,10 +17,8 @@ import './trip-animation-widget.scss'; @@ -17,10 +17,8 @@ import './trip-animation-widget.scss';
17 import template from "./trip-animation-widget.tpl.html"; 17 import template from "./trip-animation-widget.tpl.html";
18 import TbOpenStreetMap from '../openstreet-map'; 18 import TbOpenStreetMap from '../openstreet-map';
19 import L from 'leaflet'; 19 import L from 'leaflet';
20 -//import tinycolor from 'tinycolor2';  
21 import tinycolor from "tinycolor2"; 20 import tinycolor from "tinycolor2";
22 import {fillPatternWithActions, isNumber, padValue, processPattern} from "../widget-utils"; 21 import {fillPatternWithActions, isNumber, padValue, processPattern} from "../widget-utils";
23 -//import {fillPatternWithActions, isNumber, padValue, processPattern, fillPattern} from "../widget-utils";  
24 22
25 (function () { 23 (function () {
26 // save these original methods before they are overwritten 24 // save these original methods before they are overwritten
@@ -121,20 +119,17 @@ function tripAnimationWidget() { @@ -121,20 +119,17 @@ function tripAnimationWidget() {
121 } 119 }
122 120
123 /*@ngInject*/ 121 /*@ngInject*/
124 -function tripAnimationController($document, $scope, $http, $timeout, $filter) { 122 +function tripAnimationController($document, $scope, $http, $timeout, $filter, $sce) {
125 let vm = this; 123 let vm = this;
126 - //const varsRegex = /\$\{([^\}]*)\}/g;  
127 - //let icon;  
128 124
129 vm.initBounds = true; 125 vm.initBounds = true;
130 126
131 vm.markers = []; 127 vm.markers = [];
132 vm.index = 0; 128 vm.index = 0;
133 vm.dsIndex = 0; 129 vm.dsIndex = 0;
134 - vm.isPlaying = false;  
135 vm.minTime = 0; 130 vm.minTime = 0;
136 vm.maxTime = 0; 131 vm.maxTime = 0;
137 - vm.isPLaying = false; 132 + vm.isPlaying = false;
138 vm.trackingLine = { 133 vm.trackingLine = {
139 "type": "FeatureCollection", 134 "type": "FeatureCollection",
140 features: [] 135 features: []
@@ -163,7 +158,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -163,7 +158,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
163 158
164 function initializeCallbacks() { 159 function initializeCallbacks() {
165 vm.self.onDataUpdated = function () { 160 vm.self.onDataUpdated = function () {
166 - createUpdatePath(); 161 + createUpdatePath(true);
167 }; 162 };
168 163
169 vm.self.onResize = function () { 164 vm.self.onResize = function () {
@@ -192,26 +187,54 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -192,26 +187,54 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
192 } 187 }
193 188
194 vm.playMove = function (play) { 189 vm.playMove = function (play) {
195 - if (play && vm.isPLaying) return;  
196 - if (play || vm.isPLaying) vm.isPLaying = true;  
197 - if (vm.isPLaying) {  
198 - if (vm.index + 1 > vm.maxTime) return;  
199 - vm.index++;  
200 - vm.trips.forEach(function (trip) {  
201 - moveMarker(trip);  
202 - }); 190 + if (play && vm.isPlaying) return;
  191 + if (play || vm.isPlaying) vm.isPlaying = true;
  192 + if (vm.isPlaying) {
  193 + moveInc(1);
203 vm.timeout = $timeout(function () { 194 vm.timeout = $timeout(function () {
204 vm.playMove(); 195 vm.playMove();
205 }, 1000 / vm.speed) 196 }, 1000 / vm.speed)
206 } 197 }
207 }; 198 };
208 199
  200 + vm.moveNext = function () {
  201 + vm.stopPlay();
  202 + moveInc(1);
  203 + }
  204 +
  205 + vm.movePrev = function () {
  206 + vm.stopPlay();
  207 + moveInc(-1);
  208 + }
  209 +
  210 + vm.moveStart = function () {
  211 + vm.stopPlay();
  212 + moveToIndex(vm.minTime);
  213 + }
  214 +
  215 + vm.moveEnd = function () {
  216 + vm.stopPlay();
  217 + moveToIndex(vm.maxTime);
  218 + }
209 219
210 vm.stopPlay = function () { 220 vm.stopPlay = function () {
211 - vm.isPLaying = false;  
212 - $timeout.cancel(vm.timeout); 221 + if (vm.isPlaying) {
  222 + vm.isPlaying = false;
  223 + $timeout.cancel(vm.timeout);
  224 + }
213 }; 225 };
214 226
  227 + function moveInc(inc) {
  228 + let newIndex = vm.index + inc;
  229 + moveToIndex(newIndex);
  230 + }
  231 +
  232 + function moveToIndex(newIndex) {
  233 + if (newIndex > vm.maxTime || newIndex < vm.minTime) return;
  234 + vm.index = newIndex;
  235 + recalculateTrips();
  236 + }
  237 +
215 function recalculateTrips() { 238 function recalculateTrips() {
216 vm.trips.forEach(function (value) { 239 vm.trips.forEach(function (value) {
217 moveMarker(value); 240 moveMarker(value);
@@ -233,7 +256,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -233,7 +256,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
233 vm.utils = vm.self.ctx.$scope.$injector.get('utils'); 256 vm.utils = vm.self.ctx.$scope.$injector.get('utils');
234 257
235 vm.showTimestamp = vm.settings.showTimestamp !== false; 258 vm.showTimestamp = vm.settings.showTimestamp !== false;
236 - vm.ctx.$element = angular.element("#heat-map", vm.ctx.$container); 259 + vm.ctx.$element = angular.element("#trip-animation-map", vm.ctx.$container);
237 vm.defaultZoomLevel = 2; 260 vm.defaultZoomLevel = 2;
238 if (vm.ctx.settings.defaultZoomLevel) { 261 if (vm.ctx.settings.defaultZoomLevel) {
239 if (vm.ctx.settings.defaultZoomLevel > 0 && vm.ctx.settings.defaultZoomLevel < 21) { 262 if (vm.ctx.settings.defaultZoomLevel > 0 && vm.ctx.settings.defaultZoomLevel < 21) {
@@ -257,6 +280,8 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -257,6 +280,8 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
257 let staticSettings = {}; 280 let staticSettings = {};
258 vm.staticSettings = staticSettings; 281 vm.staticSettings = staticSettings;
259 //Calculate General Settings 282 //Calculate General Settings
  283 + staticSettings.buttonColor = tinycolor(vm.widgetConfig.color).setAlpha(0.54).toRgbString();
  284 + staticSettings.disabledButtonColor = tinycolor(vm.widgetConfig.color).setAlpha(0.3).toRgbString();
260 staticSettings.mapProvider = vm.ctx.settings.mapProvider || "OpenStreetMap.Mapnik"; 285 staticSettings.mapProvider = vm.ctx.settings.mapProvider || "OpenStreetMap.Mapnik";
261 staticSettings.latKeyName = vm.ctx.settings.latKeyName || "latitude"; 286 staticSettings.latKeyName = vm.ctx.settings.latKeyName || "latitude";
262 staticSettings.lngKeyName = vm.ctx.settings.lngKeyName || "longitude"; 287 staticSettings.lngKeyName = vm.ctx.settings.lngKeyName || "longitude";
@@ -268,10 +293,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -268,10 +293,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
268 staticSettings.useLabelFunction = vm.ctx.settings.useLabelFunction || false; 293 staticSettings.useLabelFunction = vm.ctx.settings.useLabelFunction || false;
269 staticSettings.showLabel = vm.ctx.settings.showLabel || false; 294 staticSettings.showLabel = vm.ctx.settings.showLabel || false;
270 staticSettings.useTooltipFunction = vm.ctx.settings.useTooltipFunction || false; 295 staticSettings.useTooltipFunction = vm.ctx.settings.useTooltipFunction || false;
271 - staticSettings.tooltipPattern = vm.ctx.settings.tooltipPattern || "<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Start Time:</b> ${maxTime}<br/><b>End Time:</b> ${minTime}";  
272 - staticSettings.tooltipOpacity = vm.ctx.settings.tooltipOpacity || 1;  
273 - staticSettings.tooltipColor = vm.ctx.settings.tooltipColor ? tinycolor(vm.ctx.settings.tooltipColor).toHexString() : "#ffffff";  
274 - staticSettings.tooltipFontColor = vm.ctx.settings.tooltipFontColor ? tinycolor(vm.ctx.settings.tooltipFontColor).toHexString() : "#000000"; 296 + staticSettings.tooltipPattern = vm.ctx.settings.tooltipPattern || "<span style=\"font-size: 26px; color: #666; font-weight: bold;\">${entityName}</span>\n" +
  297 + "<br/>\n" +
  298 + "<span style=\"font-size: 12px; color: #666; font-weight: bold;\">Time:</span><span style=\"font-size: 12px;\"> ${formattedTs}</span>\n" +
  299 + "<span style=\"font-size: 12px; color: #666; font-weight: bold;\">Latitude:</span> ${latitude:7}\n" +
  300 + "<span style=\"font-size: 12px; color: #666; font-weight: bold;\">Longitude:</span> ${longitude:7}";
  301 + staticSettings.tooltipOpacity = angular.isNumber(vm.ctx.settings.tooltipOpacity) ? vm.ctx.settings.tooltipOpacity : 1;
  302 + staticSettings.tooltipColor = vm.ctx.settings.tooltipColor ? tinycolor(vm.ctx.settings.tooltipColor).toRgbString() : "#ffffff";
  303 + staticSettings.tooltipFontColor = vm.ctx.settings.tooltipFontColor ? tinycolor(vm.ctx.settings.tooltipFontColor).toRgbString() : "#000000";
275 staticSettings.pathColor = vm.ctx.settings.color ? tinycolor(vm.ctx.settings.color).toHexString() : "#ff6300"; 304 staticSettings.pathColor = vm.ctx.settings.color ? tinycolor(vm.ctx.settings.color).toHexString() : "#ff6300";
276 staticSettings.pathWeight = vm.ctx.settings.strokeWeight || 1; 305 staticSettings.pathWeight = vm.ctx.settings.strokeWeight || 1;
277 staticSettings.pathOpacity = vm.ctx.settings.strokeOpacity || 1; 306 staticSettings.pathOpacity = vm.ctx.settings.strokeOpacity || 1;
@@ -351,16 +380,23 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -351,16 +380,23 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
351 } 380 }
352 } 381 }
353 382
354 - function configureTripSettings(trip) { 383 + function configureTripSettings(trip, index, apply) {
355 trip.settings = {}; 384 trip.settings = {};
356 trip.settings.color = calculateColor(trip); 385 trip.settings.color = calculateColor(trip);
357 trip.settings.strokeWeight = vm.staticSettings.pathWeight; 386 trip.settings.strokeWeight = vm.staticSettings.pathWeight;
358 trip.settings.strokeOpacity = vm.staticSettings.pathOpacity; 387 trip.settings.strokeOpacity = vm.staticSettings.pathOpacity;
359 trip.settings.pointColor = vm.staticSettings.pointColor; 388 trip.settings.pointColor = vm.staticSettings.pointColor;
360 trip.settings.pointSize = vm.staticSettings.pointSize; 389 trip.settings.pointSize = vm.staticSettings.pointSize;
361 - trip.settings.labelText = calculateLabel(trip);  
362 - trip.settings.tooltipText = calculateTooltip(trip);  
363 trip.settings.icon = calculateIcon(trip); 390 trip.settings.icon = calculateIcon(trip);
  391 + if (apply) {
  392 + $timeout(() => {
  393 + trip.settings.labelText = calculateLabel(trip);
  394 + trip.settings.tooltipText = $sce.trustAsHtml(calculateTooltip(trip));
  395 + },0,true);
  396 + } else {
  397 + trip.settings.labelText = calculateLabel(trip);
  398 + trip.settings.tooltipText = $sce.trustAsHtml(calculateTooltip(trip));
  399 + }
364 } 400 }
365 401
366 function calculateLabel(trip) { 402 function calculateLabel(trip) {
@@ -464,7 +500,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -464,7 +500,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
464 return icon; 500 return icon;
465 } 501 }
466 502
467 - function createUpdatePath() { 503 + function createUpdatePath(apply) {
468 if (vm.trips && vm.map) { 504 if (vm.trips && vm.map) {
469 vm.trips.forEach(function (trip) { 505 vm.trips.forEach(function (trip) {
470 if (trip.marker) { 506 if (trip.marker) {
@@ -486,7 +522,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -486,7 +522,7 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
486 } 522 }
487 let normalizedTimeRange = createNormalizedTime(vm.data, 1000); 523 let normalizedTimeRange = createNormalizedTime(vm.data, 1000);
488 createNormalizedTrips(normalizedTimeRange, vm.datasources); 524 createNormalizedTrips(normalizedTimeRange, vm.datasources);
489 - createTripsOnMap(); 525 + createTripsOnMap(apply);
490 if (vm.initBounds && !vm.initTrips) { 526 if (vm.initBounds && !vm.initTrips) {
491 vm.trips.forEach(function (trip) { 527 vm.trips.forEach(function (trip) {
492 vm.map.extendBounds(vm.map.bounds, trip.polyline); 528 vm.map.extendBounds(vm.map.bounds, trip.polyline);
@@ -501,7 +537,6 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -501,7 +537,6 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
501 537
502 vm.map.fitBounds(vm.map.bounds); 538 vm.map.fitBounds(vm.map.bounds);
503 } 539 }
504 -  
505 } 540 }
506 541
507 function fillPattern(pattern, replaceInfo, currentNormalizedValue) { 542 function fillPattern(pattern, replaceInfo, currentNormalizedValue) {
@@ -549,12 +584,20 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -549,12 +584,20 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
549 } 584 }
550 }); 585 });
551 for (let i = min_time; i < max_time; i += step) { 586 for (let i = min_time; i < max_time; i += step) {
552 - normalizedArray.push({ts: i}) 587 + normalizedArray.push({ts: i, formattedTs: $filter('date')(i, 'medium')});
  588 +
553 } 589 }
554 - if (normalizedArray[normalizedArray.length - 1] && normalizedArray[normalizedArray.length - 1].ts !== max_time) normalizedArray.push({ts: max_time}); 590 + if (normalizedArray[normalizedArray.length - 1] && normalizedArray[normalizedArray.length - 1].ts !== max_time) {
  591 + normalizedArray.push({ts: max_time, formattedTs: $filter('date')(max_time, 'medium')});
  592 + }
555 } 593 }
556 vm.maxTime = normalizedArray.length - 1; 594 vm.maxTime = normalizedArray.length - 1;
557 - vm.minTime = 0; 595 + vm.minTime = vm.maxTime > 1 ? 1 : 0;
  596 + if (vm.index < vm.minTime) {
  597 + vm.index = vm.minTime;
  598 + } else if (vm.index > vm.maxTime) {
  599 + vm.index = vm.maxTime;
  600 + }
558 return normalizedArray; 601 return normalizedArray;
559 } 602 }
560 603
@@ -611,27 +654,43 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -611,27 +654,43 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
611 } 654 }
612 el.latLngs.push(data.latLng); 655 el.latLngs.push(data.latLng);
613 }); 656 });
614 - addAngleForTip(el); 657 + addAngleForTrip(el);
615 }) 658 })
616 } 659 }
617 660
618 - function addAngleForTip(trip) { 661 + function addAngleForTrip(trip) {
619 if (trip.timeRange && trip.timeRange.length > 0) { 662 if (trip.timeRange && trip.timeRange.length > 0) {
620 trip.timeRange.forEach(function (point, index) { 663 trip.timeRange.forEach(function (point, index) {
621 let nextPoint, prevPoint; 664 let nextPoint, prevPoint;
622 nextPoint = index === (trip.timeRange.length - 1) ? trip.timeRange[index] : trip.timeRange[index + 1]; 665 nextPoint = index === (trip.timeRange.length - 1) ? trip.timeRange[index] : trip.timeRange[index + 1];
623 prevPoint = index === 0 ? trip.timeRange[0] : trip.timeRange[index - 1]; 666 prevPoint = index === 0 ? trip.timeRange[0] : trip.timeRange[index - 1];
624 - point.h = findAngle(prevPoint[vm.staticSettings.latKeyName], prevPoint[vm.staticSettings.lngKeyName], nextPoint[vm.staticSettings.latKeyName], nextPoint[vm.staticSettings.lngKeyName]);  
625 - point.h += vm.staticSettings.rotationAngle; 667 + let nextLatLng = {
  668 + lat: nextPoint[vm.staticSettings.latKeyName],
  669 + lng: nextPoint[vm.staticSettings.lngKeyName]
  670 + };
  671 + let prevLatLng = {
  672 + lat: prevPoint[vm.staticSettings.latKeyName],
  673 + lng: prevPoint[vm.staticSettings.lngKeyName]
  674 + };
  675 + if (nextLatLng.lat === prevLatLng.lat && nextLatLng.lng === prevLatLng.lng) {
  676 + if (angular.isNumber(prevPoint.h)) {
  677 + point.h = prevPoint.h;
  678 + } else {
  679 + point.h = vm.staticSettings.rotationAngle;
  680 + }
  681 + } else {
  682 + point.h = findAngle(prevLatLng.lat, prevLatLng.lng, nextLatLng.lat, nextLatLng.lng);
  683 + point.h += vm.staticSettings.rotationAngle;
  684 + }
626 }); 685 });
627 } 686 }
628 } 687 }
629 688
630 - function createTripsOnMap() { 689 + function createTripsOnMap(apply) {
631 if (vm.trips.length > 0) { 690 if (vm.trips.length > 0) {
632 vm.trips.forEach(function (trip) { 691 vm.trips.forEach(function (trip) {
633 if (trip.timeRange.length > 0 && trip.latLngs.every(el => angular.isDefined(el))) { 692 if (trip.timeRange.length > 0 && trip.latLngs.every(el => angular.isDefined(el))) {
634 - configureTripSettings(trip, vm.index); 693 + configureTripSettings(trip, vm.index, apply);
635 if (vm.staticSettings.showPoints) { 694 if (vm.staticSettings.showPoints) {
636 trip.points = []; 695 trip.points = [];
637 trip.latLngs.forEach(function (latLng) { 696 trip.latLngs.forEach(function (latLng) {
@@ -648,14 +707,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -648,14 +707,14 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
648 } 707 }
649 708
650 if (trip.timeRange && trip.timeRange.length && angular.isUndefined(trip.marker)) { 709 if (trip.timeRange && trip.timeRange.length && angular.isUndefined(trip.marker)) {
651 - trip.marker = L.marker(trip.timeRange[vm.index].latLng).addTo(vm.map.map); 710 + trip.marker = L.marker(trip.timeRange[vm.index].latLng);
652 trip.marker.setZIndexOffset(1000); 711 trip.marker.setZIndexOffset(1000);
653 trip.marker.setIcon(vm.staticSettings.icon); 712 trip.marker.setIcon(vm.staticSettings.icon);
654 trip.marker.setRotationOrigin('center center'); 713 trip.marker.setRotationOrigin('center center');
655 - // trip.marker.addTo(vm.map.map);  
656 - trip.marker.on('click', function () {  
657 - showHideTooltip(trip);  
658 - }); 714 + trip.marker.on('click', function () {
  715 + showHideTooltip(trip);
  716 + });
  717 + trip.marker.addTo(vm.map.map);
659 moveMarker(trip); 718 moveMarker(trip);
660 } 719 }
661 } 720 }
@@ -675,10 +734,10 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) { @@ -675,10 +734,10 @@ function tripAnimationController($document, $scope, $http, $timeout, $filter) {
675 trip.marker.setZIndexOffset(1000); 734 trip.marker.setZIndexOffset(1000);
676 trip.marker.setIcon(vm.staticSettings.icon); 735 trip.marker.setIcon(vm.staticSettings.icon);
677 trip.marker.setRotationOrigin('center center'); 736 trip.marker.setRotationOrigin('center center');
  737 + trip.marker.on('click', function () {
  738 + showHideTooltip(trip);
  739 + });
678 trip.marker.addTo(vm.map.map); 740 trip.marker.addTo(vm.map.map);
679 - trip.marker.on('click', function () {  
680 - showHideTooltip(trip);  
681 - });  
682 trip.marker.update(); 741 trip.marker.update();
683 } 742 }
684 743
@@ -14,93 +14,123 @@ @@ -14,93 +14,123 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -.heat-map-widget { 17 +.trip-animation-widget {
  18 +
18 position: relative; 19 position: relative;
19 width: 100%; 20 width: 100%;
20 height: 100%; 21 height: 100%;
21 font-size: 16px; 22 font-size: 16px;
22 line-height: 24px; 23 line-height: 24px;
23 -}  
24 -  
25 -.heat-map-info-panel {  
26 - position: absolute;  
27 - top: 0;  
28 - right: 0;  
29 - z-index: 2;  
30 - background-color: rgba(0, 0, 0, .3);  
31 - border-bottom-left-radius: 5px;  
32 24
33 - .md-button {  
34 - min-width: auto; 25 + .trip-animation-label-container {
  26 + height: 24px;
35 } 27 }
36 -}  
37 28
38 -.heat-map-tooltip {  
39 - position: absolute;  
40 - top: 47px;  
41 - right: 0;  
42 - z-index: 2;  
43 - padding: 10px;  
44 - background-color: #fff;  
45 - border-top-left-radius: 10px;  
46 - border-bottom-left-radius: 10px;  
47 - transition: .3s ease-in-out;  
48 -  
49 - &-hidden {  
50 - transform: translateX(100%);  
51 - }  
52 -} 29 + .trip-animation-container {
  30 + position: relative;
  31 + z-index: 1;
  32 + flex: 1;
  33 + width: 100%;
53 34
54 -.heat-map-title {  
55 - padding: 10px;  
56 -} 35 + #trip-animation-map {
  36 + z-index: 1;
  37 + width: 100%;
  38 + height: 100%;
57 39
58 -.heat-map-control-panel {  
59 - position: absolute;  
60 - bottom: 0;  
61 - z-index: 2;  
62 - box-sizing: border-box;  
63 - width: 100%;  
64 - padding-right: 70px;  
65 - padding-left: 20px;  
66 - background: rgba(0, 0, 0, .3); 40 + .pointsLayerMarkerIcon {
  41 + border-radius: 50%;
  42 + }
  43 + }
67 44
68 - md-slider-container {  
69 - button {  
70 - max-width: none; 45 + .trip-animation-info-panel {
  46 + position: absolute;
  47 + top: 0;
  48 + right: 0;
  49 + z-index: 2;
  50 + pointer-events: none;
71 51
72 - ng-md-icon {  
73 - width: 36px;  
74 - height: 36px; 52 + .md-button {
  53 + top: 0;
  54 + left: 0;
  55 + width: 32px;
  56 + min-width: 32px;
  57 + height: 32px;
  58 + min-height: 32px;
  59 + padding: 0 0 2px;
  60 + margin: 2px;
  61 + line-height: 24px;
75 62
76 - svg {  
77 - width: inherit;  
78 - height: inherit; 63 + ng-md-icon {
  64 + width: 24px;
  65 + height: 24px;
  66 +
  67 + svg {
  68 + width: inherit;
  69 + height: inherit;
  70 + }
79 } 71 }
80 } 72 }
81 } 73 }
82 74
83 - .panel-timer {  
84 - max-width: none;  
85 - font-size: 20px;  
86 - font-weight: 600; 75 + .trip-animation-tooltip {
  76 + position: absolute;
  77 + top: 38px;
  78 + right: 0;
  79 + z-index: 2;
  80 + padding: 10px;
  81 + background-color: #fff;
  82 + transition: .3s ease-in-out;
  83 +
  84 + &-hidden {
  85 + transform: translateX(110%);
  86 + }
87 } 87 }
88 } 88 }
89 -}  
90 89
91 -.heat-map-container {  
92 - position: relative;  
93 - z-index: 1;  
94 - flex: 1;  
95 - width: 100%;  
96 -} 90 + .trip-animation-control-panel {
  91 + position: relative;
  92 + box-sizing: border-box;
  93 + width: 100%;
  94 + padding-left: 10px;
97 95
98 -#heat-map {  
99 - z-index: 1;  
100 - width: 100%;  
101 - height: 100%; 96 + md-slider-container {
  97 + md-slider {
  98 + min-width: 80px;
  99 + }
  100 +
  101 + button.md-button.md-icon-button {
  102 + width: 44px;
  103 + min-width: 44px;
  104 + height: 44px;
  105 + min-height: 44px;
  106 + margin: 0;
  107 + line-height: 28px;
102 108
103 - .pointsLayerMarkerIcon {  
104 - border-radius: 50%; 109 + md-icon {
  110 + width: 28px;
  111 + height: 28px;
  112 + font-size: 28px;
  113 +
  114 + svg {
  115 + width: inherit;
  116 + height: inherit;
  117 + }
  118 + }
  119 + }
  120 +
  121 + md-select {
  122 + margin: 0;
  123 + }
  124 + }
  125 +
  126 + .panel-timer {
  127 + max-width: none;
  128 + padding-right: 250px;
  129 + padding-left: 90px;
  130 + margin-top: -20px;
  131 + font-size: 12px;
  132 + font-weight: 500;
  133 + text-align: center;
  134 + }
105 } 135 }
106 } 136 }
@@ -15,40 +15,53 @@ @@ -15,40 +15,53 @@
15 limitations under the License. 15 limitations under the License.
16 16
17 --> 17 -->
18 -<div class="heat-map-widget tracking-widget" layout="column" layout-align="center start" 18 +<div class="trip-animation-widget" layout="column" layout-align="center start"
19 ng-style="{'padding-top' : (!vm.widgetConfig.showTitle && vm.ctx.settings.showLabel) ? '5px' : '0px'}"> 19 ng-style="{'padding-top' : (!vm.widgetConfig.showTitle && vm.ctx.settings.showLabel) ? '5px' : '0px'}">
20 - <div ng-show="vm.ctx.settings.showLabel"> 20 + <div class="trip-animation-label-container" ng-show="vm.ctx.settings.showLabel">
21 {{vm.trips[vm.activeTripIndex].settings.labelText}} 21 {{vm.trips[vm.activeTripIndex].settings.labelText}}
22 </div> 22 </div>
23 - <div class="heat-map-control-panel" lang="row" layout-align="center start"> 23 + <div class="trip-animation-container" layout="column">
  24 + <div flex id='trip-animation-map'></div>
  25 + <div class="trip-animation-info-panel" layout="row">
  26 + <md-button class="md-primary md-fab" aria-label="tooltip" ng-show="vm.staticSettings.displayTooltip" ng-click="vm.showHideTooltip()">
  27 + <ng-md-icon icon="info_outline"></ng-md-icon>
  28 + </md-button>
  29 + </div>
  30 + <div class="trip-animation-tooltip md-whiteframe-z4" layout="column" ng-class="!vm.staticSettings.showTooltip ? 'trip-animation-tooltip-hidden':''" ng-bind-html="vm.trips[vm.activeTripIndex].settings.tooltipText"
  31 + ng-style="{'background-color': vm.staticSettings.tooltipColor, 'opacity': vm.staticSettings.tooltipOpacity, 'color': vm.staticSettings.tooltipFontColor}">
  32 + </div>
  33 + </div>
  34 + <div class="trip-animation-control-panel">
24 <md-slider-container> 35 <md-slider-container>
  36 + <md-button class="md-icon-button" aria-label="Start" ng-click="vm.moveStart()">
  37 + <md-icon class="material-icons" ng-style="{'color': vm.staticSettings.buttonColor}">fast_rewind</md-icon>
  38 + </md-button>
  39 + <md-button class="md-icon-button" aria-label="Previous" ng-click="vm.movePrev()">
  40 + <md-icon class="material-icons" ng-style="{'color': vm.staticSettings.buttonColor}">skip_previous</md-icon>
  41 + </md-button>
25 <md-slider ng-model="vm.index" min="{{vm.minTime}}" max="{{vm.maxTime}}" ng-change="vm.recalculateTrips()"></md-slider> 42 <md-slider ng-model="vm.index" min="{{vm.minTime}}" max="{{vm.maxTime}}" ng-change="vm.recalculateTrips()"></md-slider>
26 - <md-button aria-label="Play" ng-click="vm.playMove(true)" ng-disabled="vm.isPlaying">  
27 - <ng-md-icon icon="play_circle_outline"></ng-md-icon> 43 + <md-button class="md-icon-button" aria-label="Next" ng-click="vm.moveNext()">
  44 + <md-icon class="material-icons" ng-style="{'color': vm.staticSettings.buttonColor}">skip_next</md-icon>
  45 + </md-button>
  46 + <md-button class="md-icon-button" aria-label="End" ng-click="vm.moveEnd()">
  47 + <md-icon class="material-icons" ng-style="{'color': vm.staticSettings.buttonColor}">fast_forward</md-icon>
  48 + </md-button>
  49 + <md-button class="md-icon-button" aria-label="Play" ng-click="vm.playMove(true)" ng-disabled="vm.isPlaying">
  50 + <md-icon class="material-icons" ng-style="{'color': vm.isPlaying ? vm.staticSettings.disabledButtonColor : vm.staticSettings.buttonColor}">
  51 + play_circle_outline
  52 + </md-icon>
28 </md-button> 53 </md-button>
29 <md-select ng-model="vm.speed" aria-label="Speed selector"> 54 <md-select ng-model="vm.speed" aria-label="Speed selector">
30 <md-option ng-value="speed" flex="1" ng-repeat="speed in vm.speeds track by $index">{{ speed}} 55 <md-option ng-value="speed" flex="1" ng-repeat="speed in vm.speeds track by $index">{{ speed}}
31 </md-option> 56 </md-option>
32 </md-select> 57 </md-select>
33 - <md-button aria-label="Stop playing" ng-click="vm.stopPlay()">  
34 - <ng-md-icon icon="pause_circle_outline"></ng-md-icon> 58 + <md-button class="md-icon-button" aria-label="Stop playing" ng-click="vm.stopPlay()" ng-disabled="!vm.isPlaying">
  59 + <md-icon class="material-icons" ng-style="{'color': vm.isPlaying ? vm.staticSettings.buttonColor : vm.staticSettings.disabledButtonColor}">
  60 + pause_circle_outline
  61 + </md-icon>
35 </md-button> 62 </md-button>
36 - <div class="panel-timer">{{vm.trips[vm.activeTripIndex].timeRange[vm.index].ts | date:'medium'}}  
37 - </div>  
38 </md-slider-container> 63 </md-slider-container>
39 - </div>  
40 - <div class="heat-map-container" layout="column">  
41 - <div flex id='heat-map'></div>  
42 - <div class="heat-map-info-panel" layout="row">  
43 - <md-button aria-label="tooltip" ng-show="vm.staticSettings.displayTooltip" ng-click="vm.showHideTooltip()">  
44 - <ng-md-icon icon="info"></ng-md-icon>  
45 - </md-button>  
46 - <!--<md-button aria-label="settings" ng-click="vm.openHideSettings()">-->  
47 - <!--<ng-md-icon icon="settings_applications"></ng-md-icon>-->  
48 - <!--</md-button>-->  
49 - </div>  
50 - <div class="heat-map-tooltip" class="heat-map-title" layout="column" ng-class="!vm.staticSettings.showTooltip ? 'heat-map-tooltip-hidden':''" ng-bind-html="vm.trips[vm.activeTripIndex].settings.tooltipText"  
51 - ng-style="{'background-color': vm.staticSettings.tooltipColor, 'opacity': vm.staticSettings.tooltipOpacity, 'color': vm.staticSettings.tooltipFontColor}"> 64 + <div class="panel-timer">{{vm.trips[vm.activeTripIndex].timeRange[vm.index].ts | date:'medium'}}
52 </div> 65 </div>
53 </div> 66 </div>
54 -</div>  
  67 +</div>