I have to create bar graphs as shown in the attached image using highcharts. The graph in the image has been created using Excel. But Highcharts doesn't seem to provide such feature. Though it allows to create graph using patterns but one doesn't have much control on those patterns. Can anyone please confirm if we can create similar kind of charts in highcharts or not? I have created a fiddle with highcharts for sample at http://jsfiddle.net/sandeepkparashar/6c48x39v/3/Dashed Bar Chart
As was mentioned in the comment, pattern-fill plugin can handle this.
You can create patterns and map the series, so every second column will have the corresponded pattern.
var colors = ["#FF0000", "#FF8C00", "#FFFF00", "#00FF00", "#3366FF"];
var series = [{
"color": "#FF0000",
"name": "High",
"data": [298, 199, 448, 271, 772, 494, 935, 562]
}, {
"color": "#FF8C00",
"name": "Medium High",
"data": [130, 32, 234, 172, 159, 134, 218, 160]
}, {
"color": "#FFFF00",
"name": "Medium",
"data": [141, 163, 95, 63, 71, 22, 26, 13]
}, {
"color": "#00FF00",
"name": "Medium Low",
"data": [42, 8, 34, 19, 16, 20, 21, 26]
}, {
"color": "#3366FF",
"name": "Low",
"data": [4, 4, 0, 0, 0, 0, 0, 0]
}];
function getPatterns(colors) {
return colors.map(function(color, i) {
return {
id: 'custom-pattern-' + i,
path: {
d: 'M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11',
stroke: color
}
};
});
}
function getMappedSeries(series) {
return series.map(function(serie, i) {
return {
color: colors[i],
name: serie.name,
data: serie.data.map(function(value, j) {
return j % 2 ? {
y: value,
color: 'url(#custom-pattern-' + i + ')'
} : value;
})
};
});
}
example: http://jsfiddle.net/6c48x39v/8/
Natively, you can set border dash style for the series but you need to set dash style for the specific points, so you would have to split the series into dash/no border series or extend Highcharts.
Related
I have 2 spline charts that I want to compare on a singe graph. The first should take up the top 25% of the plot area and the second should take up the bottom 75% of the plot area. To achieve this, I tried the following:
"yAxis": [{
"height": "25%",
"id": "blue",
"labels": {
"enabled": false
},
"title": {
"text": ""
},
"min": 267.15,
"max": 289.15,
"index": 0
},{
"id": "red",
"height":"75%",
"top": "25%",
"min": 265,
"max": 290,
"plotLines": [{
"color": "#fff8df",
"value": 285.15
}, {
"color": "#fff8df",
"value": 279.15
}, {
"color": "#c5eded",
"value": 273.15
}],
"index": 1
}],
The problem with this is that I have a min/max set (the graph is showing temperatures and we only care about a certain range). Because of these combined things, the graph is drawing right over the xAxis and outside of the expected plot area.
see: https://jsfiddle.net/06f9huam/
What I would like to see is the red line to be cut off if it goes below 265, just like it gets cut off when it goes over 290.
You can cut the unnecessary parts of lines by using clip-path attribute, example:
chart: {
animation: false,
events: {
load: function() {
const series1 = this.series[0];
const series2 = this.series[1];
const clipRect1 = this.renderer.clipRect(
series1.yAxis.left - series1.group.translateX,
series1.yAxis.top - series1.group.translateY,
series1.yAxis.width,
series1.yAxis.height
);
const clipRect2 = this.renderer.clipRect(
series2.yAxis.left - series2.group.translateX,
series2.yAxis.top - series2.group.translateY,
series2.yAxis.width,
series2.yAxis.height
);
series1.graph.clip(clipRect1);
series2.graph.clip(clipRect2);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/15e3g78w/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#clipRect
https://api.highcharts.com/class-reference/Highcharts.SVGElement#clip
I'm working on a Highchart map mixing Bubble map an mapline.
I use a first serie to show the map and color region depending on a measure range and a second serie to display a bubble on a region
var data = [
["05", 48810.00, 48810, 10, 19768, -1],
["09", 39239.00, 39239, 10, 13348, -1],
["10", 14974.00, 14974, 10, 7252, -1],
["11", 57124.00, 57124, 10, 26272, -1],
["14", 38821.00, 38821, 10, 17547, -1]
], maxSize = 0;
var all_codes = ["05", "09", "10", "11", "14"];
var Color = [];
Color[0] = "rgba(116, 171, 226, 0.8)";
Color[1] = "rgba(239, 141, 93, 0.8)";
Color[2] = "rgba(63, 182, 142, 0.8)";
Color[3] = "rgba(240, 106, 147, 0.8)";
Color[4] = "rgba(169, 125, 216, 0.8)";
Color[5] = "rgba(58, 181, 194, 0.8)";
Color[6] = "rgba(105, 115, 246, 0.8)";
Color[7] = "rgba(205, 89, 177, 0.8)";
Color[8] = "rgba(140, 162, 171, 0.8)";
Color[9] = "rgba(243, 135, 135, 0.8)";
Color[10] = "rgba(77, 120, 162, 0.8)";
Color[11] = "rgba(24, 102, 180, 0.8)";
Color[12] = "rgba(204, 67, 0, 0.8)";
Color[13] = "rgba(3, 115, 77, 0.8)";
Color[14] = "rgba(215, 9, 71, 0.8)";
Color[15] = "rgba(119, 42, 203, 0.8)";
Color[16] = "rgba(8, 119, 131, 0.8)";
Color[17] = "rgba(37, 49, 212, 0.8)";
Color[18] = "rgba(146, 20, 115, 0.8)";
serie_color = [{
from: 0,
to: 5254,
name: '< 5 254.00',
color: Color[0]
}, {
from: 5255,
to: 10509,
name: 'From 5 255.00 to 10 509.00',
color: Color[1]
}, {
from: 10510,
to: 15764,
name: 'From 10 510.00 to 15 764.00',
color: Color[2]
}, {
from: 15765,
to: 21019,
name: 'From 15 765.00 to 21 019.00',
color: Color[3]
}, {
from: 21020,
to: 26274,
name: '> 21 020.00',
color: Color[4]
}, ];
$(function() {
var chart = Highcharts.mapChart("container", {
chart: {
backgroundColor: "#ffffff",
animation: false
},
colorAxis: [{
dataClasses: serie_color
},
{
minColor: '#efecf3',
maxColor: '#990041',
}
],
mapNavigation: {
enabled: true
},
series: [{
mapData: Highcharts.maps["bret"],
data: data,
name: "States",
borderColor: "#319663",
nullColor: "#f7f7f7",
showInLegend: true,
joinBy: ["code", "CODE_REGION"],
keys: ["CODE_REGION", "DimGraphList_0", "z", "valSize", "value", "pieOffset"]
},
{
mapData: Highcharts.maps["bret"],
type: "mapbubble",
name: "Bubbles",
colorAxis: 1,
showInLegend: true,
joinBy: ["code", "CODE_REGION"],
keys: ["CODE_REGION", "DimGraphList_0", "z", "valSize", "value", "pieOffset"],
data: data,
minSize: "5%",
maxSize: "15%"
}
]
});
});
Result is fine (https://jsfiddle.net/vegaelce/f7neq2a1/) but I've a strange behavior, when the bubble is displayed on the map, the map is is off-centered.
On the jsfiddle, if you click on the "Bubble" value in the legend (to hide them), you'll see the map move and be centered (that should be the expected right position with the bubble displayed).
Any suggestion about this move ? I suspect an offset or something else but how to find/set it ?
Another tip concerns the legend : I'd like to move the 2 legends on different points :
the legend for the first serie (colored bullet points) on the bottom of the chart
the scalar legend for the bubbles on the left (or right) of the chart
Highchart considers that there is only one legend (grouping the 2 series), is it possible to dissociate them ?
Thanks in advance
The first issue looks like a Highcharts bug (related with wrong calculation of x-axis extremes), you can report it here: https://github.com/highcharts/highcharts/issues/new/choose
As a workaround use this code:
Highcharts.seriesTypes.mapbubble.prototype.useMapGeometry = true;
Live demo: https://jsfiddle.net/BlackLabel/oL1zahtm/
As to your second question - Highcharts doesn't have built-in support for multiple legends, but you can change some legend items position by manual translatation, for example:
chart: {
...,
events: {
render: function() {
this.legend.allItems[5].legendGroup.attr({
translateX: -50,
translateY: -50
});
this.legend.allItems[6].legendGroup.attr({
translateX: -50,
translateY: -70
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/m7zaeLrd/
Here is the code I have added to plot the bubble chart
{
chart: {
type: 'bubble',
plotBorderWidth: 1,
zoomType: 'xy',
},
title: {
text: 'Highcharts bubbles with radial gradient fill',
},
xAxis: {
gridLineWidth: 1,
min: 0,
},
yAxis: {
min: 0,
max: 100,
},
plotOptions: {
series: {
maxSize: 20,
cursor: 'pointer',
stickyTracking: false,
},
bubble: {
dataLabels: {
enabled: true,
format: '{point.y:,.0f}%',
inside: false,
align: 'center',
x: 0,
y: -8,
style: {
textOutline: 0,
fontWeight: '400',
color: 'black',
},
},
marker: {
lineWidth: 0,
},
},
},
series: [
{
data: [
[42, 38, 500],
[6, 18, 1],
[0, 93, 505],
[57, 2, 90],
[80, 76, 22],
[11, 74, 96],
[88, 56, 10],
[30, 47, 49],
[57, 62, 98],
[4, 16, 16],
[46, 10, 11],
[22, 187, 89],
[57, 191, 82],
[45, 15, 98],
],
},
],
}
There you might find 2 data points not showing up because y-axis range has been defined. I would also need those points to be rendered in the graph at boundary level (at 100). Is there any special property to set this (or) it is not working even if highcharts had default feature like that. Please help me with this.
You can preprocess your data to set y: 100 for values that are greater than 100 and save the original value to show it, for example in a tooltip:
var data = [
...
];
var processedData = data.map(el => ({
x: el[0],
y: el[1] > 100 ? 100 : el[1],
z: el[2],
realYVal: el[1]
}));
Highcharts.chart('container', {
...,
series: [{
data: processedData
}]
});
Live demo: http://jsfiddle.net/BlackLabel/jx0o7e1d/
How to create a multi-axis highchart showing difference of multiple axis in different color. (how to show the orange color in attached image)
Expected graph.
The simplest way is to use column chart with 2 series (orange and grey) and plotOptions.grouping property set to false. I added 2 additional line series with disabled mouseTracking, and markers similar to markers on your image. Additionally i formatted tooltip to display the orange over value.
Cross marker SVG:
Highcharts.SVGRenderer.prototype.symbols.cross = function(x, y, w, h) {
return ['M', x, y, 'L', x + w, y + h, 'M', x + w, y, 'L', x, y + h, 'z'];
};
plotOptions.grouping:
plotOptions: {
column: {
borderWidth: 0,
grouping: false
}
},
And our series:
var orangeData = [1, 3, 8, 13, 11, 13, 15, 25, 29, 31, 27, 25, 16, 11, 10, 4, 4, 8, 2, 1, 1],
greyData = [3, 4, 11, 11, 12, 14, 15, 21, 25, 25, 23, 21, 15, 13, 12, 5, 5, 4, 2, 1, 1];
series: [{
data: orangeData,
color: '#f7931e',
tooltip: {
pointFormatter: function() {
return 'Orange value is higher than grey value by: ' + (orangeData[this.index] - greyData[this.index])
}
}
}, {
type: 'line',
data: orangeData,
color: '#ec1c24',
marker: {
symbol: 'cross',
lineColor: null,
lineWidth: 2
},
enableMouseTracking: false
}, {
data: greyData,
color: '#989898'
}, {
type: 'line',
data: greyData,
color: '#231f20',
enableMouseTracking: false
}]
You can take a look at jsFiddle demo:
https://jsfiddle.net/BlackLabel/xpwdhrvz/
http://jsfiddle.net/vUdGJ/
$(function () {
$('#container').highcharts(
{
"xAxis": {
"startOnTick": true,
"endOnTick": true,
"type": "datetime",
"min": Date.UTC(2014, 1, 2),
"max": Date.UTC(2014, 4, 31)
},
"series": [{
"type": "line",
"data": [
[Date.UTC(2014, 1, 2, 11, 0, 0, 0), 30],
[Date.UTC(2014, 1, 3, 11, 0, 0, 0), 24],
],
}]
}
);
});
If you drag the divider to the left, the first point disappears behind the y-axis.
The model could not be much simpler. Is this a bug?
It's caused by setting startOnTick: true. As you can see, the first tick on a chart is 3rd of Feb (even if you specify to be 2nd of a Feb). Simply remove that option and will be working fine: http://jsfiddle.net/vUdGJ/1/