From a99d0737449ad5f19c8fd6d5d782f43852ff3773 Mon Sep 17 00:00:00 2001 From: Sergey Tarnavskiy Date: Fri, 20 Oct 2017 16:57:44 +0300 Subject: [PATCH] Added new analogue compass widget --- .../widget_bundles/analogue_gauges.json | 16 + ui/src/app/api/widget.service.js | 2 + ui/src/app/widget/lib/analogue-compass.js | 438 ++++++++++++++++++ 3 files changed, 456 insertions(+) create mode 100644 ui/src/app/widget/lib/analogue-compass.js diff --git a/application/src/main/data/json/system/widget_bundles/analogue_gauges.json b/application/src/main/data/json/system/widget_bundles/analogue_gauges.json index 4fc8d89d1d..4ecbc73429 100644 --- a/application/src/main/data/json/system/widget_bundles/analogue_gauges.json +++ b/application/src/main/data/json/system/widget_bundles/analogue_gauges.json @@ -68,6 +68,22 @@ "dataKeySettingsSchema": "{}\n", "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":60,\"startAngle\":67.5,\"ticksAngle\":225,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":-60,\"to\":-50,\"color\":\"#42a5f5\"},{\"from\":-50,\"to\":-40,\"color\":\"rgba(66, 165, 245, 0.83)\"},{\"from\":-40,\"to\":-30,\"color\":\"rgba(66, 165, 245, 0.66)\"},{\"from\":-30,\"to\":-20,\"color\":\"rgba(66, 165, 245, 0.5)\"},{\"from\":-20,\"to\":-10,\"color\":\"rgba(66, 165, 245, 0.33)\"},{\"from\":-10,\"to\":0,\"color\":\"rgba(66, 165, 245, 0.16)\"},{\"from\":0,\"to\":10,\"color\":\"rgba(229, 115, 115, 0.16)\"},{\"from\":10,\"to\":20,\"color\":\"rgba(229, 115, 115, 0.33)\"},{\"from\":20,\"to\":30,\"color\":\"rgba(229, 115, 115, 0.5)\"},{\"from\":30,\"to\":40,\"color\":\"rgba(229, 115, 115, 0.66)\"},{\"from\":40,\"to\":50,\"color\":\"rgba(229, 115, 115, 0.83)\"},{\"from\":50,\"to\":60,\"color\":\"#e57373\"}],\"showUnitTitle\":true,\"colorPlate\":\"#cfd8dc\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"valueDec\":1,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1000,\"animationRule\":\"bounce\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"°C\",\"majorTicksCount\":12,\"numbersFont\":{\"family\":\"Roboto\",\"size\":20,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":30,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"unitTitle\":\"Temperature\",\"minValue\":-60},\"title\":\"Temperature radial gauge - Canvas Gauges\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" } + }, + { + "alias": "analogue_compass", + "name": "Analogue Compass", + "descriptor": { + "type": "latest", + "sizeX": 6, + "sizeY": 5, + "resources": [], + "templateHtml": "", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueCompass(self.ctx, 'compass');\n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueCompass.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n };\n}\n\nself.onDestroy = function() {\n}\n", + "settingsSchema": "{}", + "dataKeySettingsSchema": "{}\n", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"minorTicks\":22,\"needleCircleSize\":15,\"showBorder\":true,\"borderOuterWidth\":10,\"colorPlate\":\"#222\",\"colorMajorTicks\":\"#f5f5f5\",\"colorMinorTicks\":\"#ddd\",\"colorNeedle\":\"#f08080\",\"colorNeedleCircle\":\"#e8e8e8\",\"colorBorder\":\"#ccc\",\"majorTickFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ccc\"},\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"animationTarget\":\"needle\",\"majorTicks\":[\"N\",\"NE\",\"E\",\"SE\",\"S\",\"SW\",\"W\",\"NW\"]},\"title\":\"Analogue Compass\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" + } } ] } \ No newline at end of file diff --git a/ui/src/app/api/widget.service.js b/ui/src/app/api/widget.service.js index 511dc178f8..0df17b74c7 100644 --- a/ui/src/app/api/widget.service.js +++ b/ui/src/app/api/widget.service.js @@ -27,6 +27,7 @@ import thingsboardRpcWidgets from '../widget/lib/rpc'; import TbFlot from '../widget/lib/flot-widget'; import TbAnalogueLinearGauge from '../widget/lib/analogue-linear-gauge'; import TbAnalogueRadialGauge from '../widget/lib/analogue-radial-gauge'; +import TbAnalogueCompass from '../widget/lib/analogue-compass'; import TbCanvasDigitalGauge from '../widget/lib/canvas-digital-gauge'; import TbMapWidget from '../widget/lib/map-widget'; import TbMapWidgetV2 from '../widget/lib/map-widget2'; @@ -57,6 +58,7 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr $window.TbFlot = TbFlot; $window.TbAnalogueLinearGauge = TbAnalogueLinearGauge; $window.TbAnalogueRadialGauge = TbAnalogueRadialGauge; + $window.TbAnalogueCompass = TbAnalogueCompass; $window.TbCanvasDigitalGauge = TbCanvasDigitalGauge; $window.TbMapWidget = TbMapWidget; $window.TbMapWidgetV2 = TbMapWidgetV2; diff --git a/ui/src/app/widget/lib/analogue-compass.js b/ui/src/app/widget/lib/analogue-compass.js new file mode 100644 index 0000000000..a59b0dede0 --- /dev/null +++ b/ui/src/app/widget/lib/analogue-compass.js @@ -0,0 +1,438 @@ +/* + * Copyright © 2016-2017 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import $ from 'jquery'; +import canvasGauges from 'canvas-gauges'; +/*import tinycolor from 'tinycolor2';*/ + +export default class TbAnalogueCompass { + constructor(ctx, canvasId) { + this.ctx = ctx; + + canvasGauges.performance = window.performance; // eslint-disable-line no-undef, angular/window-service + + var gaugeElement = $('#'+canvasId, ctx.$container); + + var settings = ctx.settings; + var majorTicks = (settings.majorTicks && settings.majorTicks.length > 0) ? angular.copy(settings.majorTicks) : ["N","NE","E","SE","S","SW","W","NW"]; + majorTicks.push(majorTicks[0]); + + function getFontFamily(fontSettings) { + var family = fontSettings && fontSettings.family ? fontSettings.family : 'Roboto'; + if (family === 'RobotoDraft') { + family = 'Roboto'; + } + return family; + } + + var gaugeData = { + + renderTo: gaugeElement[0], + + // Generic options + minValue: 0, + maxValue: 360, + majorTicks: majorTicks, + minorTicks: settings.minorTicks || 22, + ticksAngle: 360, + startAngle: 180, + strokeTicks: settings.showStrokeTicks || false, + highlights: false, + valueBox: false, + + //needle + needleCircleSize: settings.needleCircleSize || 15, + needleType: 'line', + needleStart: 75, + needleEnd: 99, + needleWidth: 3, + needleCircleOuter: false, + + //borders + borders: settings.showBorder || false, + borderInnerWidth: 0, + borderMiddleWidth: 0, + borderOuterWidth: settings.borderOuterWidth || 10, + borderShadowWidth: 0, + + //colors + colorPlate: settings.colorPlate || '#222', + colorMajorTicks: settings.colorMajorTicks || '#f5f5f5', + colorMinorTicks: settings.colorMinorTicks || '#ddd', + colorNeedle: settings.colorNeedle || '#f08080', + colorNeedleEnd: settings.colorNeedle || '#f08080', + colorNeedleCircleInner: settings.colorNeedleCircle || '#e8e8e8', + colorNeedleCircleInnerEnd: settings.colorNeedleCircle || '#e8e8e8', + colorBorderOuter: settings.colorBorder || '#ccc', + colorBorderOuterEnd: settings.colorBorder || '#ccc', + colorNeedleShadowDown: "#222", + + //fonts + fontNumbers: getFontFamily(settings.majorTickFont), + fontNumbersSize: settings.majorTickFont && settings.majorTickFont.size ? settings.majorTickFont.size : 20, + fontNumbersStyle: settings.majorTickFont && settings.majorTickFont.style ? settings.majorTickFont.style : 'normal', + fontNumbersWeight: settings.majorTickFont && settings.majorTickFont.weight ? settings.majorTickFont.weight : '500', + colorNumbers: settings.majorTickFont && settings.majorTickFont.color ? settings.majorTickFont.color : '#ccc', + + //animations + animation: settings.animation !== false && !ctx.isMobile, + animationDuration: (angular.isDefined(settings.animationDuration) && settings.animationDuration !== null) ? settings.animationDuration : 500, + animationRule: settings.animationRule || 'cycle', + animationTarget: settings.animationTarget || 'needle' + }; + this.gauge = new canvasGauges.RadialGauge(gaugeData).draw(); + } + + update() { + if (this.ctx.data.length > 0) { + var cellData = this.ctx.data[0]; + if (cellData.data.length > 0) { + var tvPair = cellData.data[cellData.data.length - + 1]; + var value = tvPair[1]; + this.gauge.value = value; + } + } + } + + mobileModeChanged() { + var animation = this.ctx.settings.animation !== false && !this.ctx.isMobile; + this.gauge.update({animation: animation}); + } + + resize() { + this.gauge.update({width: this.ctx.width, height: this.ctx.height}); + } + + static get settingsSchema() { + return { + "schema": { + "type": "object", + "title": "Settings", + "properties": { + "majorTicks": { + "title": "Major ticks names", + "type": "array", + "items": { + "title": "Tick name", + "type": "string" + } + }, + "minorTicks": { + "title": "Minor ticks count", + "type": "number", + "default": 22 + }, + "showStrokeTicks": { + "title": "Show ticks stroke", + "type": "boolean", + "default": false + }, + "needleCircleSize": { + "title": "Needle circle size", + "type": "number", + "default": 15 + }, + "showBorder": { + "title": "Show border", + "type": "boolean", + "default": true + }, + "borderOuterWidth": { + "title": "Border width", + "type": "number", + "default": 10 + }, + "colorPlate": { + "title": "Plate color", + "type": "string", + "default": "#222" + }, + "colorMajorTicks": { + "title": "Major ticks color", + "type": "string", + "default": "#f5f5f5" + }, + "colorMinorTicks": { + "title": "Minor ticks color", + "type": "string", + "default": "#ddd" + }, + "colorNeedle": { + "title": "Needle color", + "type": "string", + "default": "#f08080" + }, + "colorNeedleCircle": { + "title": "Needle circle color", + "type": "string", + "default": "#e8e8e8" + }, + "colorBorder": { + "title": "Border color", + "type": "string", + "default": "#ccc" + }, + "majorTickFont": { + "title": "Major tick font", + "type": "object", + "properties": { + "family": { + "title": "Font family", + "type": "string", + "default": "Roboto" + }, + "size": { + "title": "Size", + "type": "number", + "default": 20 + }, + "style": { + "title": "Style", + "type": "string", + "default": "normal" + }, + "weight": { + "title": "Weight", + "type": "string", + "default": "500" + }, + "color": { + "title": "color", + "type": "string", + "default": "#ccc" + } + } + }, + "animation": { + "title": "Enable animation", + "type": "boolean", + "default": true + }, + "animationDuration": { + "title": "Animation duration", + "type": "number", + "default": 500 + }, + "animationRule": { + "title": "Animation rule", + "type": "string", + "default": "cycle" + }, + "animationTarget": { + "title": "Animation target", + "type": "string", + "default": "needle" + } + }, + "required": [] + }, + "form": [ + { + "key": "majorTicks", + "items":[ + "majorTicks[]" + ] + }, + "minorTicks", + "showStrokeTicks", + "needleCircleSize", + "showBorder", + "borderOuterWidth", + { + "key": "colorPlate", + "type": "color" + }, + { + "key": "colorMajorTicks", + "type": "color" + }, + { + "key": "colorMinorTicks", + "type": "color" + }, + { + "key": "colorNeedle", + "type": "color" + }, + { + "key": "colorNeedleCircle", + "type": "color" + }, + { + "key": "colorBorder", + "type": "color" + }, + { + "key": "majorTickFont", + "items": [ + "majorTickFont.family", + "majorTickFont.size", + { + "key": "majorTickFont.style", + "type": "rc-select", + "multiple": false, + "items": [ + { + "value": "normal", + "label": "Normal" + }, + { + "value": "italic", + "label": "Italic" + }, + { + "value": "oblique", + "label": "Oblique" + } + ] + }, + { + "key": "majorTickFont.weight", + "type": "rc-select", + "multiple": false, + "items": [ + { + "value": "normal", + "label": "Normal" + }, + { + "value": "bold", + "label": "Bold" + }, + { + "value": "bolder", + "label": "Bolder" + }, + { + "value": "lighter", + "label": "Lighter" + }, + { + "value": "100", + "label": "100" + }, + { + "value": "200", + "label": "200" + }, + { + "value": "300", + "label": "300" + }, + { + "value": "400", + "label": "400" + }, + { + "value": "500", + "label": "500" + }, + { + "value": "600", + "label": "600" + }, + { + "value": "700", + "label": "800" + }, + { + "value": "800", + "label": "800" + }, + { + "value": "900", + "label": "900" + } + ] + }, + { + "key": "majorTickFont.color", + "type": "color" + } + ] + }, + "animation", + "animationDuration", + { + "key": "animationRule", + "type": "rc-select", + "multiple": false, + "items": [ + { + "value": "linear", + "label": "Linear" + }, + { + "value": "quad", + "label": "Quad" + }, + { + "value": "quint", + "label": "Quint" + }, + { + "value": "cycle", + "label": "Cycle" + }, + { + "value": "bounce", + "label": "Bounce" + }, + { + "value": "elastic", + "label": "Elastic" + }, + { + "value": "dequad", + "label": "Dequad" + }, + { + "value": "dequint", + "label": "Dequint" + }, + { + "value": "decycle", + "label": "Decycle" + }, + { + "value": "debounce", + "label": "Debounce" + }, + { + "value": "delastic", + "label": "Delastic" + } + ] + }, + { + "key": "animationTarget", + "type": "rc-select", + "multiple": false, + "items": [ + { + "value": "needle", + "label": "Needle" + }, + { + "value": "plate", + "label": "Plate" + } + ] + } + ] + }; + } +}