I am trying to create a scatter plot where when you select a point it will create a new graph with different data. This works fine.
The issue is when you zoom in on the second scatter plot then press reset zoom, the chart resizes and pushes all the data to the left (I'm assuming because all my data points have the same x coordinate or because the values are very small). I thought by using setExtremes() the reset zoom would use those values as the min and max.
Here's the JSFiddle: http://jsfiddle.net/kzBxB/5/
Below is the function I'm using to create the new chart. Do I need to change anything to make the 'reset zoom' register my given xAxis min and max values?
function newPoints() {
var chart = jQuery('#container').highcharts();
for (var i = 0; i < chart.series.length; i++) {
serie = chart.series[i];
//sets the new x axis and new data
chart.yAxis[0].setExtremes(0, 10);
chart.xAxis[0].setExtremes(.001, .003);
chart.addSeries({
type: 'scatter',
name: serie.name,
data: [
[.002, 1],
[.002, 2],
[.002, 3],
[.002, 4],
[.002, 5][.002, 6]
]
}, false);
//removes the old series
serie.remove(false);
}
//redraws the chart
chart.redraw();
}
The problem is that all values have the same x-value, so Highcharts don't know where to plot them (what is the range of points). In such case I advice to use afterSetExtremes event:
xAxis: {
events: {
afterSetExtremes: function(e){
if(e.min === e.max){
this.setExtremes(.001, .003);
}
}
}
},
And example: http://jsfiddle.net/kzBxB/7/
Related
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 have a line chart that plots multiple datasets where each dataset has two lines associated with it: a reference line and a measured line.
To plot all of these lines, I added individual series for each subset of data, giving the reference line a dashed appearance and the measured line a solid appearance.
The tooltip formatter displays a popover of detail data for a specific point based on the cursor position. It only displays data for one series.
How might I group the series together in such a way that I can display a tooltip for multiple series, but not necessarily all of the series?
Highcharts seems to have an option for shared that displays a tooltip for all of the series that correspond to the cursor's X coordinate, but is there a way to do some sort of grouping? Is there something I can do to the series configuration so that each series renders two lines on the chart but with different appearances?
Not sure if what I'm trying to do is possible with Highcharts. Might need to be a custom chart.
There is no such default functionality in Highcharts, but for now I see two possible workarounds:
slight change in x value:
series: [{
data: [1, 1, 1]
}, {
data: [[0.0001, 2], [1.0002, 2], [2.0002, 2]]
}, {
data: [3, 3, 3]
}, {
data: [[0.0001, 4], [1.0002, 4], [2.0002, 4]]
}]
Live demo: http://jsfiddle.net/BlackLabel/v1uxp3jh/
wrap of the refresh method to exclude some of the unwanted points:
(function(H) {
H.wrap(H.Tooltip.prototype, 'refresh', function(proceed, points) {
points.forEach(function(p, i) {
if (p.series.name === "Series 2") {
points.splice(i, 1);
}
});
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/qd4mnx8e/
Docs: https://www.highcharts.com/docs/extending-highcharts
I've an API that is returning the following data:
[1466274600000, 166.409],
[1466274900000, 138.266],
[1466275200000, 160.668],
[1466275500000, 147.300],
[1466275800000, 147.778],
[1466276100000, 136.043]
I've loaded this into Highstock, which gives me this chart
However, the values are actually the rate of change between the timestamp and the next timestamp. So, the difference between the value at 1466274600000 and 1466274900000 is 166.409, etc. so I'd like the charts to represent this by appearing over the gap between the ticks.
Is this possible? I can change the output of the API if necessary...
Fiddle here: http://jsfiddle.net/bLrah/157/
Is this what you're looking for?
http://jsfiddle.net/strince/bLrah/159/
var data = [
[1466274600000, 166.409],
[1466274900000, 138.266],
[1466275200000, 160.668],
[1466275500000, 147.300],
[1466275800000, 147.778],
[1466276100000, 136.043]
];
var columnWidth = $("#chart").width() / data.length;
...
plotOptions: {
column: {
pointPadding: 1,
borderWidth: 1,
pointWidth: columnWidth
}
},
This question is regarding highcharts. Can we create something like this in highcharts? Pie chart on a scatter plot? Please have a look at the url https://www.dropbox.com/s/mcmzn0t0hz4s2x7/pieChartScatterPlot.png
I would draw a normal scatter plot first, then loop the points placing additional pie charts on top of them:
// initial scatter
series: [{
type: 'scatter',
name: 'Scatter Me',
data: [3, 2, 1, 3, 4]
}]
// in load event, loop our scatter series
// and add a pie chart at each point
chart: {
events: {
load: function(){
var chart = this;
$.each(chart.series[0].data, function(i,datap){
chart.addSeries({
type: 'pie',
minSize: 50,
size: 50,
dataLabels: {enabled: false},
data: [Math.random() * 10, Math.random() * 10, Math.random() * 10],
center: [datap.plotX-21, datap.plotY-21],
}, false);
});
chart.redraw();
}
}
}
Here's a fiddle and how it looks:
The one thing that's got me scratching my head is that I had to introduce a fudge factor to get the pie center to align with the points.
I want to plot a scatter chart with lines connecting each point. Is it possible to vary the width of the line between each segment?
For example, I want the line from point A to point B to have a width of 5. I want the line between point B and point C to have a width of 2.
Sure, I could use the renderer to manually draw the lines, but then I have to handle the coordinates and scaling manually.
(FWIW, here's an example of a scatter plot with connecting lines.)
There is no configuration option to do this. The difficult way would be, as you say, to implement it your self with help of the renderer.
You can configure individual points with color and size:
data: [{
x: 161.2,
y: 51.6,
marker: {
radius: 15,
fillColor: 'rgb(255, 0, 0)'
}
}]
but the line that connects two markers do not have any individual settings.
There is a way to do this without using the renderer, however it is very much a hack.
The basic premise is that you can adjust the thickness of a line in Highcharts after render time by manipulating the SVG or VML attributes, and you can prevent Highcharts from changing it back. Therefore all you need to do is break up your series into two point series and chart them all at once. Code below, fiddle can be seen here http://jsfiddle.net/39rL9/
$(document).ready(function() {
//Define the data points
DATA = [
{x: 2,y: 4,thickness: 1},
{x: 7,y: 8,thickness: 8},
{x: 10,y: 10,thickness: 2},
{x: 22,y: 2,thickness: 10},
{x: 11,y: 20,thickness: 15},
{x: 5,y: 15,thickness: 2}
]
//Format the data into two point series
//and create an object that can be put
//directly into the "series" option
var finalSeries = [];
for (var i=0; i < DATA.length-1; i++) {
finalSeries[i]={};
finalSeries[i].data = [];
finalSeries[i].data.push(DATA[i]);
finalSeries[i].data.push(DATA[i+1])
};
//A function to change the thickness of
//the lines to the proper size
function changeLineThick(){
var drawnSeries = $(".highcharts-series")
for (var i=0; i < drawnSeries.length; i++) {
drawnSeries.eq(i)
.children("path")
.eq(3) //this could change depending on your series styling
.attr("stroke-width",DATA[i].thickness)
};
}
//Define and render the HighChart
chart = new Highcharts.Chart({
chart: {
renderTo: "chart-container",
defaultSeriesType: "scatter"
},
plotOptions: {
scatter: {
lineWidth: 2
}
},
symbols: ["circle","circle","circle","circle","circle","circle"],
series: finalSeries
})
changeLineThick();
//prevent Highcharts from reverting the line
//thincknesses by constantly setting them
//to the values you want
$("#chart-container").mousemove(function(){changeLineThick()})
})