8 changed files with 359 additions and 6 deletions
@ -0,0 +1,21 @@ |
|||
/* |
|||
* 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 tbShinyKnob from './shiny-knob.directive'; |
|||
|
|||
export default angular.module('thingsboard.widgets.rpc', [ |
|||
tbShinyKnob |
|||
]).name; |
|||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,198 @@ |
|||
/* |
|||
* 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 './shiny-knob.scss'; |
|||
|
|||
import CanvasDigitalGauge from './../CanvasDigitalGauge'; |
|||
//import tinycolor from 'tinycolor2';
|
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import shinyKnobTemplate from './shiny-knob.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
export default angular.module('thingsboard.widgets.rpc.shinyKnob', []) |
|||
.directive('tbShinyKnob', ShinyKnob) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function ShinyKnob() { |
|||
return { |
|||
restrict: "E", |
|||
scope: true, |
|||
bindToController: { |
|||
ctx: '=' |
|||
}, |
|||
controller: ShinyKnobController, |
|||
controllerAs: 'vm', |
|||
templateUrl: shinyKnobTemplate |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function ShinyKnobController($element, $scope, $document) { |
|||
let vm = this; |
|||
|
|||
vm.value = 0; |
|||
|
|||
var snap = 0; |
|||
|
|||
var knob = angular.element('.knob', $element), |
|||
knobContainer = angular.element('#knob-container', $element), |
|||
knobTop = knob.find('.top'), |
|||
startDeg = -1, |
|||
currentDeg = 0, |
|||
rotation = 0, |
|||
lastDeg = 0; |
|||
|
|||
var canvasBarElement = angular.element('#canvasBar', $element); |
|||
|
|||
var levelColors = ['rgb(0, 128, 0)', 'rgb(251, 192, 45)', 'rgb(244, 67, 54)']; |
|||
var canvasBar; |
|||
|
|||
$scope.$watch('vm.ctx', () => { |
|||
if (vm.ctx) { |
|||
init(); |
|||
} |
|||
}); |
|||
|
|||
function init() { |
|||
|
|||
vm.minValue = angular.isDefined(vm.ctx.settings.minValue) ? vm.ctx.settings.minValue : 0; |
|||
vm.maxValue = angular.isDefined(vm.ctx.settings.maxValue) ? vm.ctx.settings.maxValue : 100; |
|||
|
|||
vm.darkTheme = vm.ctx.settings.theme == 'dark'; |
|||
|
|||
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)', |
|||
levelColors: levelColors, |
|||
minValue: vm.minValue, |
|||
maxValue: vm.maxValue, |
|||
gaugeType: 'donut', |
|||
dashThickness: 1.5, |
|||
donutStartAngle: Math.PI, |
|||
animation: false, |
|||
animationDuration: 250, |
|||
animationRule: 'linear' |
|||
}; |
|||
|
|||
canvasBar = new CanvasDigitalGauge(canvasBarData).draw(); |
|||
|
|||
knob.on('mousedown touchstart', (e) => { |
|||
e.preventDefault(); |
|||
var offset = knob.offset(); |
|||
var center = { |
|||
y : offset.top + knob.height()/2, |
|||
x: offset.left + knob.width()/2 |
|||
}; |
|||
|
|||
var a, b, deg, tmp, |
|||
rad2deg = 180/Math.PI; |
|||
|
|||
knob.on('mousemove.rem touchmove.rem', (e) => { |
|||
|
|||
e = (e.originalEvent.touches) ? e.originalEvent.touches[0] : e; |
|||
|
|||
a = center.y - e.pageY; |
|||
b = center.x - e.pageX; |
|||
deg = Math.atan2(a,b)*rad2deg; |
|||
|
|||
if(deg<0){ |
|||
deg = 360 + deg; |
|||
} |
|||
|
|||
if(startDeg == -1){ |
|||
startDeg = deg; |
|||
} |
|||
|
|||
tmp = Math.floor((deg-startDeg) + rotation); |
|||
|
|||
if(tmp < 0){ |
|||
tmp = 360 + tmp; |
|||
} |
|||
else if(tmp > 359){ |
|||
tmp = tmp % 360; |
|||
} |
|||
|
|||
if(snap && tmp < snap){ |
|||
tmp = 0; |
|||
} |
|||
if(Math.abs(tmp - lastDeg) > 180){ |
|||
return false; |
|||
} |
|||
currentDeg = tmp; |
|||
lastDeg = tmp; |
|||
|
|||
knobTop.css('transform','rotate('+(currentDeg)+'deg)'); |
|||
turn(currentDeg/359); |
|||
}); |
|||
|
|||
$document.on('mouseup.rem touchend.rem',() => { |
|||
knob.off('.rem'); |
|||
$document.off('.rem'); |
|||
rotation = currentDeg; |
|||
startDeg = -1; |
|||
}); |
|||
|
|||
}); |
|||
|
|||
vm.ctx.resize = resize; |
|||
resize(); |
|||
|
|||
var initialValue = angular.isDefined(vm.ctx.settings.initialValue) ? vm.ctx.settings.initialValue : vm.minValue; |
|||
|
|||
setValue(initialValue); |
|||
} |
|||
|
|||
function resize() { |
|||
var width = knobContainer.width(); |
|||
var height = knobContainer.height(); |
|||
var size = Math.min(width, height); |
|||
knob.css({width: size, height: size}); |
|||
canvasBar.update({width: size, height: size}); |
|||
} |
|||
|
|||
function turn(ratio) { |
|||
var value = (vm.minValue + (vm.maxValue - vm.minValue)*ratio).toFixed(2); |
|||
if (canvasBar.value != value) { |
|||
canvasBar.value = value; |
|||
} |
|||
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)'); |
|||
if (canvasBar.value != value) { |
|||
canvasBar.value = value; |
|||
} |
|||
vm.value = value; |
|||
} |
|||
|
|||
function onValue(value) { |
|||
console.log(`onValue ${value}`); //eslint-disable-line
|
|||
$scope.$applyAsync(() => { |
|||
vm.value = value; |
|||
}); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
/** |
|||
* 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. |
|||
*/ |
|||
|
|||
$knob-img: url('./knob.png'); |
|||
|
|||
$bars-margin-pct: percentage(0.2); |
|||
$shadow-size: 5; |
|||
$shadow-size-px: $shadow-size+px; |
|||
$shadow-offset-px: $shadow-size/2+px; |
|||
|
|||
.tb-shiny-knob { |
|||
width:100%; |
|||
height:100%; |
|||
&.dark { |
|||
background: #000;//$dark-bg-img #1f2129; |
|||
} |
|||
|
|||
.knob { |
|||
position: relative; |
|||
&[draggable] { |
|||
-moz-user-select: none; |
|||
-webkit-user-select: none; |
|||
user-select: none; |
|||
} |
|||
#canvasBar { |
|||
position:absolute; |
|||
top:0; |
|||
left:0; |
|||
bottom: 0; |
|||
right: 0; |
|||
} |
|||
.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:10; |
|||
cursor:default !important; |
|||
&:after { |
|||
content:''; |
|||
width:10px; |
|||
height:10px; |
|||
background-color:#666; |
|||
position:absolute; |
|||
top:50%; |
|||
left:10px; |
|||
margin-top:-5px; |
|||
border-radius: 50%; |
|||
cursor:default !important; |
|||
box-shadow: 0 0 1px #5a5a5a inset; |
|||
} |
|||
} |
|||
.base{ |
|||
top: calc(#{$bars-margin-pct} - #{$shadow-offset-px}); |
|||
left: $bars-margin-pct; |
|||
bottom: calc(#{$bars-margin-pct} + #{$shadow-offset-px}); |
|||
right: $bars-margin-pct; |
|||
border-radius:50%; |
|||
box-shadow:0 $shadow-size-px 0 #4a5056,$shadow-size-px $shadow-size-px $shadow-size-px #000; |
|||
position:absolute; |
|||
z-index:1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
<!-- |
|||
|
|||
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. |
|||
|
|||
--> |
|||
|
|||
<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"> |
|||
<canvas id="canvasBar"></canvas> |
|||
<div class="top"></div> |
|||
<div class="base"></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
Loading…
Reference in new issue