I have a sparkline chart of temperature sensor data,
Its a year of data sampled at every 1 min
I first load a blank chart, then I do a server call, bring the results back and display it by calling
getchart.addSeries({
name: thisGroup,
id: probeItem[0],
data: probeDataArray,
keys: ['x', 'y', 'specialId'],
there could be upto 20 series, and they all load on the screen one by one
This renders quite quickly, however I now need to add a label annotation where the temperature goes over a certain Value (i.e. in add a warning symbol when its alarm state)
Currently I'm looping through each point and seeing if its over a certain value:
currentSeries.points.forEach(function (point) {
However this is very slow.
I have an array of the alarms, and can reference them as
['x', 'y', 'specialId']
However I cannot see how I can add an annotation label by x,y or specialId.
I can only seem to add the label if i loop through all the points already rendered
Is there a way to add a label by using my Id's?
I also need to resize the graph and the labels to remain in the same place
Alternatively if this is not possible, is there anyway to add the labels as i'm adding the series?:
getchart.addSeries({
name: thisGroup,
id: CurrentGroupID,
dashStyle: 'ShortDot',
data: groupLogArray,
keys: ['x', 'y', 'specialId'],
showInNavigator: true, //this shows the series data in the small bottom navigator
point: {
events: {
click: function () {
//alert("test click");
}
}
}
});
You can add an annotation by x and y axis values:
chart.addAnnotation({
labels: [{
text: 'Alarm',
point: {
x: 2,
y: 3,
xAxis: 0,
yAxis: 0
}
}]
});
Live demo: http://jsfiddle.net/BlackLabel/k6trha3e/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#addAnnotation
As an alternative, you can also use data labels: http://jsfiddle.net/BlackLabel/n4586xzq/
Related
I am currently working on a specific type of chart and I am trying to achieve the following behavior for example :
As you can see there's a gap between the series last point and the xAxis max value and the reason for this is i wanna have a fix max value and load the daily values of a specific currency as the day passes by. So for example in the morning this chart would be empty and by 18:30 it would be filled.
In my mock example i have the current chart:
and when I try to set a new xAxis max value ( i also tried softMax) to a future day (using epoch converter for unixtimestamp) i am getting this:
and i set the max by doing :
return {
endOnTick: false,
max:1631962355,
tickLength: 2,
gridLineColor: '#b9b9b9',
gridLineWidth: 0,
tickColor: '#808080',
labels: {
style: {
color: '#b9b9b9',
},
x: 0,
y: 12,
format: '{value:%d.%b}',
},
visible: true,
};
}
UPDATE
After implementing your response I get an even weirder behavior. I get the same initial start I had before (no difference) but now if i click and drag it to the right I go from this :
to this:
and If i click and drag it to the left, into this:
The transformation happens without animation, neither by wathching the drag and move motion happen. It just instantly transforms after i drag my cursor pointer for a while towards the sides i mentioned above
You need to use milliseconds instead of seconds:
xAxis: {
max: 1631962355000,
...
}
Live demo: https://jsfiddle.net/BlackLabel/herncjL5/
API Reference: https://api.highcharts.com/highstock/xAxis.max
I'm trying to plot some sparse values over a few hundred x-axis category labels. The labels represent points along a geographical entity, so it is necessary to space them according to the actual distance between each point.
I can easily make x-axis categories and plot the values against them, but each category is evenly spaced. If I change to using a complex marker with {x, y, name} properties, the categories are only displayed if they match the tick interval. If a category doesn't match the tick interval, then a number is displayed.
I can produce the following:
with this small fake sample of data, JSFiddle:
...
xAxis: {
type: 'category'
},
series: [{
name: 'Series 1',
data: [
{x:1, y:null, name: 'AB1.1'},
{x:4, y:1, name: 'AB1.2'},
{x:5, y:null, name: 'AB1.3'},
{x:11, y:1, name: 'AB1.4'},
{x:14, y:null, name: 'AB1.5'},
{x:14, y:null, name: 'AB1.6'},
{x:19, y:1, name: 'AB1.7'},
{x:27, y:1, name: 'AB1.8'},
{x:28, y:null, name: 'AB1.9'},
{x:30, y:1, name: 'AB2'},
{x:37, y:1, name: 'AB2.1'},
{x:37, y:1, name: 'AB2.2'},
{x:38, y:1, name: 'AB2.3'},
]
}]
...
As you can see, the x-axis at this zoom level shows:
0, 3, 6, 9, 12, 15, 18, 21, 24, AB1.8, AB2, 33, 36, 39
What I want is for the x-axis to show any of the actual labels (so long as the markers are placed relative to their distance, just like the x-values of the plot); but no generated numbers.
In reality, I have multiple series with around 1,000 points each, but they will all be on the same geographical entity so they all share the same categories. (JSFiddle with much more fake data). I can also guarantee that x-values are whole numbers.
I have already tried specifying various x-axis options around ticks, minimum ticks etc. but highcharts still wants to extrapolate evenly spaced labels.
Thanks!
I have got the results I want (JSFiddle) by setting xAxis.tickPositions dynamically on zoom. To begin with, I pick about 35 x-Axis positions to display my markers (an arbitrary number but I picked something that worked for my fixed-width chart size).
Then, on zoom, I update the chart to display about 30 markers that are within the new zoom level.
This way I always have a good number of markers displayed, and they are unevenly spaced because that's what my actual data is like.
Zoomed out (L) and zoomed in (R):
this is an array of all x-axis points that have a marker-a few thousand
allTicks = [1, 6, 9, 9, ...]
a function to select 30 points from the given array
function selectTickPositions(tickPositions) {
const maxTicks = 30;
if (tickPositions.length <= maxTicks) return tickPositions; // return all
let mod = Math.round(tickPositions.length / maxTicks);
// always select the first and the last, and then up to 30 more
return tickPositions.filter((val, idx) => idx == 0 || idx == tickPositions.length - 1 || idx % mod == 0);
}
setup the chart options:
let theChart = Highcharts.chart('container', {
chart: {
...
events: {
// the selection event is fired when a zoom selection is made
selection: (event) => {
let ticks;
if (event.xAxis) {
let min = event.xAxis[0].min;
let max = event.xAxis[0].max;
ticks = selectTickPositions(allTicks.filter(t => t >= min && t <= max));
} else {
ticks = selectTickPositions(allTicks);
}
theChart.update({
xAxis: {
tickPositions: ticks
}
});
return true;
}
}
},
...
xAxis: {
type: 'category',
tickPositions: selectTickPositions(allTicks)
},
});
I am not sure if I understand your requirement very well, but here is my attempt of showing just a xAxis.labels if the label is a category string.
Demo: https://jsfiddle.net/BlackLabel/4xdjw5L7/
xAxis: {
type: 'category',
endOnTick: true,
startOnTick: true,
labels: {
formatter() {
if (typeof this.value !== 'number') {
return this.value
}
}
}
},
API: https://api.highcharts.com/highcharts/xAxis.labels.formatter
Let me know if this is an expected output.
I created a calendar using a heatmap, like this:
calendar screen:
The axis types are categories, so the months are placed as blocks with the respective offset in the matrix. Every month is defined as a series with names.
Now my problem is, I want to show the month name above the block. However, I found no way to display the serial name. He is simply ignored.
The x-axis displays only the index of the category. I can not use this. The data label contains the color value for the heatmap.
My workaround currently is that I insert the month names as PlotLine. But that's not the way to go. Especially since the positioning is independent of the monthly block and thus error-prone.
series: [{
name: 'January',
keys: ['x', 'y', 'value'],
data: [...]
}, ...next month...]
jsFiddle example
You can use Highcharts.SVGRenderer to add series name as text in calculated position:
events: {
load: function() {
var series = this.series,
bbox;
series.forEach(function(s) {
bbox = s.group.getBBox(true);
this.renderer.text(
s.name,
bbox.x + this.plotLeft + bbox.width/2,
bbox.y + this.plotTop - 10
)
.attr({
align: 'center'
})
.css({
color: 'black',
fontSize: '12px'
})
.add();
}, this);
}
}
Live demo: https://jsfiddle.net/BlackLabel/zypnwq50/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
I have a highstock chart with a scatter series that has overlapping points. The X values are identical but the Y values have slight variations. Because the variations are small the overlap is not exact but is still difficult for the user to distinguish.
When a scatter point is clicked / tapped I want to identify all data points that the mouse pointer / finger touches. However it seems like Highcharts will only raise a click event for the point on top of the stack. There are several suggestions online for iterating over all data points and finding those with matching Y values, however in my case I would need to apply some fuzzy logic and try and select points that look to the user like they're overlapping, based on the size of the marker and the height of the chart and this seems like a move in the wrong direction.
Is there anything within Highcharts I can use to find all the points the user interacted with?
JS Fiddle: http://jsfiddle.net/f22tq4t2/1/
Highcharts.stockChart('container', {
series: [{
type: 'scatter',
name: 'Demo scatter overlap',
data: [{x: 1500052112000, y: 5}, {x: 1500052112000, y: 5.1}, {x: 1500052118000, y: 15.1}, {x: 1500052118000, y: 15.2}]
}],
xAxis: {
min: 1500052109000,
max: 1500052119000,
type: "datetime"
},
plotOptions: {
series: {
point: {
events: {
click: (event) => {
alert('clicked ' + event.point.y);
}
}
}
}
}
});
Which I am passing to:
series: [{
name: 'Fixed bugs',
data: fixed,
pointWidth: 40
}, {
name: 'Assigned Bugs',
data:assigned,
pointWidth: 40
}, {
name: 'Re-Opened Bugs',
data: Reopened,
pointWidth: 40
},
{
name: 'Closed Bugs',
data: closed,
pointWidth: 40
}]
to this chart and I have the data like this :
data: fixed=[3,5,5,8]
data:assigned=[0,1,0,0]
and follows. Now I want to show the column with zero value to... For me its not showing the column value with zero.
minPointLength will work. Use this.
plotOptions: {
column: {
minPointLength: 3
}
}
You can do this quite simply with the minPointLength option. It sets the minimum number of pixels per column, default is 0, so zero values don't show up. It's in the docs here.
Try this JSFiddle
Here is a way to do it - although I think just having the column be zero-valued and not visible is the best way.
Find a very very low number that none of your data points would ever have but still keep it >0. Let us say it is .005. When you bring in your data any value that is 0 assign it this .005 value. In your tooltip formatter do an IF on the value. If it is .005 then make it 0. This way you get to see the "zero" column but the tooltip displayed will be 0 as well. If you are doing any kind of calculation on the stacked columns then you need to account for this non-0 0 value in there as well.
Not sure what you are trying to display, but maybe you could try to show the datalabels like this:
plotOptions: {
series: {
dataLabels: {
enabled: true,
color: 'gray'
}
}
}
Attempt at demo