highcharts special marker on column chart - highcharts

My question is similar to the one in
Highcharts: Show special marker on column chart
I have a column chart, which is a histogram of mutual fund returns in a specific period.I want to highlight where the Mutual Fund of interest falls with a special marker.
Say for example, i have -50 to -25, -25 to 0, 0 to 10, 10 to 20, 20 to 30, and 30 to 50 on my x axis, and corresponding Y values. I want to highlight with a marker on '20 to 30' to show that the Mutual Fund of interest falls into that bucket. I know we can do this using spline chart like http://www.highcharts.com/demo/spline-symbols.
Is there a way to do the same for column charts ??

In general you can't add custom marker to the column chart, but you can add similar behavior. I've created simple example with custom marker for scatter series, useful if you want to add more series into legends: http://jsbin.com/oyudan/37/edit (if not, just set showInLegend: false)
Highcharts.updateMarketMarkers = function (chart) {
/* get category width */
var catWidth = chart.xAxis[0].width / chart.xAxis[0].categories.length;
/* get padding of each column (two sides) */
var catPadding = chart.series[0].options.pointPadding * catWidth;
/* actual value - padding - symbol width/2 */
chart.series[2].markerGroup.translate(chart.series[2].markerGroup.translateX - 2 * catPadding - chart.series[2].data[0].shapeArgs.r / 2);
};
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
showAxes: false,
events: {
load: function () {
Highcharts.updateMarketMarkers(this);
},
redraw: function () {
Highcharts.updateMarketMarkers(this);
}
}
},
...
Another solution is to use Highcharts renderer to draw custom shapes at specific place. Here you can find more about renderer: http://api.highcharts.com/highcharts#Renderer

Related

Outline or border for the spline series in highcharts

I have created a graph using highcharts which has 6 series. 3 are column series and 3 are spline series.spline series will collide or go within the column chart so having a requirement to add outline to spline series to have better viewing. Trying to add a border color for the spline series but unable to do. But the same is possible in column chart.If anyone have tried this before for spline series kindly help.
plotOptions: {
series: {
borderColor: '#303030'
}
},
this bordercolor is working for column but not in spline series
column chart
http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/column-bordercolor/
would like to have border for the below series
http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-datalabels-box/
There is no such feature in Highcharts to set line border, but all is not lost.
You can achieve the effect you want, by adding new "fake" series basing on every line series, and set a couple of parameters.
Best place (in code) to do that would be the chart.events.load function, so there just find all series with line type:
chart: {
events: {
load() {
var series = this.series.filter(elem => elem.type === 'line')
}
}
}
Then, iterate on all the series found, and create new one so that it would have color: [color_you_want], the same data and marker.symbol, increased lineWidth as well as marker.radius, won't be accessible by mouse and not visible in legend, just like below:
chart: {
events: {
load() {
var series = this.series.filter(elem => elem.type === 'line')
series.forEach(series => {
this.addSeries({
data: series.userOptions.data,
showInLegend: false,
color: '#000',
enableMouseTracking: false,
zIndex: -9999,
marker: {
symbol: series.symbol,
radius: series.options.marker.radius + 1
},
lineWidth: series.options.lineWidth + 2
})
})
}
}
}
Hope, it helps you.
Live example: http://jsfiddle.net/yw2tb4nm/
API Reference:
https://api.highcharts.com/highcharts/chart.events.load
https://api.highcharts.com/highcharts/series.line.marker.symbol
https://api.highcharts.com/highcharts/series.line.marker.radius
https://api.highcharts.com/highcharts/series.line.showInLegend
https://api.highcharts.com/highcharts/series.line.enableMouseTracking

Identify all overlapping Highcharts scatter points clicked by the user

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);
}
}
}
}
}
});

Highcharts - Permanent, Draggable Selection Box

I am currently experimenting with the Highcharts charting library, and am totally blown away by its capabilities.
Something I am trying to accomplish is to add a permanent, draggable 'selection' box (or mask) to my chart. This selection box will always be a certain fixed width. For example, say my chart has 30 days worth of data, I would like there to be a draggable box with the width of 1 day. Dragging the box up and down the x-axis (over the actual chart data) will fire off other application events using the selected day as a parameter.
I guess I am looking for something very similar to the navigator in Highstock charts - but again the primary difference is keeping a fixed width selection. Any tips or suggestions would be greatly appreciated.
In Highcharts there is no such built-in feature but in Highstock you can also use only scrollbar, see: http://jsfiddle.net/ea7za/ Now you can use or bottom scrollbar or panning (drag on plotting area).
$.getJSON('url.json', function(data) {
var min = data[0][0], // min
max = data[500][0]; // max - e.g. max = min + 24 * 3600 * 1000; as one day
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector : {
enabled: false
},
navigator: {
enabled: false
},
xAxis: {
min: min,
max: max
},
title : {
text : 'AAPL Stock Price'
},
series : [{
name : 'AAPL',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});

Multiple different chart types stacked, column type with y value as color

What is the best way to achieve a chart with multiple types when it should include a type that has the following kind of visual presentation.
| yellow |blue| gray | yellow | gray |
i.e. a type which is one dimensional (but visually has height), and the color indicates 'y' (which here consists of categories: yellow, blue, gray)
You should also be able to stack those:
| radical | senseless | high tension |
| yellow |blue| gray | yellow | gray |
I can achieve this with having a chart typed column with a series for each category:
http://jsfiddle.net/RCnYV/
But how can I also add another chart type above that, like:
yAxis (only for the line)
^ ___
|------- ___________________________ ____/
| \__________/ \/
| radical | senseless | high tension |
| yellow |blue| gray | yellow | gray |
-----------------------------------------------------------> xAxis (shared)
So the line series should be above (not hovering over) the others. Note that the xAxis is shared between all of the series, i.e. all of the series have exactly as many data points. It is just that some of the series are presented as type 'line', and others with the new type (that I don't know good name for, ribbon?).
Also what other ways are there to create a similar chart? One problem with the above is that I need to create one series for each catalog, that is 2 * series in total, and not just two as would be the case with basic chart.
Are you looking for something like this # http://jsfiddle.net/jugal/cABfL/ ?
You can stack the charts by specifying heights for your yAxis, and manipulating its top so that they stack one over the other
yAxis: [{
top: 300,
lineWidth: 2,
offset: 0,
height: 200,
tooltip: {
enabled: true,
formatter: function() {
return this.series.name + ": " + $wnd.Highcharts.numberFormat(this.y, 2);
}
}
},
{
height: 200,
lineWidth: 2,
offset: 0,
tooltip: {
enabled: true,
formatter: function() {
return this.value + 50;
}
}
}],
Similar stacking example is available # http://www.highcharts.com/stock/demo/candlestick-and-volume
EDIT
To answer to the second part of the question (Also what other ways are there to create a similar chart?). There isn't anything out of the box that highchart seems to bring to the table for such a visualization, so you would need to work yourself around the existing lines and columns to get this visualization.
This is how I went about it.
I tried using the stacked bar chart for each ribbon, hence would need 2 series, 1 for the line and 1 each for both the ribbons. But after giving it a try, turned out the bar chart is nothing but a rotated column chart (at least a sort of), it seems to have the vertical axis as the X and horizontal one as Y, hence it messes up any other chart, i.e. the line chart gets messed up as it wants the horizontal to be the X.
Basically using a bar chart didn't take me much far. I went ahead using the line chart (With a very thick line lineWidth:50) and drew a horizontal (Constant Y for each point) line chart with one series for each section of the ribbon, hence being able to give each section different color. Each ribbon would need a separate Y-axis, with different offset as mentioned above. Also removed all the tooltip, Y-axis labels and grid lines, to make it look as different from a line chart and more like the ribbon. Tooltip may be needed, but line charts give tooltip for points, in our case we want tooltip on section between two points, hence wrote a mouseOver event handler and calculated the length of the section in there. The only part that was hurting now was creating a series for each section of the ribbon, so went ahead and wrote the following utility function that accepted a list of values, basically the x intercepts for each section (you can improvise it to take section length instead) and returned an array of series.
// usage: createSeries([0, 3, 4, 6], 1)
// Creates 4 series and assigns them all to yAxis 1
// you can extend this to take colors etc too, as per requirement
function createSeries(data, yAxisIndex) {
var i;
var series = [];
for (i = 0; i < data.length - 1; i++) { // Node lenghth-1
var start = data[i];
var end = data[i + 1];
series.push({
yAxis: yAxisIndex,
animation: false,
stack: 0,
data: [[start, 0], [end, 0]],
lineWidth: 50,
marker: {
enabled: false
},
tooltip: {
pointFormat: function() {
return "";
}
},
events: {
mouseOver: function() {
alert(this.data[1].x - this.data[0].x);
}
},
showInLegend: false
});
}
return series;
}
All that was needed was to push these series into the existing series and then feed it to the highchart constructor.
Final jsFiddle: http://jsfiddle.net/jugal/cABfL/

Highcharts scatter plot with variable line width

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()})
})

Resources