Highmaps mix Bubble map and maplines causes map offset - highcharts
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/
Related
HIghcharts: Bubble are not showing up beyond scale
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/
Change color in specific columns w/ multiple series
I have two series each with its color and I want to be able to define a different color for both series in a specific column. How can I display the first 3 columns in grey? https://jsfiddle.net/Kagebi/omcqrzsu/ Highcharts.chart('container', { chart: { type: 'column', }, plotOptions: { column: { grouping: false } }, tooltip: { shared: true // true breaks series highliting on hover }, xAxis: { categories: ['24-02', '25-02', '26-02', '27-02', '28-02', '29-02', '01-03', '02-03', '03-03', '04-03', '05-03'] }, series: [ { name: 'Expected', data: [180, 140, 180, 140, 180, 140, 180, 140, 180, 140, 180], color: '#b2dbff', }, { name: 'Current', data: [99, 197, 165, 80, 144, 80, 144, 80, 144, 80, 144], color: '#1d94fa'} ], events:{ load: function() { var point = this.series[0].points[1]; point.update({ color: 'black' }); } }, } )
You can specify the color of each entry in a serie like that: data: [{ name: 'Point 1', color: '#00FF00', y: 0 }, { name: 'Point 2', color: '#FF00FF', y: 5 }] See the documentation here : https://www.highcharts.com/docs/chart-concepts/series (point n°3). I've updated your jsfiddle here with the first three columns in grey: https://jsfiddle.net/0mhnck5L/
How to create vertical merged stacked bar in highchart
How to create vertical merged stacked bar in highchart. Group Padding and Point Padding is not working in Highchart. Expected: Actual: https://jsfiddle.net/sathishkumar_v/3woxcskg/ Highcharts.chart('container', { chart: { type: 'spline' }, title: { text: null }, exporting:{ enabled: false }, legend: { align: 'right', }, xAxis: { categories: [ '6:00AM', '7:00AM', '8:00AM', '9:00AM', '10:00AM', '11:00AM', '12:00AM', '1:00PM', '2:00PM', '3:00PM', '4:00PM', '5:00PM', '6:00PM', '7:00PM', '8:00PM', '9:00PM', '10:00PM' ], plotBands: [ { from: 0, to: 2, color: '#D4E2F2' }, { from: 2, to: 5, color: '#EFC5CA' }, { from: 14, to: 16, color: '#D4E2F2' }, { from: 11, to: 14, color: '#EFC5CA' }, ] }, yAxis: [ { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'TRIPS' } }, { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'DEMAND(PAX)' }, opposite: true } ], tooltip: { shared: true, valueSuffix: ' units' }, credits: { enabled: false }, plotOptions: { areaspline: { fillOpacity: 0.5 } }, series: [{ name: 'Planned Trips', yAxis: 1, data: [0, 35, 80, 120, 230, 210, 175, 155, 130, 120, 150, 100, 175, 160, 175, 140, 180], color: '#304894', }, { name: 'Actual Trips', ///yAxis: 2, data: [0, 145, 165, 180, 190, 225, 195, 175, 150, 190, 200, 230, 175, 90, 115, 140, 120], color: '#6FD1F6', }, { name: 'Actual Demand', type: 'column', stacking: 'normal', data: [0, 25, 35, 80, 130, 150, 115, 100, 80, 70, 30, 80, 100, 75, 60, 75, 40], color: '#6FD1F6', pointWidth: 10 }, { type: 'column', name: 'Planned Demand', stacking: 'normal', data: [3, 35, 11, 11, 12, 14, 15, 21, 25, 25, 23, 21, 15, 13, 12, 5, 5], color: '#304894', pointWidth: 10 }] }); I am using https://github.com/bellstrand/highcharts-border-radius for the border radius top - left and right
You can use a wrapper function to do this, like so: (function (H) { H.wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) { console.log(this) let borderRadius = this.points[0].pointWidth / 2; this.options.borderRadius = borderRadius; $.each(this.points, function (i,point) { point.shapeArgs.y -= borderRadius; //move the point down by borderRadius pixels point.shapeArgs.height += borderRadius * 2; //add borderRadius pixels to the total height of a point (to cover the gap) }); proceed.apply(this, Array.prototype.slice.call(arguments, 1)); }); }(Highcharts)); Which takes half of the initial width of the bar as the border radius and covers the gaps they would leave. (function (H) { H.wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) { let borderRadius = this.points[0].pointWidth / 2; this.options.borderRadius = borderRadius; $.each(this.points, function (i,point) { point.shapeArgs.y -= borderRadius; //move the point down by borderRadius pixels point.shapeArgs.height += borderRadius * 2; //add borderRadius pixels to the total height of a point (to cover the gap) }); proceed.apply(this, Array.prototype.slice.call(arguments, 1)); }); }(Highcharts)); Highcharts.chart('container', { chart: { type: 'spline' }, title: { text: null }, exporting:{ enabled: false }, legend: { align: 'right', }, xAxis: { categories: [ '6:00AM', '7:00AM', '8:00AM', '9:00AM', '10:00AM', '11:00AM', '12:00AM', '1:00PM', '2:00PM', '3:00PM', '4:00PM', '5:00PM', '6:00PM', '7:00PM', '8:00PM', '9:00PM', '10:00PM' ], plotBands: [ { from: 0, to: 2, color: '#D4E2F2' }, { from: 2, to: 5, color: '#EFC5CA' }, { from: 14, to: 16, color: '#D4E2F2' }, { from: 11, to: 14, color: '#EFC5CA' }, ] }, yAxis: [ { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'TRIPS' } }, { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'DEMAND(PAX)' }, opposite: true } ], tooltip: { shared: true, valueSuffix: ' units' }, credits: { enabled: false }, plotOptions: { areaspline: { fillOpacity: 0.5 } }, series: [{ name: 'Planned Trips', yAxis: 1, data: [0, 35, 80, 120, 230, 210, 175, 155, 130, 120, 150, 100, 175, 160, 175, 140, 180], color: '#304894', }, { name: 'Actual Trips', ///yAxis: 2, data: [0, 145, 165, 180, 190, 225, 195, 175, 150, 190, 200, 230, 175, 90, 115, 140, 120], color: '#6FD1F6', }, { name: 'Actual Demand', type: 'column', stacking: 'normal', data: [0, 25, 35, 80, 130, 150, 115, 100, 80, 70, 30, 80, 100, 75, 60, 75, 40], color: '#6FD1F6', pointWidth: 10 }, { type: 'column', name: 'Planned Demand', stacking: 'normal', data: [3, 35, 11, 11, 12, 14, 15, 21, 25, 25, 23, 21, 15, 13, 12, 5, 5], color: '#304894', pointWidth: 10 }] }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <script src="https://code.highcharts.com/modules/export-data.js"></script> <div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div> Working example: https://jsfiddle.net/ewolden/3woxcskg/19/ If you have several charts in your page but only want this to affect one chart you can set a custom flag for that. You would then need to: In the chart config: chart: { customFlag: 'wrap', ... }, And in the wrapper: (function (H) { H.wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) { console.log(this) if(this.chart.options.chart.customFlag == 'wrap') { let borderRadius = this.points[0].pointWidth / 2; this.options.borderRadius = borderRadius; $.each(this.points, function (i,point) { point.shapeArgs.y -= borderRadius; //move the point down by borderRadius pixels point.shapeArgs.height += borderRadius * 2; //add borderRadius pixels to the total height of a point (to cover the gap) }); } proceed.apply(this, Array.prototype.slice.call(arguments, 1)); }); }(Highcharts)); (function (H) { H.wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) { console.log(this) if(this.chart.options.chart.customFlag == 'wrap') { let borderRadius = this.points[0].pointWidth / 2; this.options.borderRadius = borderRadius; $.each(this.points, function (i,point) { point.shapeArgs.y -= borderRadius; //move the point down by borderRadius pixels point.shapeArgs.height += borderRadius * 2; //add borderRadius pixels to the total height of a point (to cover the gap) }); } proceed.apply(this, Array.prototype.slice.call(arguments, 1)); }); }(Highcharts)); Highcharts.chart('container', { chart: { type: 'spline', customFlag: 'wrap' }, title: { text: null }, exporting:{ enabled: false }, legend: { align: 'right', }, xAxis: { categories: [ '6:00AM', '7:00AM', '8:00AM', '9:00AM', '10:00AM', '11:00AM', '12:00AM', '1:00PM', '2:00PM', '3:00PM', '4:00PM', '5:00PM', '6:00PM', '7:00PM', '8:00PM', '9:00PM', '10:00PM' ], plotBands: [ { from: 0, to: 2, color: '#D4E2F2' }, { from: 2, to: 5, color: '#EFC5CA' }, { from: 14, to: 16, color: '#D4E2F2' }, { from: 11, to: 14, color: '#EFC5CA' }, ] }, yAxis: [ { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'TRIPS' } }, { gridLineDashStyle: 'longdash', // tickPositions: [0, 100, 200, 300, 400, 500, 600, 700, 800], title: { text: 'DEMAND(PAX)' }, opposite: true } ], tooltip: { shared: true, valueSuffix: ' units' }, credits: { enabled: false }, plotOptions: { areaspline: { fillOpacity: 0.5 } }, series: [{ name: 'Planned Trips', yAxis: 1, data: [0, 35, 80, 120, 230, 210, 175, 155, 130, 120, 150, 100, 175, 160, 175, 140, 180], color: '#304894', }, { name: 'Actual Trips', ///yAxis: 2, data: [0, 145, 165, 180, 190, 225, 195, 175, 150, 190, 200, 230, 175, 90, 115, 140, 120], color: '#6FD1F6', }, { name: 'Actual Demand', type: 'column', stacking: 'normal', data: [0, 25, 35, 80, 130, 150, 115, 100, 80, 70, 30, 80, 100, 75, 60, 75, 40], color: '#6FD1F6', pointWidth: 10 }, { type: 'column', name: 'Planned Demand', stacking: 'normal', data: [3, 35, 11, 11, 12, 14, 15, 21, 25, 25, 23, 21, 15, 13, 12, 5, 5], color: '#304894', pointWidth: 10 }] }); Highcharts.chart('container2', { chart: { type: 'column' }, title: { text: 'Monthly Average Rainfall' }, subtitle: { text: 'Source: WorldClimate.com' }, xAxis: { categories: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], crosshair: true }, yAxis: { min: 0, title: { text: 'Rainfall (mm)' } }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>', footerFormat: '</table>', shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0 } }, series: [{ name: 'Tokyo', data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4] }, { name: 'New York', data: [83.6, 78.8, 98.5, 93.4, 106.0, 84.5, 105.0, 104.3, 91.2, 83.5, 106.6, 92.3] }, { name: 'London', data: [48.9, 38.8, 39.3, 41.4, 47.0, 48.3, 59.0, 59.6, 52.4, 65.2, 59.3, 51.2] }, { name: 'Berlin', data: [42.4, 33.2, 34.5, 39.7, 52.6, 75.5, 57.4, 60.4, 47.6, 39.1, 46.8, 51.1] }] }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <script src="https://code.highcharts.com/modules/export-data.js"></script> <div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div> <div id="container2" style="min-width: 310px; height: 400px; margin: 0 auto"></div> Working example: https://jsfiddle.net/ewolden/3woxcskg/24/
How to create dashed bar graph in highcharts
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.
Color grouped bars slightly different in HighCharts
I have a grouped HighCharts bar chart that is colored by group. For example all bars in group 1 are blue, group 2 is gray, group 3 is green. Now I just need to have slight variations of color within each group. So group 1 would have a dark blue bar, regular blue bar, and a light blue bar. Then group 2 would have dark gray, regular gray, and light gray. I can't figure out how to get those color variations within each group. Thanks to anyone in advance for looking into this. $(function () { var pWidth = 20, // points width pPadding = 5, // point padding gPadding = 15, // group padding categories = ['Africa', 'America', 'Asia', 'Europe', 'Oceania'], series = [{ name: 'Year 1800', data: [107, 55, 635, 203, 30], color: 'red' }, { name: 'Year 1900', data: [133, 156, 550, 408, 45] }, { name: 'Year 2008', data: [500, 604, 404, 632, 60] }], sLen = series.length, cLen = categories.length; var catWidth = 2 * gPadding + sLen * (pPadding + pWidth); // 2*gPadding = left group padding + right group padding // sLen * pPadding = distance between points // sLen * pWidth = space taken by points itselves // cat width = one category width/height var height = catWidth * cLen; var groupPadding = gPadding / catWidth; $('#container').highcharts({ chart: { height: height, type: 'bar', marginLeft: 0, marginRight: 0, marginTop: 0, marginBottom: 0, spacingTop: 0, spacingBottom: 0, spacingLeft: 0, spacingRight: 0 }, title: { text: '' }, xAxis: { categories: categories, title: { text: null, }, labels: { enabled: false } }, yAxis: { title: { text: null, }, labels: { enabled: false } }, plotOptions: { bar: { pointWidth: pWidth, groupPadding: groupPadding }, series: { colorByPoint: true } }, legend: { enabled: false }, credits: { enabled: false }, series: series }); }); Here is a fiddle.
You can specify each color in the point configuration. Instead of: data: [107, 55, 635, 203, 30], Use: data: [{y: 107, color: 'someColor'}, {y: 55, color: 'someColor'}, {y: 635, color: 'someColor'}, {y: 203, color: 'someColor'}, {y: 30, color: 'someColor'}], Here's an updated fiddle where I've done the first group with shades of blue.