mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 07:16:39 +00:00
Use hue, saturation and a brightness filter for state badge (#1021)
* Use hue and saturation values. Use css filter for brightness. * Assign style properties at once. * label => if else logic
This commit is contained in:
parent
6ee9808d42
commit
796ec4a4b0
@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
ha-state-icon {
|
||||
transition: color .3s ease-in-out;
|
||||
transition: color .3s ease-in-out, filter .3s ease-in-out;
|
||||
}
|
||||
|
||||
/* Color the icon if light or sun is on */
|
||||
@ -52,7 +52,7 @@ class StateBadge extends Polymer.Element {
|
||||
return {
|
||||
stateObj: {
|
||||
type: Object,
|
||||
observer: 'updateIconColor',
|
||||
observer: 'updateIconAppearance',
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -61,80 +61,35 @@ class StateBadge extends Polymer.Element {
|
||||
return window.hassUtil.computeDomain(stateObj);
|
||||
}
|
||||
|
||||
_rgbFromBrightness(brightness) {
|
||||
// Set icon bbroghtness to a scale between 15% bright to 100% bright.
|
||||
const iconBrightness = (brightness + 45) / (255 + 45);
|
||||
const hostBrightness = 1 - iconBrightness;
|
||||
const re = /rgb\((\d+), (\d+), (\d+)\)/;
|
||||
const rgbIconMatch = window.getComputedStyle(this.$.icon).color.match(re);
|
||||
const rgbHostMatch = window.getComputedStyle(this).color.match(re);
|
||||
let rgb;
|
||||
if (rgbIconMatch && rgbHostMatch) {
|
||||
const rgbIcon = rgbIconMatch.slice(1).map(v => Number.parseInt(v, 10));
|
||||
const rgbHost = rgbHostMatch.slice(1).map(v => Number.parseInt(v, 10));
|
||||
rgb = [
|
||||
Math.round((rgbIcon[0] * iconBrightness) + (rgbHost[0] * hostBrightness)),
|
||||
Math.round((rgbIcon[1] * iconBrightness) + (rgbHost[1] * hostBrightness)),
|
||||
Math.round((rgbIcon[2] * iconBrightness) + (rgbHost[2] * hostBrightness)),
|
||||
];
|
||||
if (rgb.some(v => Number.isNaN(v))) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an attribute changes that influences the color of the icon.
|
||||
*/
|
||||
updateIconColor(newVal) {
|
||||
const icon = this.$.icon;
|
||||
updateIconAppearance(newVal) {
|
||||
const iconStyle = {
|
||||
display: 'inline',
|
||||
color: '',
|
||||
filter: '',
|
||||
};
|
||||
const hostStyle = {
|
||||
backgroundImage: '',
|
||||
};
|
||||
// hide icon if we have entity picture
|
||||
if (newVal.attributes.entity_picture) {
|
||||
this.style.backgroundImage = 'url(' + newVal.attributes.entity_picture + ')';
|
||||
icon.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._timeoutId) {
|
||||
window.clearTimeout(this._timeoutId);
|
||||
this._timeoutId = null;
|
||||
}
|
||||
|
||||
this.style.backgroundImage = '';
|
||||
icon.style.display = 'inline';
|
||||
if (newVal.state === 'unavailable') return;
|
||||
let rgb;
|
||||
let oldColor;
|
||||
if (newVal.attributes.rgb_color) {
|
||||
rgb = newVal.attributes.rgb_color;
|
||||
} else if (newVal.attributes.brightness && newVal.attributes.brightness !== 255) {
|
||||
if (icon.style.color !== '') {
|
||||
oldColor = icon.style.color;
|
||||
icon.style.transition = 'none';
|
||||
icon.style.color = '';
|
||||
}
|
||||
rgb = this._rgbFromBrightness(newVal.attributes.brightness);
|
||||
}
|
||||
// Set color of icon to rgb color if available and it is not very white (sum rgb colors < 730)
|
||||
if (rgb && rgb.reduce((cur, tot) => cur + tot, 0) < 730) {
|
||||
if (oldColor) {
|
||||
icon.style.color = oldColor;
|
||||
}
|
||||
// If we had to cancel transition - wait after restoring old color so transition will start
|
||||
// from oldColor and not from css 'on' color.
|
||||
if (icon.style.transition && oldColor) {
|
||||
this._timeoutId = window.setTimeout(() => {
|
||||
icon.style.transition = '';
|
||||
icon.style.color = 'rgb(' + rgb.join(',') + ')';
|
||||
}, 10);
|
||||
hostStyle.backgroundImage = 'url(' + newVal.attributes.entity_picture + ')';
|
||||
iconStyle.display = 'none';
|
||||
} else {
|
||||
icon.style.color = 'rgb(' + rgb.join(',') + ')';
|
||||
if (newVal.attributes.hs_color) {
|
||||
const hue = newVal.attributes.hs_color[0];
|
||||
const sat = newVal.attributes.hs_color[1];
|
||||
if (sat > 10) iconStyle.color = `hsl(${hue}, 100%, ${100 - (sat / 2)}%)`;
|
||||
}
|
||||
} else {
|
||||
icon.style.color = '';
|
||||
if (newVal.attributes.brightness) {
|
||||
const brightness = newVal.attributes.brightness;
|
||||
// lowest brighntess will be around 50% (that's pretty dark)
|
||||
iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`;
|
||||
}
|
||||
}
|
||||
Object.assign(this.$.icon.style, iconStyle);
|
||||
Object.assign(this.style, hostStyle);
|
||||
}
|
||||
}
|
||||
customElements.define(StateBadge.is, StateBadge);
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user