I have a set of interconnected charts with Highcharts and callback functions. Specifically, put together a scatter plot with an x-axis range selection, which connects to a bar chart that reflects the average y-value of the points selected, by category.
It uses the 'events' key when creating the chart to call a function that edits and redraws the bar chart.
Please click on this sandbox link to see the example that I have put together: https://codesandbox.io/s/youthful-browser-mid8x?file=/index.html
I would like to know if the code can be written any better with improvements. If anyone can please review and let me know. Thanks.
You don't need to call redraw after setData:
function update_chart2(xmin, xmax) {
...
chart2.series[0].setData(new_data);
// chart2.redraw(); - redraw is called in setData
}
You can update xAxis with plot-band options instead of removing and adding it.
events: {
selection: function (event) {
...
if (event.xAxis) {
xmin = event.xAxis[0].min;
xmax = event.xAxis[0].max;
this.xAxis[0].update(
{
plotBands: [
{
from: xmin,
to: xmax
}
]
},
false
);
}
update_chart2(Math.floor(xmin) + 1, Math.floor(xmax) + 1);
},
...
}
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Series#setData
https://api.highcharts.com/class-reference/Highcharts.Axis#update
Related
I am using the Highcharts synchronized charts to display three different variables. However, in order to render cleaner graphs, I'd like to display the x-axis (which is the same for all three graphs) only for the bottom graph.
For that, I presume, I need to cycle at the end of the generation process through the charts and suppress the first two x-axis, kind like
for (i = 0; i < (Highcharts.charts.length - 1); i = i + 1)
{
chart = Highcharts.charts[i];
chart.xAxis.labels.enabled = false;
}
Here is the default fiddle.
I don't succeed in getting this to work. Can anyone help me out on this?
You can set the xAxis.visible property depending on the chart index:
success: function (activity) {
activity = JSON.parse(activity);
activity.datasets.forEach(function (dataset, i) {
...
Highcharts.chart(chartDiv, {
xAxis: {
visible: i === 2,
...
},
...
});
});
}
Live demo: https://jsfiddle.net/BlackLabel/cmdb5at0/
API Reference: https://api.highcharts.com/highcharts/xAxis.visible
I have created an highcharts stacked bar chart, but when the data is skewed, the bars are not visible or the numbers overlap, as shown in below image.
I have seen many posts, but there is no out of the box solution for this, so i am making my custom solution.
I am setting a default height of 150 if the y value is less than 150.
This solution works, but the total of the bars now is shown to be 300 instead of the actual original value. How can i change the total stacklabel value on my own? I am unable to find a way to do that.
Here is the code to change the height to default values. I am storing the actual value in realValue variable in the point object.
chartOptions = {
type: CHARTING.CHART_OPTIONS.TYPE.COLUMN,
// On chart load, apply custom logic
events : {
load: function () {
var chart = this,
minColHeightVal = 150;
chart.series.forEach(function (s) {
s.points.forEach(function (p) {
if (p.y < minColHeightVal) {
p.update({
y: minColHeightVal,
realValue: p.y
}, false);
}
});
});
// How to iterate over the bars here and sum the actual value? i.e. point.realValue and set the stacklabel?
chart.redraw();
}
}
}
Did you try to use minPointLength option? It may be a simpler solution in your case: https://api.highcharts.com/highcharts/series.column.minPointLength
However, using your code to get the wanted result, use stackLabels.formatter function:
formatter: function() {
var series = this.axis.series,
x = this.x,
sum = 0;
series.forEach(function(s) {
if (s.points && s.points[x]) {
sum += s.points[x].realValue ? s.points[x].realValue : s.points[x].y
}
});
return sum;
}
Live demo: https://jsfiddle.net/BlackLabel/uocdykbL/
API Reference: https://api.highcharts.com/highcharts/yAxis.stackLabels.formatter
I am wondering if it is possible to set the value of a series to always be the top of the current chart, more or less like using plotBands or plotLines.
For example, I would love to have a series like: [1,1], [1,yAxis.top] ...
Is that possible?
Yo do not know what is an axis max until you set it or let the Highcharts calculate it. I assume that you do not want to set axis.max, so you need to wait until the Highcharts sets axis max and then add a max point dynamically. You can use a load event to achieve that.
chart: {
events: {
load: function () {
const axis = this.yAxis[0]
const max = axis.max
const series = this.series[0]
axis.update({ max })
series.addPoint(axis.max, true, false, false)
}
}
},
example http://jsfiddle.net/qb2tn7jh/
I am using Highcharts and I would like this chart to update each second. This is what I have now: JSFiddle
I have timer window.setInterval(updateChart, 1000); and it works properly actualizing data each second.
But I have no idea how to actualize the view. It is important that I don't want to draw chart again and again each second. I only want to shift points and add new ones. Do anyone know how to do that?
Look at the the series.addPoint method.
Your updateChart function becomes:
function updateChart()
{
for (var source = 1; source <=3; source++)
{
var point = [
23,
Math.floor((Math.random() * 10*source) + 5+source*2),
source
];
Highcharts.charts[0].series[0].addPoint(point, false, true); // add the point, don't redraw and shift off a point
}
Highcharts.charts[0].redraw(); // 3 points added, now redraw
}
Update fiddle.
I'm trying to make a particular bar chart with D3.js, and I don't find any example who could match. I would code a bar chart with two series (one negative, and one generally positive) disposed on the same line, but not stacked.
I guess that maybe it's not very clear, so I've made this on Highcharts. I want to use D3 to connect the chart with a map I did before.
So, does someone know any example that could help me? Can I sort directly the chart even if my series are unordered? And if the two series are punctually postive, does the little one appear in front of the largest?
The trick is to order your data, in order to do so, you can use the [d3.ascending()][1] functions:
with the following example data:
data = [{
name: "A",
valueRight: 1,
valueLeft: 2
}, {
name: "B",
valueRight: 4,
valueLeft: 5
}, ...]
We would have:
function leftBound(node) {
return d3.max([node.valueLeft,-node.valueRight])
}
function rightBound(node) {
return d3.max([node.valueRight,-node.valueLeft])
}
dataSort = function(a,b) {
res = d3.descending(leftBound(a),leftBound(b))
if(res==0) {
return d3.descending(rightBound(a),rightBound(b))
} else {
return res
}
}
For reusable charts, you can also use [selection.sort()][2] but you have to do this for the 2 bar categories.
JsFiddle: http://jsfiddle.net/vgZ6E/55/
ScreenShot:
The original code is from the following question: d3.js bar chart with pos & neg bars (win/loss) for each record