Browse Source

TB-70: Control knob widget.

pull/211/head
Igor Kulikov 9 years ago
parent
commit
64385b019e
  1. 6
      application/src/main/data/json/system/widget_bundles/control_widgets.json
  2. 19
      ui/src/app/widget/lib/CanvasDigitalGauge.js
  3. BIN
      ui/src/app/widget/lib/rpc/knob.png
  4. 32
      ui/src/app/widget/lib/rpc/knob.svg
  5. 27
      ui/src/app/widget/lib/rpc/shiny-knob.directive.js
  6. 52
      ui/src/app/widget/lib/rpc/shiny-knob.scss
  7. 9
      ui/src/app/widget/lib/rpc/shiny-knob.tpl.html

6
application/src/main/data/json/system/widget_bundles/control_widgets.json

@ -42,11 +42,11 @@
"name": "Shiny Knob Control",
"descriptor": {
"type": "rpc",
"sizeX": 2.5,
"sizeY": 3,
"sizeX": 4,
"sizeY": 3.5,
"resources": [],
"templateHtml": "<tb-shiny-knob ctx='ctx'></tb-shiny-knob>",
"templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.switch-panel {\n margin: 0;\n height: 32px;\n width: 66px;\n min-width: 66px;\n}\n\n.switch-panel md-switch {\n margin: 0;\n width: 36px;\n min-width: 36px;\n}\n\n.switch-panel md-switch > div.md-container {\n margin: 0;\n}\n\n.switch-panel.col-0 md-switch {\n padding-left: 8px;\n padding-right: 4px;\n}\n\n.switch-panel.col-1 md-switch {\n padding-left: 4px;\n padding-right: 8px;\n}\n\n.gpio-row {\n height: 32px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"theme\": {\n \"title\": \"Knob theme\",\n \"type\": \"string\",\n \"default\": \"light\"\n }, \n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"minValue\", \"maxValue\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n {\n \"key\": \"theme\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"light\",\n \"label\": \"Light\"\n },\n {\n \"value\": \"dark\",\n \"label\": \"Dark\"\n }\n ]\n },\n \"requestTimeout\"\n ]\n}",
"dataKeySettingsSchema": "{}\n",

19
ui/src/app/widget/lib/CanvasDigitalGauge.js

@ -238,6 +238,21 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge {
return this;
}
getValueColor() {
if (this.contextProgressClone) {
var color = this.contextProgressClone.currentColor;
if (!color) {
if (this.options.neonGlowBrightness) {
color = getProgressColor(0, this.options.neonColorsRange);
} else {
color = getProgressColor(0, this.options.colorsRange);
}
}
return color;
} else {
return '#000';
}
}
}
/* eslint-disable angular/document-service */
@ -666,9 +681,9 @@ function drawBarGlow(context, startX, startY, endX, endY, color, strokeWidth, is
function drawProgress(context, options, progress) {
var neonColor;
if (options.neonGlowBrightness) {
neonColor = getProgressColor(progress, options.neonColorsRange);
context.currentColor = neonColor = getProgressColor(progress, options.neonColorsRange);
} else {
context.strokeStyle = getProgressColor(progress, options.colorsRange);
context.currentColor = context.strokeStyle = getProgressColor(progress, options.colorsRange);
}
let {barLeft, barRight, barTop, baseX, width, barBottom, Cx, Cy, Rm, Ro, Ri, strokeWidth} =

BIN
ui/src/app/widget/lib/rpc/knob.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

32
ui/src/app/widget/lib/rpc/knob.svg

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg id="svg52850" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="28.222mm" width="28.222mm" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 99.999997 99.999997" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs id="defs52852">
<radialGradient id="radialGradient52746-69" xlink:href="#linearGradient53063" gradientUnits="userSpaceOnUse" cy="990.69" cx="1006.1" gradientTransform="matrix(.0028197 -2.0966 3.8027 .0051141 -2863.2 3472.2)" r="86.621"/>
<linearGradient id="linearGradient53063">
<stop id="stop53065" stop-color="#b5b5b5" offset="0"/>
<stop id="stop53067" stop-color="#f5f5f5" offset="1"/>
</linearGradient>
<radialGradient id="radialGradient52746-69-7-0" gradientUnits="userSpaceOnUse" cy="990.69" cx="1006.1" gradientTransform="matrix(.0016764 -1.2465 2.2609 .0030406 -3150 20.652)" r="86.621">
<stop id="stop53119" stop-color="#808080" offset="0"/>
<stop id="stop53121" stop-color="#fdfdfd" offset="1"/>
</radialGradient>
<radialGradient id="radialGradient52746-69-7" xlink:href="#linearGradient53063" gradientUnits="userSpaceOnUse" cy="990.69" cx="1006.1" gradientTransform="matrix(.0016276 -1.2102 2.195 .002952 -3084.7 -17.281)" r="86.621"/>
</defs>
<metadata id="metadata52855">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="layer1" transform="translate(-330.69 -606.32)">
<g id="g53154" transform="matrix(.40816 -.40816 .40816 .40816 -513.05 503.76)">
<circle id="path52738-5" cy="1281.7" cx="907.94" r="86.621" fill="url(#radialGradient52746-69)"/>
<circle id="path52738-5-3-6" transform="scale(-1)" cy="-1281.7" cx="-907.94" r="51.5" fill="url(#radialGradient52746-69-7-0)"/>
<circle id="path52738-5-3" transform="scale(-1)" cy="-1281.7" cx="-907.94" r="50" fill="url(#radialGradient52746-69-7)"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

27
ui/src/app/widget/lib/rpc/shiny-knob.directive.js

@ -17,7 +17,6 @@
import './shiny-knob.scss';
import CanvasDigitalGauge from './../CanvasDigitalGauge';
//import tinycolor from 'tinycolor2';
/* eslint-disable import/no-unresolved, import/default */
@ -53,7 +52,11 @@ function ShinyKnobController($element, $scope, $document) {
var knob = angular.element('.knob', $element),
knobContainer = angular.element('#knob-container', $element),
knobTop = knob.find('.top'),
// knobTop = knob.find('.top'),
knobTopPointerContainer = knob.find('.top-pointer-container'),
knobTopPointer = knob.find('.top-pointer'),
knobValueBackground = knob.find('.value-background'),
knobValue = knob.find('.knob-value'),
startDeg = -1,
currentDeg = 0,
rotation = 0,
@ -61,7 +64,7 @@ function ShinyKnobController($element, $scope, $document) {
var canvasBarElement = angular.element('#canvasBar', $element);
var levelColors = ['rgb(0, 128, 0)', 'rgb(251, 192, 45)', 'rgb(244, 67, 54)'];
var levelColors = ['rgb(0, 128, 0)', 'rgb(251, 192, 45)', 'rgb(255, 0, 0)'];//['cyan'];//
var canvasBar;
$scope.$watch('vm.ctx', () => {
@ -80,14 +83,14 @@ function ShinyKnobController($element, $scope, $document) {
var canvasBarData = {
renderTo: canvasBarElement[0],
hideValue: true,
neonGlowBrightness: vm.darkTheme ? 40 : 0,
gaugeWidthScale: 0.5,
gaugeColor: vm.darkTheme ? 'rgb(23, 26, 28)' : 'rgba(0,0,0,0)',
neonGlowBrightness: 40,//40,//vm.darkTheme ? 40 : 0,
gaugeWidthScale: 0.2,
gaugeColor: vm.darkTheme ? 'rgb(23, 26, 28)' : 'rgba(0, 0, 0, 0.75)',
levelColors: levelColors,
minValue: vm.minValue,
maxValue: vm.maxValue,
gaugeType: 'donut',
dashThickness: 1.5,
dashThickness: 0,//1.5,
donutStartAngle: Math.PI,
animation: false,
animationDuration: 250,
@ -141,7 +144,7 @@ function ShinyKnobController($element, $scope, $document) {
currentDeg = tmp;
lastDeg = tmp;
knobTop.css('transform','rotate('+(currentDeg)+'deg)');
knobTopPointerContainer.css('transform','rotate('+(currentDeg)+'deg)');
turn(currentDeg/359);
});
@ -168,6 +171,8 @@ function ShinyKnobController($element, $scope, $document) {
var size = Math.min(width, height);
knob.css({width: size, height: size});
canvasBar.update({width: size, height: size});
var valHeight = knobValueBackground.height()/3.3;
knobValue.css({'fontSize': valHeight+'px', 'lineHeight': valHeight+'px'});
}
function turn(ratio) {
@ -175,16 +180,20 @@ function ShinyKnobController($element, $scope, $document) {
if (canvasBar.value != value) {
canvasBar.value = value;
}
knobTopPointer.css({'backgroundColor': canvasBar.getValueColor()});
knobValue.css({'color': 'cyan'});//canvasBar.getValueColor()});
onValue(value);
}
function setValue(value) {
var ratio = (value-vm.minValue) / (vm.maxValue - vm.minValue);
rotation = lastDeg = currentDeg = ratio*360;
knobTop.css('transform','rotate('+(currentDeg)+'deg)');
knobTopPointerContainer.css('transform','rotate('+(currentDeg)+'deg)');
if (canvasBar.value != value) {
canvasBar.value = value;
}
knobTopPointer.css({'backgroundColor': canvasBar.getValueColor()});
knobValue.css({'color': 'cyan'});//canvasBar.getValueColor()});
vm.value = value;
}

52
ui/src/app/widget/lib/rpc/shiny-knob.scss

@ -14,10 +14,11 @@
* limitations under the License.
*/
$knob-img: url('./knob.png');
$knob-img: url('./knob.svg');
$bars-margin-pct: percentage(0.2);
$shadow-size: 5;
$bars-margin-pct: percentage(0.08);
$value-background-margin-pct: percentage(0.30);
$shadow-size: 0;
$shadow-size-px: $shadow-size+px;
$shadow-offset-px: $shadow-size/2+px;
@ -25,7 +26,7 @@ $shadow-offset-px: $shadow-size/2+px;
width:100%;
height:100%;
&.dark {
background: #000;//$dark-bg-img #1f2129;
background: #000;
}
.knob {
@ -42,30 +43,51 @@ $shadow-offset-px: $shadow-size/2+px;
bottom: 0;
right: 0;
}
.top{
.value-background {
position:absolute;
top: $value-background-margin-pct;
left: $value-background-margin-pct;
bottom: $value-background-margin-pct;
right: $value-background-margin-pct;
border-radius: 50%;
background: #000;
color: #fff;
font-weight: 500;
z-index:4;
}
.top-pointer-container {
position:absolute;
top: calc(#{$bars-margin-pct} - #{$shadow-offset-px});
left: $bars-margin-pct;
bottom: calc(#{$bars-margin-pct} + #{$shadow-offset-px});
right: $bars-margin-pct;
background:$knob-img no-repeat;
background-size: contain;
z-index:10;
z-index:3;
cursor:default !important;
&:after {
.top-pointer {
content:'';
width:10px;
height:10px;
background-color:#666;
width:5%;
height:5%;
background-color:#b5b5b5;
position:absolute;
top:50%;
left:10px;
margin-top:-5px;
left:5%;
margin-top:-2.5%;
border-radius: 50%;
cursor:default !important;
box-shadow: 0 0 1px #5a5a5a inset;
box-shadow: 1px 0 2px #040404;
}
}
.top{
position:absolute;
top: calc(#{$bars-margin-pct} - #{$shadow-offset-px});
left: $bars-margin-pct;
bottom: calc(#{$bars-margin-pct} + #{$shadow-offset-px});
right: $bars-margin-pct;
background:$knob-img no-repeat;
background-size: contain;
z-index:2;
cursor:default !important;
}
.base{
top: calc(#{$bars-margin-pct} - #{$shadow-offset-px});
left: $bars-margin-pct;

9
ui/src/app/widget/lib/rpc/shiny-knob.tpl.html

@ -17,12 +17,15 @@
-->
<div class="tb-shiny-knob" layout="column" ng-class="{'dark': vm.darkTheme}">
<div layout="row" layout-align="center start" class="md-padding">
<span>{{ vm.value }}</span>
</div>
<div id="knob-container" flex layout="column" layout-align="center center">
<div class="knob">
<div class="value-background" layout="row" layout-align="center center">
<span class="knob-value">{{ vm.value }}</span>
</div>
<canvas id="canvasBar"></canvas>
<div class="top-pointer-container">
<div class="top-pointer"></div>
</div>
<div class="top"></div>
<div class="base"></div>
</div>

Loading…
Cancel
Save