Search code examples
highchartsbubble-chart

Highmaps mix Bubble map and maplines causes map offset


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


Solution

  • 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/