javascriptsvghighchartsbubble-charthighmaps

Highmaps label centering in irregular path


While working on Highmap to display some sort of data according of an area coverage. I was able to create the map with bubble chart type but I face one major problem, alignment! Each bubble is aligned to the area/path it belongs to; basically I have two series s1: {id, z, path} s2: {id, z, path} where these series are joinedBy: id field. I think Highmaps calculates the center according to the width and height of the path resulting some bubbles to be placed in another area. Is there any ways I can fix this by setting offset left/top per each path, since the paths are irregular and could have a different shapes?

Please refer to the attached image and this jsfiddle: http://jsfiddle.net/ycsp27cL/14/ Gray Bubble: actual bubbles created by Highmaps.  Red Bubble: the expected bubble area

Gray Bubble: actual bubbles created by Highmaps.
Red Bubble: the expected bubble area


Solution

  • It is possible to add:

        properties: {
            "hc-middle-x":0.5,
            "hc-middle-y":0.8
        },
    

    to data point so you can establish position of center, used later in Highcharts. Scale is from 0 to 1, where 0 is most left/top and 1 is most right/bottom position of a path for x/y.

    JSFiddle: http://jsfiddle.net/ycsp27cL/15/


    Update for TopoJSON.

    Since around late 2021, TopoJSON has been supported as one of the map file formats and is the main map format for the Highcharts Maps' Map Collection.

    To adjust the default dataLabel position in TopoJSON file you should be looking at modifying values of hc-middle-lon and hc-middle-lat that are the label geo coordinates.

    Example:

    Let's move the Spain label a bit down so that on the initial zoom of the map the Portugal label is visible too. To do this you could modify the map data like:

    topology.objects.default.geometries[6].properties['hc-middle-lat'] = 39;
    

    (async () => {
    
        const topology = await fetch(
            'https://code.highcharts.com/mapdata/custom/europe.topo.json'
        ).then(response => response.json());
        
        // Move the dataLabel default position
        topology.objects.default.geometries[6].properties['hc-middle-lat'] = 39;
    
        // Prepare demo data. The data is joined to map using value of 'hc-key'
        // property by default. See API docs for 'joinBy' for more info on linking
        // data and map.
        const data = [
            ['dk', 10], ['fo', 11], ['hr', 12], ['nl', 13], ['ee', 14], ['bg', 15],
            ['es', 116], ['it', 17], ['sm', 18], ['va', 19], ['tr', 20], ['mt', 21],
            ['fr', 22], ['no', 23], ['de', 24], ['ie', 25], ['ua', 26], ['fi', 27],
            ['se', 28], ['ru', 29], ['gb', 30], ['cy', 31], ['pt', 32], ['gr', 33],
            ['lt', 34], ['si', 35], ['ba', 36], ['mc', 37], ['al', 38], ['cnm', 39],
            ['nc', 40], ['rs', 41], ['ro', 42], ['me', 43], ['li', 44], ['at', 45],
            ['sk', 46], ['hu', 47], ['ad', 48], ['lu', 49], ['ch', 50], ['be', 51],
            ['kv', 52], ['pl', 53], ['mk', 54], ['lv', 55], ['by', 56], ['is', 57],
            ['md', 58], ['cz', 59]
        ];
    
        // Create the chart
        Highcharts.mapChart('container', {
            chart: {
                map: topology
            },
    
            title: {
                text: 'Highcharts Maps basic demo'
            },
    
            subtitle: {
                text: 'Source map: <a href="http://code.highcharts.com/mapdata/custom/europe.topo.json">Europe</a>'
            },
    
            mapNavigation: {
                enabled: true,
                buttonOptions: {
                    verticalAlign: 'bottom'
                }
            },
    
            colorAxis: {
                min: 0
            },
    
            series: [{
                data: data,
                name: 'Random data',
                states: {
                    hover: {
                        color: '#BADA55'
                    }
                },
                dataLabels: {
                    enabled: true,
                    format: '{point.name}'
                }
            }]
        });
    
    })();
    #container {
        height: 500px;
        min-width: 310px;
        max-width: 800px;
        margin: 0 auto;
    }
    
    .loading {
        margin-top: 10em;
        text-align: center;
        color: gray;
    }
    <script src="https://code.highcharts.com/maps/highmaps.js"></script>
    <script src="https://code.highcharts.com/maps/modules/accessibility.js"></script>
    
    <div id="container"></div>

    JSFiddle demo: https://jsfiddle.net/BlackLabel/g7feujmq/