You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Highcharts世界地图drillup函数导致地图方向异常求助

Highcharts地图钻取返回后方向异常的修复方案

问题说明

基于Highcharts实现的世界地图钻取功能,钻取到子区域地图正常,但点击钻取返回按钮后,世界地图的方向出现翻转/偏移问题。

原因分析

钻取子地图时,会加载子地图的hc-recommended-mapview配置,其中包含子地图的投影(projection)设置。返回顶层地图时,仅恢复了视图范围,未显式恢复世界地图的原始投影配置,导致地图渲染方向异常。

修复步骤

  1. 初始化时完整保存世界地图的mapView配置(包含投影信息)
  2. 在afterDrillUp事件中,更新mapView时同时恢复原始投影设置

修改后的完整代码

const drilldown = async function (e) {
    if (!e.seriesOptions) {
        const chart = this,
            mapKey = `countries/${e.point.drilldown}/${e.point.drilldown}-all`;

        // 错误处理超时,成功加载后清除
        let fail = setTimeout(() => {
            if (!Highcharts.maps[mapKey]) {
                chart.showLoading(`
                    <i class="icon-frown"></i>
                    加载${e.point.name}失败
                `);
                fail = setTimeout(() => {
                    chart.hideLoading();
                }, 1000);
            }
        }, 3000);

        // 显示加载动画
        chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>');

        // 加载钻取地图数据
        const topology = await fetch(
            `https://code.highcharts.com/mapdata/${mapKey}.topo.json`
        ).then(response => response.json());

        const data = Highcharts.geojson(topology);

        // 设置模拟数据
        data.forEach((d, i) => {
            d.value = i;
        });

        // 应用子地图推荐视图
        chart.mapView.update(
            Highcharts.merge(
                {
                    insets: undefined,
                    padding: 0
                },
                topology.objects.default['hc-recommended-mapview']
            )
        );

        // 隐藏加载并添加钻取系列
        chart.hideLoading();
        clearTimeout(fail);
        chart.addSeriesAsDrilldown(e.point, {
            name: e.point.name,
            data,
            dataLabels: {
                enabled: true,
                format: '{point.name}'
            }
        });
    }
};

// 钻取返回时恢复顶层地图视图
const afterDrillUp = function (e) {
    if (e.seriesOptions.custom && e.seriesOptions.custom.mapView) {
        e.target.mapView.update(
            // 完整恢复原始mapView配置,包括投影
            e.seriesOptions.custom.mapView,
            false
        );
    }
};

(async () => {

    const topology = await fetch(
        'https://code.highcharts.com/mapdata/custom/world-highres3.topo.json'
    ).then(response => response.json());

    const data = Highcharts.geojson(topology);

    // 保存完整的原始mapView配置(包含projection)
    const mapView = {
        ...topology.objects.default['hc-recommended-mapview'],
        // 显式指定世界地图的投影,确保返回时正确渲染
        projection: {
            name: 'Miller'
        }
    };

    // 设置钻取关联键
    data.forEach((d, i) => {
        d.drilldown = d.properties['hc-key'];
        d.value = i; // 模拟数据
    });

    // 初始化地图
    Highcharts.mapChart('container', {
        chart: {
            events: {
                drilldown,
                afterDrillUp
            },
            backgroundColor: '#B6DCF4'
        },

        title: {
            text: 'Highcharts 地图钻取示例'
        },
        legend: {
            enabled: false
        },

        mapView,

        mapNavigation: {
            enabled: true,
            buttonOptions: {
                verticalAlign: 'bottom'
            }
        },

        plotOptions: {
            map: {
                states: {
                    hover: {
                        color: '#EEDD66'
                    }
                }
            }
        },

        series: [{
            data,
            nullColor: 'white',
            dataLabels: {
                enabled: true,
                format: '{point.properties.postal-code}'
            },
            custom: {
                mapView
            }
        }],

        drilldown: {
            activeDataLabelStyle: {
                color: '#FFFFFF',
                textDecoration: 'none',
                textOutline: '1px #000000'
            },
            breadcrumbs: {
                floating: true,
                relativeTo: 'spacingBox'
            },
            drillUpButton: {
                relativeTo: 'spacingBox',
                position: {
                    x: 0,
                    y: 60
                }
            }
        }
    });

})();

关键修改点

  • 保存mapView时,显式包含projection配置(世界地图默认使用Miller投影)
  • afterDrillUp事件中,直接使用完整的原始mapView配置进行更新,不再合并部分配置,确保投影设置被正确恢复

内容的提问来源于stack exchange,提问作者arunmmanoharan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:19:59