node-red-contrib-ewelink-cube
Version:
Node-RED integration with eWeLink Cube
195 lines (188 loc) • 6.64 kB
JavaScript
const DIV_HEIGHT = 120;
const DIV_WIDTH = 456;
const HALF_CIRCLE_HEIGHT = 12;
const HALF_CIRCLE_WIDTH = 12;
const HUE_RANGE = 360;
const SATURATION_RANGE = 100;
const VALUE_RANGE = 100;
export const ColorRgb = {
template: `
<div class="card">
<div class="card-header">
<span>{{title}}</span>
<el-switch
v-model="switchValue"
inactive-color="#cccc"
@change="changeSwitch"
:disabled="disabled"
>
</el-switch>
</div>
<div
class="rgb-background-wrap"
@mousedown="mouseDown"
@click="clickRgb"
:class="{ disable: colorRgbDisabled }"
@mousemove="mousemove"
@mouseup="mouseUp"
@mouseleave="mouseleave"
v-if="switchValue"
>
<div
class="trigger-circle"
@click="(e) => e.stopPropagation()"
:style="{
left: circleLeft+'px',
top: circleTop+'px',
width: CIRCLE_WIDTH+'px',
height: CIRCLE_HEIGHT+'px',
}"
></div>
</div>
</div>
`,
props: ['nodeRed', 'state', 'deviceData'],
data() {
return {
title: this.nodeRed._('control-device.label.colorRgb'),
colorRgbValue: 50,
switchValue: false,
defaultValue: { red: 255, green: 0, blue: 0 },
circleLeft: 24,
circleTop: 24,
colorRgbDisabled: false,
canSend: false,
CIRCLE_WIDTH: 24,
CIRCLE_HEIGHT: 24,
disabled: false,
};
},
watch: {
state: {
handler(newVal) {
if (Object.keys(newVal).length === 0) {
this.reset();
}
// power联动
const linkRalation = !this.state.power || ['reverse','off'].includes(this.state.power.powerState);
if (this.hasPower && linkRalation) {
this.disabled = true;
this.switchValue = false;
} else {
this.disabled = false;
}
// 色温颜色互斥
if(this.state['color-temperature']){
this.switchValue = false;
}
// 模式联动
const lightMode = _.get(this.state, ['mode', 'lightMode', 'modeValue'], '');
if(this.hasModeLight && ['whiteLight', 'colorTemperature'].includes(lightMode)){
this.switchValue = false;
this.disabled = true;
}
},
immediate: true,
deep: true,
},
},
computed:{
hasPower(){
if(!this.deviceData || !this.deviceData.capabilities) return false;
return this.deviceData.capabilities.some((item) => item.capability === 'power');
},
hasModeLight(){
if(!this.deviceData || !this.deviceData.capabilities) return false;
return this.deviceData.capabilities.some((item) => item.capability === 'mode' && item.name === 'lightMode');
}
},
methods: {
callBack(state, deleteFlag) {
const data = {
'color-rgb': state,
};
this.$emit('call-back', data, deleteFlag);
},
changeSwitch(value) {
this.colorRgbValue = this.defaultValue;
this.callBack(this.defaultValue, !value);
if(value)this.$emit('call-back', { 'color-temperature': {}}, true);
},
mouseDown() {
this.canSend = true;
},
mousemove(event) {
if (!this.canSend) {
return;
}
this.setDragPosition(event);
this.changeRgb();
},
mouseUp() {
this.canSend = false;
},
mouseleave() {
this.canSend = false;
},
clickRgb(event) {
this.setDragPosition(event);
this.changeRgb();
},
changeRgb() {
const rgbObj = this.position2rgb(this.circleLeft, this.circleTop);
this.callBack(
{
red: Math.round(rgbObj.red),
green: Math.round(rgbObj.green),
blue: Math.round(rgbObj.blue),
},
false
);
},
setDragPosition(event) {
const { offsetX, offsetY } = event;
const { x, y } = this.toCorrectPosition(offsetX, offsetY);
this.circleLeft = x;
this.circleTop = y;
},
position2rgb(x, y) {
const h = (x / DIV_WIDTH) * HUE_RANGE;
const s = (y / DIV_HEIGHT) * SATURATION_RANGE;
const value = VALUE_RANGE;
const [red, green, blue] = hsvToRgb(h, s, value);
return { red, green, blue };
},
rgb2position(red, green, blue) {
const [h, s] = rgbToHsv(red, green, blue);
const x = (h / HUE_RANGE) * DIV_WIDTH;
const y = (s / SATURATION_RANGE) * DIV_HEIGHT;
return this.toCorrectPosition(x, y);
},
toCorrectPosition(x, y) {
y = Math.max(HALF_CIRCLE_HEIGHT, Math.min(DIV_HEIGHT - HALF_CIRCLE_HEIGHT, y));
x = Math.max(HALF_CIRCLE_WIDTH, Math.min(DIV_WIDTH - HALF_CIRCLE_WIDTH, x));
return { x, y };
},
setCirclePosition(rgbObj) {
const { red, green, blue } = rgbObj;
const { x, y } = this.rgb2position(red, green, blue);
this.circleLeft = x;
this.circleTop = y;
},
reset() {
this.switchValue = false;
this.setCirclePosition(this.defaultValue);
},
},
mounted() {
if (!this.state.power && this.hasPower) {
this.switchValue = false;
this.disabled = true;
return;
}
if (this.state['color-rgb']) {
this.switchValue = true;
this.setCirclePosition(this.state['color-rgb']);
}
},
};