Add configurable filter and state_filter to hui-image. (#1423)
* Add configurable filter and state_filter to hui-image. * Rename state -> stateObj. * Cleanup * Remove unnecessary CSS * Use placeholder for broken images. * Update broken image
This commit is contained in:
parent
77c65d43ae
commit
5df758c0b2
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="36" height="36" viewBox="0 0 24 24"><path fill="#505050" d="M19,3A2,2 0 0,1 21,5V11H19V13H19L17,13V15H15V17H13V19H11V21H5C3.89,21 3,20.1 3,19V5A2,2 0 0,1 5,3H19M21,15V19A2,2 0 0,1 19,21H19L15,21V19H17V17H19V15H21M19,8.5A0.5,0.5 0 0,0 18.5,8H5.5A0.5,0.5 0 0,0 5,8.5V15.5A0.5,0.5 0 0,0 5.5,16H11V15H13V13H15V11H17V9H19V8.5Z" /></svg>
|
After Width: | Height: | Size: 571 B |
|
@ -4,9 +4,9 @@ import '@polymer/paper-toggle-button/paper-toggle-button.js';
|
|||
|
||||
import { STATES_OFF } from '../../../common/const.js';
|
||||
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
||||
import isValidObject from '../common/is-valid-object';
|
||||
|
||||
const UPDATE_INTERVAL = 10000;
|
||||
const DEFAULT_FILTER = 'grayscale(100%)';
|
||||
|
||||
/*
|
||||
* @appliesMixin LocalizeMixin
|
||||
|
@ -15,35 +15,33 @@ class HuiImage extends LocalizeMixin(PolymerElement) {
|
|||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.state-off {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
height: auto;
|
||||
transition: filter .2s linear;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.error {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#brokenImage {
|
||||
background: grey url('/static/images/image-broken.svg') center/36px no-repeat;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[_imageSrc]]">
|
||||
<img
|
||||
src="[[_imageSrc]]"
|
||||
on-error="_onImageError"
|
||||
on-load="_onImageLoad"
|
||||
class$="[[_imageClass]]" />
|
||||
</template>
|
||||
<template is="dom-if" if="[[_error]]">
|
||||
<div class="error">[[localize('ui.card.camera.not_available')]]</div>
|
||||
</template>
|
||||
|
||||
<img
|
||||
id="image"
|
||||
src="[[_imageSrc]]"
|
||||
on-error="_onImageError"
|
||||
on-load="_onImageLoad" />
|
||||
<div id="brokenImage"></div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -57,11 +55,8 @@ class HuiImage extends LocalizeMixin(PolymerElement) {
|
|||
image: String,
|
||||
stateImage: Object,
|
||||
cameraImage: String,
|
||||
_error: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
_imageClass: String,
|
||||
filter: String,
|
||||
stateFilter: Object,
|
||||
_imageSrc: String
|
||||
};
|
||||
}
|
||||
|
@ -91,14 +86,16 @@ class HuiImage extends LocalizeMixin(PolymerElement) {
|
|||
}
|
||||
|
||||
_onImageError() {
|
||||
this.setProperties({
|
||||
_imageSrc: null,
|
||||
_error: true
|
||||
});
|
||||
this._imageSrc = null;
|
||||
this.$.image.classList.add('hidden');
|
||||
this.$.brokenImage.style.setProperty('height', `${this._lastImageHeight || '100'}px`);
|
||||
this.$.brokenImage.classList.remove('hidden');
|
||||
}
|
||||
|
||||
_onImageLoad() {
|
||||
this._error = false;
|
||||
this.$.image.classList.remove('hidden');
|
||||
this.$.brokenImage.classList.add('hidden');
|
||||
this._lastImageHeight = this.$.image.offsetHeight;
|
||||
}
|
||||
|
||||
_hassChanged(hass) {
|
||||
|
@ -106,20 +103,36 @@ class HuiImage extends LocalizeMixin(PolymerElement) {
|
|||
return;
|
||||
}
|
||||
|
||||
const state = hass.states[this.entity];
|
||||
const unavailable = !isValidObject(state, ['state']);
|
||||
const stateObj = hass.states[this.entity];
|
||||
const newState = !stateObj ? 'unavailable' : stateObj.state;
|
||||
|
||||
if (newState === this._currentState) return;
|
||||
this._currentState = newState;
|
||||
|
||||
this._updateStateImage();
|
||||
this._updateStateFilter(stateObj);
|
||||
}
|
||||
|
||||
_updateStateImage() {
|
||||
if (!this.stateImage) {
|
||||
this._imageClass = unavailable || STATES_OFF.includes(state.state) ? 'state-off' : '';
|
||||
this._imageFallback = true;
|
||||
return;
|
||||
}
|
||||
const stateImg = this.stateImage[this._currentState];
|
||||
this._imageSrc = stateImg || this.image;
|
||||
this._imageFallback = !stateImg;
|
||||
}
|
||||
|
||||
const stateImg = !unavailable ? this.stateImage[state.state] : this.stateImage.unavailable;
|
||||
_updateStateFilter(stateObj) {
|
||||
let filter;
|
||||
if (!this.stateFilter) {
|
||||
filter = this.filter;
|
||||
} else {
|
||||
filter = this.stateFilter[this._currentState] || this.filter;
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
_imageClass: !stateImg && (unavailable || STATES_OFF.includes(state.state)) ? 'state-off' : '',
|
||||
_imageSrc: stateImg || this.image
|
||||
});
|
||||
const isOff = !stateObj || STATES_OFF.includes(stateObj.state);
|
||||
this.$.image.style.filter = filter || (isOff && this._imageFallback && DEFAULT_FILTER) || '';
|
||||
}
|
||||
|
||||
_updateCameraImageSrc() {
|
||||
|
@ -128,17 +141,12 @@ class HuiImage extends LocalizeMixin(PolymerElement) {
|
|||
entity_id: this.cameraImage,
|
||||
}).then((resp) => {
|
||||
if (resp.success) {
|
||||
this.setProperties({
|
||||
_imageSrc: `data:${resp.result.content_type};base64, ${resp.result.content}`,
|
||||
_error: false
|
||||
});
|
||||
this._imageSrc = `data:${resp.result.content_type};base64, ${resp.result.content}`;
|
||||
this._onImageLoad();
|
||||
} else {
|
||||
this.setProperties({
|
||||
_imageSrc: null,
|
||||
_error: true
|
||||
});
|
||||
this._onImageError();
|
||||
}
|
||||
});
|
||||
}, () => this._onImageError());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue