mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 22:07:20 +00:00
Sensor Card Fill feature (#4745)
This commit is contained in:
parent
7758ddba56
commit
107f428dd3
@ -27,6 +27,17 @@ import { SensorCardConfig } from "./types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
|
||||
const average = (items): number => {
|
||||
return (
|
||||
items.reduce((sum, entry) => sum + parseFloat(entry.state), 0) /
|
||||
items.length
|
||||
);
|
||||
};
|
||||
|
||||
const lastValue = (items): number => {
|
||||
return parseFloat(items[items.length - 1].state) || 0;
|
||||
};
|
||||
|
||||
const midPoint = (
|
||||
_Ax: number,
|
||||
_Ay: number,
|
||||
@ -69,34 +80,40 @@ const calcPoints = (
|
||||
max: number
|
||||
): number[][] => {
|
||||
const coords = [] as number[][];
|
||||
const margin = 5;
|
||||
const height = 80;
|
||||
width -= 10;
|
||||
let yRatio = (max - min) / height;
|
||||
yRatio = yRatio !== 0 ? yRatio : height;
|
||||
let xRatio = width / (hours - (detail === 1 ? 1 : 0));
|
||||
xRatio = isFinite(xRatio) ? xRatio : width;
|
||||
|
||||
const first = history.filter(Boolean)[0];
|
||||
let last = [average(first), lastValue(first)];
|
||||
|
||||
const getCoords = (item, i, offset = 0, depth = 1) => {
|
||||
if (depth > 1) {
|
||||
return item.forEach((subItem, index) =>
|
||||
getCoords(subItem, i, index, depth - 1)
|
||||
);
|
||||
}
|
||||
const average =
|
||||
item.reduce((sum, entry) => sum + parseFloat(entry.state), 0) /
|
||||
item.length;
|
||||
|
||||
const x = xRatio * (i + offset / 6) + margin;
|
||||
const y = height - (average - min) / yRatio + margin * 2;
|
||||
const x = xRatio * (i + offset / 6);
|
||||
|
||||
if (item) {
|
||||
last = [average(item), lastValue(item)];
|
||||
}
|
||||
const y = height - ((item ? last[0] : last[1]) - min) / yRatio;
|
||||
return coords.push([x, y]);
|
||||
};
|
||||
|
||||
history.forEach((item, i) => getCoords(item, i, 0, detail));
|
||||
if (coords.length === 1) {
|
||||
coords[1] = [width + margin, coords[0][1]];
|
||||
for (let i = 0; i < history.length; i += 1) {
|
||||
getCoords(history[i], i, 0, detail);
|
||||
}
|
||||
|
||||
coords.push([width + margin, coords[coords.length - 1][1]]);
|
||||
if (coords.length === 1) {
|
||||
coords[1] = [width, coords[0][1]];
|
||||
}
|
||||
|
||||
coords.push([width, coords[coords.length - 1][1]]);
|
||||
return coords;
|
||||
};
|
||||
|
||||
@ -227,14 +244,27 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
} else {
|
||||
graph = svg`
|
||||
<svg width="100%" height="100%" viewBox="0 0 500 100">
|
||||
<path
|
||||
d="${this._history}"
|
||||
fill="none"
|
||||
stroke="var(--accent-color)"
|
||||
stroke-width="5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<g>
|
||||
<mask id="fill">
|
||||
<path
|
||||
class='fill'
|
||||
fill='white'
|
||||
d="${this._history} L 500, 100 L 0, 100 z"
|
||||
/>
|
||||
</mask>
|
||||
<rect height="100%" width="100%" id="fill-rect" fill="var(--accent-color)" mask="url(#fill)"></rect>
|
||||
<mask id="line">
|
||||
<path
|
||||
fill="none"
|
||||
stroke="var(--accent-color)"
|
||||
stroke-width="5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d=${this._history}
|
||||
></path>
|
||||
</mask>
|
||||
<rect height="100%" width="100%" id="rect" fill="var(--accent-color)" mask="url(#line)"></rect>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
@ -247,17 +277,15 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
.actionHandler=${actionHandler()}
|
||||
tabindex="0"
|
||||
>
|
||||
<div class="flex">
|
||||
<div class="flex header">
|
||||
<div class="name">
|
||||
<span>${this._config.name || computeStateName(stateObj)}</span>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<ha-icon
|
||||
.icon="${this._config.icon || stateIcon(stateObj)}"
|
||||
></ha-icon>
|
||||
</div>
|
||||
<div class="header">
|
||||
<span class="name"
|
||||
>${this._config.name || computeStateName(stateObj)}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex info">
|
||||
<span id="value">${stateObj.state}</span>
|
||||
@ -355,9 +383,9 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
ha-card:focus {
|
||||
@ -370,6 +398,11 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
.header {
|
||||
margin: 16px 16px 0;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.name {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
@ -377,13 +410,13 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.name {
|
||||
.name > span {
|
||||
display: block;
|
||||
display: -webkit-box;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
max-height: 1.4rem;
|
||||
margin-top: 2px;
|
||||
top: 2px;
|
||||
opacity: 0.8;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@ -405,7 +438,7 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
|
||||
.info {
|
||||
flex-wrap: wrap;
|
||||
margin: 16px 0 16px 8px;
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
#value {
|
||||
@ -432,11 +465,17 @@ class HuiSensorCard extends LitElement implements LovelaceCard {
|
||||
margin-bottom: 0px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.graph > div {
|
||||
align-self: flex-end;
|
||||
margin: auto 8px;
|
||||
margin: auto 0px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fill {
|
||||
opacity: 0.1;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user