I know that the bar chart has been asked for before, but I can’t quite find an answer.
I have figured out how to make gauge charts using oh-data-series, and I know that pie charts are also available. Since I consider a bar chart to be pretty much the most basic “chart”, I didn’t think to check if it was actually available.
My plan was to combine SVG components and a single bar to make a thermometer. I’ve done most of the SVG work (the scale is just an example and was meant to be drawn by the bar chart so that it could be changed/scaled):
(the SVG isn’t shown correctly here for some reason, but that’s not relevant to the issue - it works correctly as a widget)
But, to my surprise, when I tried to add the bar chart component, nothing happens - and when looking up oh-data-series it seems like only gauge and pie are available.
I know that there’s a question of size as to how much of ECharts to “embed” with OH, but as far as I can understand, bar, line, heatmap and scatter are already used in the “Charts type” Page. So, why aren’t these also available for “general” use via oh-data-series? Is it because only parts of these “components” are included?
There might be a way to use what’s already here for my simple need, but I can’t seem to figure it out. The charts pages seem to be “bound” to time series, and I don’t want a “grid”. I just want a single bar.
Actually, I could easily enough implement the “bar” itself using an SVG rect. What I really don’t want to make is the (y) scale, with all the lines and the labels. I’m pretty sure that you can configure an EChartsbar component to draw this pretty easily.
Are there any ways to achieve what I’m trying to do?
If you already have the rest of the widget constructed out of svg components, what benefit do you get from incorporating the chart for this? For a thermometer, you only need one value which presumably is already stored in an item if you are also getting that information from a chart, and you can just use that item value to scale an appropriate object within the svg.
I want the chart to draw the y-axis scale. I don’t want a fixed scale, but one with configurable min/max and which supports both Celsius and Fahrenheit. It would also be very convenient to not have to align the “bar value” with the axis scale myself (if the chart draws the bar, it’s already aligned).
edit: to clarify: The Celsius scale in the SVG at this time is just to “populate” it to see how it would look - it was never intended to be used (I just copied it from somewhere).
Thanks, but it seems that this widget uses oh-aggregate-series. I don’t know how that works, but I guess that if I only give it one piece of data, the “average” would equal the data. It might be workable, but I was ideally looking to use oh-data-series.
It also uses a “grid”, like the “Pages” does - but I’ll have to play with it to see how much I can “tweak” it. But, this is a good start for some experimentation
It seems to me like oh-aggregate-series is fundamentally unsuitable for this because it is based on persisted data, not on current data. Whatever I try, it wants to show the persisted data for some period. I just want to show the current Item value - regardless of if the Item is stored in persistence or not.
I can’t find a way to make this work. As can be seen by this test:
uid: widget_test_bar
tags:
- gauge
- temperature
props:
parameters:
- context: item
description: The current value
label: Item
name: item
required: true
type: TEXT
- context: number
description: The min range value
label: MinRange
name: minRange
required: false
type: TEXT
- context: number
description: The max range value
label: MaxRange
name: maxRange
required: false
type: TEXT
- context: number
description: The min value
label: Min
name: min
required: false
type: TEXT
- context: number
description: The max value
label: Max
name: max
required: false
type: TEXT
- context: string
description: The name
label: Name
name: name
required: false
type: TEXT
- context: number
description: The height of widget
label: Height
name: height
required: false
type: TEXT
parameterGroups: []
timestamp: Dec 19, 2024, 6:16:17 PM
component: oh-chart
config:
chartType: isoWeek
height: =props.height
periodVisible: false
slots:
series:
- component: oh-aggregate-series
config:
aggregationFunction: max
backgroundStyle:
borderRadius:
- 50
- 50
- 50
- 50
color:
colorStops:
- color: yellow
offset: 0
- color: white
offset: 1
type: linear
x: 0
x2: 0
y: 0
y2: 1
dimension1: minute
gridIndex: 00
item: =props.item
itemStyle:
showBackground: false
type: bar
xAxisIndex: 0
yAxisIndex: 0
data:
- name: 1
value: 30
tooltip:
- component: oh-chart-tooltip
config:
orient: vertical
show: true
trigger: axis
xAxis:
- component: oh-value-axis
config:
axisLabel:
color: red
show: true
axisLine:
show: true
axisPointer:
show: true
axisTick:
interval: 1
lineStyle:
opacity: 1
show: true
gridIndex: 0
min: 1
max: 1
nameTextStyle:
color: green
show: true
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
inverse: false
max: 30
min: -30
show: true
splitNumber: 10
axisTick:
length: 40
minorTick:
show: true
length: 20
axisLabel:
show: true
margin: 23
align: right
verticalAlign: bottom
…the bar chart can be used to draw a quite reasonable axis scale (that can be changed to fit the user need). But, I can’t get the “bar” itself to show anything meaningful. I suspect that there is some “hardcoding” in oh-aggregate-series that overrides whatever data I try to set. I can probably hide everything except the axis scale, and as such use ECharts only to create the axis scale.
But, I can’t imagine how I would go about aligning the scale with the SVG coordinates, so that I could draw the “mercury”/bar with an SVG rectangle. I wouldn’t even know where to begin to try to achieve this, as far as I know, there’s no access to any form of “coordinates” output by ECharts. I could just manually place them so that they align, but it would never work when changing min/max, when the widget is scaled etc.
So, as far as I can tell, this is a dead-end without the ability to use oh-data-series and bar together.
It draws nothing for me. I’m still on 4.2.3 if there has been any changes to this in 4.3.0. Are you sure you pasted the same version that drew your screenshot?
edit: This probably does nothing here, since this is probably one of your Items: OneCallAPIweatherandforecast_Current_Temperature. I’ll try and replace that with a valid Item
After looking a bit at the code, it seems that it’s as I thought, that bar, line etc. are also imported:
They are just not made available for oh-data-series:
I don’t know if there’s more that’s needed to make line, bar etc. available from the “data-series”, but if it’s only a question of specifying them as seriesTypeParameter, then I think it should be done.
It seems like I’m getting closer to what I want to do now:
uid: widget_test_bar
tags:
- bar
- temperature
props:
parameters:
- context: item
description: The current value
label: Item
name: item
required: true
type: TEXT
- context: number
description: The min range value
label: MinRange
name: minRange
required: false
type: TEXT
- context: number
description: The max range value
label: MaxRange
name: maxRange
required: false
type: TEXT
- context: number
description: The min value
label: Min
name: min
required: false
type: TEXT
- context: number
description: The max value
label: Max
name: max
required: false
type: TEXT
- context: string
description: The name
label: Name
name: name
required: false
type: TEXT
- context: number
description: The height of widget
label: Height
name: height
required: false
type: TEXT
parameterGroups: []
timestamp: Dec 19, 2024, 11:17:53 PM
component: oh-chart
config:
chartType: day
height: =props.height
periodVisible: false
slots:
grid:
- component: oh-chart-grid
config:
#left: -90
borderWidth: 0
includeLabels: false
width: 10
series:
- component: oh-aggregate-series
config:
aggregationFunction: last
dimension1: date
gridIndex: 0
item: =props.item
itemStyle:
color: red
showBackground: false
type: bar
xAxisIndex: 0
yAxisIndex: 0
offset: 5
barWidth: 10
barGap: 0
barCategoryGap: 0
tooltip:
- component: oh-chart-tooltip
config:
orient: vertical
show: true
trigger: axis
xAxis:
- component: oh-value-axis
config:
axisLabel:
color: red
show: true
axisLine:
show: true
axisPointer:
show: true
axisTick:
interval: 1
lineStyle:
opacity: 1
show: true
gridIndex: 0
show: false
yAxis:
- component: oh-value-axis
config:
startValue: -20
scale: false
offset: 0
gridIndex: 0
inverse: false
max: 30
min: -30
show: true
splitNumber: 10
axisLine:
show: true
onZero: true
axisTick:
length: 40
minorTick:
show: true
length: 20
axisLabel:
show: true
margin: 23
align: right
verticalAlign: bottom
However, I can’t get “the fluid/mercury” to start from the bottom instead of from zero. There is an axis-parameter startValue which should allow just that, but it was introduced in ECharts 5.5.1 - which was first included in OH on August 12:
According to the GitHub tags, that commit is part of 4.3.0 though, so I guess I’ll have to upgrade my installation before trying to do anything more on this.
Just to be able to test without upgrading my OH installation, I started a npm “dev session” of the latest MainUI main branch, which includes ECharts 5.5.1, and it seems to work fine there:
…and ran this modified version of MainUI locally. This change makes the following widget work:
uid: widget_test5xx_bar
tags:
- bar
- temperature
props:
parameters:
- context: item
description: The current value
label: Item
name: item
required: true
type: TEXT
- context: number
description: The min range value
label: MinRange
name: minRange
required: false
type: TEXT
- context: number
description: The max range value
label: MaxRange
name: maxRange
required: false
type: TEXT
- context: number
description: The min value
label: Min
name: min
required: false
type: TEXT
- context: number
description: The max value
label: Max
name: max
required: false
type: TEXT
- context: string
description: The name
label: Name
name: name
required: false
type: TEXT
- context: number
description: The height of widget
label: Height
name: height
required: false
type: TEXT
parameterGroups: []
timestamp: Dec 20, 2024, 7:56:37 PM
component: oh-chart
config:
chartType: day
height: =props.height
periodVisible: false
slots:
grid:
- component: oh-chart-grid
config:
borderWidth: 0
includeLabels: false
width: 10
series:
- component: oh-data-series
config:
data:
- name: "Name of data"
value: =Number.parseFloat(items[props.item].state)
gridIndex: 0
itemStyle:
color: red
showBackground: false
type: bar
xAxisIndex: 0
yAxisIndex: 0
offset: 5
barWidth: 10
barGap: 0
barCategoryGap: 0
tooltip:
- component: oh-chart-tooltip
config:
orient: vertical
show: true
trigger: axis
xAxis:
- component: oh-value-axis
config:
axisLabel:
color: red
show: true
axisLine:
show: true
axisPointer:
show: true
axisTick:
interval: 1
lineStyle:
opacity: 1
show: true
gridIndex: 0
show: false
yAxis:
- component: oh-value-axis
config:
startValue: -30
scale: false
offset: 0
gridIndex: 0
inverse: false
max: 30
min: -30
show: true
splitNumber: 10
axisLine:
show: true
onZero: true
axisTick:
length: 40
minorTick:
show: true
length: 20
axisLabel:
show: true
margin: 23
align: right
verticalAlign: bottom
That means that you avoid the “workaround” with using aggregate/last, potential reliance on the Item being persisted - and it also gives more freedom to manipulate the data directly, handle units etc., since you can set the value directly (value: =Number.parseFloat(items[props.item].state)). I also think it makes it easier to understand the widget, less code is involved, and that it’s generally a better way to do it when you don’t need the aggregate function.
I don’t know how to test if this has some other “negative impact” on the system though, so I’m a bit hesitant to straight forward suggest this change, but it does look tempting. I have tried to look at related commits, and it doesn’t seem like there’s anything more too it. Here is the commit that enabled the use of pie for example:
Is this something I should “suggest” at GitHub - or is it even a small enough change that I could make a PR and that it would fall into the “CLA exception” clause?
I think it might turn out to be “impossible” to achieve what I wanted to. I’ve managed to get it somewhat close to what I wanted (many parameters and details aren’t there yet, but the fundamentals).
However, I just can’t align the different elements correctly. To explain, the widget is essentially 3 layers - there’s a SVG layer in the bottom supplying the “background” of the widget. Then there’s the ECharts bar in the middle layer, which draws the “fluid”/mercury and the scale. On top there’s another SVG layer that makes up the semi-transparent “glass” that covers the fluid/mercury, to give it a somewhat more realistic look.
The problem is aligning these 3 layers so that they always are exactly on top of each other, also when scaled etc. I didn’t think that was going to be so difficult using CSS, but all I’ve tried until now has basically failed. I can get them to line up under some circumstances, but when inserting the widget in a “custom layout” page using Firefox, it goes completely crazy. It also doesn’t want to fit precisely.
I think some of the problem might be that I try to mix canvas and SVG layers. Canvases, being bitmaps that’s scaled by the browser and SVGs that is being rendered in the correct size just don’t want to behave the same.
There is an option to use a SVG renderer for ECharts, but it’s not imported by OH and even if it were, I have no idea how to tell ECharts what renderer to use. And, I don’t know if that would solve anything, it just sounds more likely that they would behave the same if all 3 layers were SVGs. But, it’s probably not that simple anyway, since the ECharts “layer” is several nested elements, while the SVGs are just a single element each.
Maybe some CSS guru could figure it out, but for now I really am out of ideas.
The post gets too long with the widget included, so I’ll have to try to post that as a separate post.
This one liner should be fine
We however have to think about or check the other types you added there, how well they are useable with data series.
BTW:
The file you edited is only the widget definition, I wonder that it does not work without changing the widget definition, because in general for the charts stuff you can do much more from the code tab than from the config UI.
My thought were simply to add what was already imported, if somebody can find some way to use them. line kind of have to work as I see it, as the data works “the same way” as a bar chart. I can’t quite imagine how it can be useful for a widget, but that’s a different matter - somebody might find some creative use that I can’t imagine.
heatmap and scatter I know less about, but when I look at the data source for a heatmap it seems to consist of an array of 3 data points x, y and “value”/color. That should be simple enough to use in a widget, where you want the color for something to change gradually with some value for example. This could arguably be solved much easier using CSS, but maybe it could make sense in some situation. The scatter data source seems to be even simpler, an array of just x and y coordinates. Again, I can’t quite see a use for it, but you never know what people come up with
If you are thinking of editing “the widget” after inserting it into a page and then edit the widget part, that might get around some restrictions, but it makes it hard to reuse the widget (copy/paste is of course a possibility, but it’s still somewhat “manual”) and to share it on the marketplace for others to use.