首页 > 其他分享 >echarts渲染世界地图+中国省份轮廓|中国地图数据文件解码|世界地图文件

echarts渲染世界地图+中国省份轮廓|中国地图数据文件解码|世界地图文件

时间:2022-10-16 22:13:02浏览次数:45  
标签:数据文件 地图 echarts 世界地图 var world options

echarts渲染世界地图+中国省份轮廓|中国地图数据文件解码|世界地图文件

近期接到大屏的需求,进入地图时展示世界地图,放大中国区域之后展示中国省份轮廓,然后,就卡住了。 也许大家并不想听我的心灵路程,只想知道答案,所以下面就直接写解决步骤了,但还是希望如果这篇文章帮你解决了问题之后,能回头来这里给个反馈,你们的鼓励是写作者的动力。

这篇文章需要具备的基础:我默认您已经具备初级前端开发的基础和已经成功渲染出来了一个世界地图或中国地图。

解决数据问题

众所周知,echarts有世界地图的数据,也有中国地图的数据,我们只需要将两者结合起来就好了。

中国地图数据地址:import china from "echarts/map/json/china.json"

世界地图数据地址:import world from "echarts/map/json/world.json"

对,就是这么简单,他们都存在于npm包中,当我们找到这个数据时,发现了另一个问题:中国地图是加密的,世界地图是明文的。 解密的代码在这里,关于这个代码是如何得到的,下面会说明。

function decodePolygon(coordinate, encodeOffsets, encodeScale) {
    var result = [];
    var prevX = encodeOffsets[0];
    var prevY = encodeOffsets[1];
    for (var i = 0; i < coordinate.length; i += 2) {
        var x = coordinate.charCodeAt(i) - 64;
        var y = coordinate.charCodeAt(i + 1) - 64;
        // ZigZag decoding
        x = (x >> 1) ^ -(x & 1);
        y = (y >> 1) ^ -(y & 1);
        // Delta deocding
        x += prevX;
        y += prevY;
        prevX = x;
        prevY = y;
        // Dequantize
        result.push([x / encodeScale, y / encodeScale]);
    }
    return result;
}
function decode(json) {
    if (!json.UTF8Encoding) {
        return json;
    }
    var encodeScale = json.UTF8Scale;
    if (encodeScale == null) {
        encodeScale = 1024;
    }
    var features = json.features;
    for (var f = 0; f < features.length; f++) {
        var feature = features[f];
        var geometry = feature.geometry;
        var coordinates = geometry.coordinates;
        var encodeOffsets = geometry.encodeOffsets;
        for (var c = 0; c < coordinates.length; c++) {
            var coordinate = coordinates[c];
            if (geometry.type === "Polygon") {
                coordinates[c] = decodePolygon(
                    coordinate,
                    encodeOffsets[c],
                    encodeScale
                );
            } else if (geometry.type === "MultiPolygon") {
                for (var c2 = 0; c2 < coordinate.length; c2++) {
                    var polygon = coordinate[c2];
                    coordinate[c2] = decodePolygon(
                        polygon,
                        encodeOffsets[c][c2],
                        encodeScale
                    );
                }
            }
        }
    }
    // Has been decoded
    json.UTF8Encoding = false;
    return json;
}

如何使用呢?看这里

let data = decode(china) // 打印这个data,得到就是解密之后的中国地图数据了

如何合并?看这里

import echarts from "echarts";
var chart;
let data = decode(china); // 这里调用的函数就是上面解密的函数
let worldAndChina = Object.assign({}, world); // 原本的world还需要用 所以这里用了一个深拷贝赋值世界地图数据
worldAndChina.features = worldAndChina.features.concat(data.features); // 对,就是这么简单用concat把两者的features合并起来就可以了
chart = echarts.init(this.$refs.chart);
echarts.registerMap("world", worldAndChina);

删除其他国家label

到这里,我们已经成功渲染出了世界地图和中国地图,但还会有一点点小小的问题,我们只希望渲染出来中国区域的label而不是整个数据的label,应该如何做呢?方法有很多,我采取的是简单粗暴的一种:

world.features.map((item, index) => {
    item.properties.name = "";
    return item;
});

添加事件

恭喜你,到现在你已经得到了一个完整的世界地图加中国地图的数据,只差一个事件切换了,放大的时候显示中国地图的数据,缩小的时候隐藏,代码如下:

chart.on("georoam", function(params) {
    var options = chart.getOption(); //获得option对象
    if (!params.originX) return; // 不是缩放就返回
    let zoom = options.geo[0].zoom;
    if (zoom > 4.5) {
        let data = decode(china);
        let worldAndChina = Object.assign({}, world);
        worldAndChina.features = worldAndChina.features.concat(data.features);
        echarts.registerMap("world", worldAndChina);
        options.geo[0].label.show = true;
    } else {
        echarts.registerMap("world", world);
        options.geo[0].label.show = false;
    }
    chart.setOption(options);
});

先揭秘一下解码的方法是如何找到的。

对比两条数据,会发现中国地图中多了一个UTF8Encoding这个属性,之后就全局匹配这个属性,在echarts这个包中找,很快就可以找到相关代码了,复制粘贴就好了。就这么简单。

等你解决完目前的燃眉之急之后,希望你可以回来看看我遇到的哪些坑,好的和不好的,对我们而言,都是宝贵的经验。

方案一:同时控制两个地图

其实刚开始做的方案是想通过两个地图的切换来实现这个效果,放弃这个方案的原因是当我们缩放的时候没有办法控制小地图的外轮廓永远和大地图都是对齐的。 当然,我并没有一步一步的写代码,而是自己拿笔把要做的事情一步步的写了下来,写到缩放的地方走死了,就放弃了。这对于我的思考也是宝贵的经验,以后遇到类似的问题就会直接pass该方案了。

方案二:融合数据

就是你们看到的上面的思路,将两套数据融合了起来,但之前思考的方案是将中国地图的数据塞到中国轮廓的地方,尝试了好多次,数据格式都没有问题,还是不可以。到目前为止,我仍然觉得这种方案理论是可以的,但确实不可以,所以只能采取上面的方式了。

方案三:切换地图->巧妙的绕过需求

刚开始走方案二的时候没有走通,就很沮丧。但需求迫在眉睫,所以想到了一种折中的方案,折中方案可能别的需求会用到,但也有很多漏洞和需要优化的地方,也简单说一下吧。

我们在放大地图查看中国地图的时候,因为屏幕尺寸的原因,我们是看不到中国之外的区域的,所以可以通过监听地图的缩放事件,到达一定比例的时候直接setoption改变地图,将world更改为china,但其中也涉及到了一些问题,比如放大之后按照当前的级别切换到中国地图的级别会是一个很小的级别,需要手动的改一下,不作为该篇文章的主要内容,只贴一下代码:

let prevMap = "";
chart.on("georoam", function(params) {
    var options = chart.getOption(); //获得option对象
    if (!params.originX) return; // 不是缩放就返回
    let zoom = options.geo[0].zoom;
    if (options.geo[0].map == "china" && zoom > 1.3) {
        return;
    }
    let chinaMap = {
        map: "china",
        label: {
            show: false,
            fontSize: 16,
            normal: {
                fontSize: 18,
                show: true,
                color: "#cae3ff"
            },
            emphasis: {
                show: true,
                color: "#cae3ff"
            }
        },
        roam: true,
        itemStyle: {
            normal: {
                areaColor: "#082161",
                borderColor: "#00a8ff",
                borderWidth: 1
            },
            emphasis: {
                areaColor: "#082161"
            }
        },
        zoom: 1.3
    };
    let worldMap = {
        map: "world",
        label: {
            show: false,
            fontSize: 16,
            normal: {
                fontSize: 18,
                show: false,
                color: "#cae3ff"
            },
            emphasis: {
                show: false,
                color: "#cae3ff"
            }
        },
        roam: true,
        itemStyle: {
            normal: {
                areaColor: "#082161",
                borderColor: "#00a8ff",
                borderWidth: 1
            },
            emphasis: {
                areaColor: "#082161"
            }
        }
    };
    if (zoom > 4.5) {
        options.geo = chinaMap;
    } else {
        options.geo = worldMap;
    }
    if (prevMap == "china" && options.geo.map == "world") {
        options.geo.zoom = 4.5;
    }
    prevMap = options.geo.map;
    chart.setOption(options); //设置option
});

如果不是我的领导一直鼓励我,还有别的更好的方案,我可能就止步于方案三了,也不会将此文章呈现在大家面前,也很感激每一个读到此处的你们,阅读者是写作者的动力。

都看到这里了,还不关注一下嘛?以后还有更多的技术分享等着你们喔~

https://zhuanlan.zhihu.com/p/379985536

标签:数据文件,地图,echarts,世界地图,var,world,options
From: https://www.cnblogs.com/sunny3158/p/16797366.html

相关文章

  • Echarts入门教程精简实用系列
    Echarts入门教程精简实用系列引语:echarts.js是百度团队推出的一款用于图表可视化的插件,用于以图表的形式展现数据,功能强大,上手简单1、从官方网站中下载所需的echarts.js......
  • 使用阿里的中国地图的json替换echarts中的china.js中的内容
    使用阿里的中国地图的json替换echarts中的china.js中的内容文末有相关资源这两天公司要求做一个地图展示要求每个省份根据用户量多少展示不同的颜色,且给每个市级单位加......
  • 解决Vue打印带有echarts的pdf问题
    智能中医项目中开发一个打印报告,报告里有患者的基本信息、病况和echarts展示的一些图表,解决了一下午终于解决。彩色打印效果如下:总体效果还是不错,汇总一下处理方法。修......
  • ECharts笔记
    ECharts笔记使用五步骤:引入echart.js→准备显示的盒子→初始化echarts实例对象→准备配置项→将配置项设置给echarts实例对象通用配置(所有配置项都可以添加)//......
  • echarts多表联动初步
    在大数据的学习过程中,后台数据分析、输出很重要,但最终是将其表现在图表上,使用echarts进行数据可视化官网上给出的数据可视化是饼图和折线图的联动,饼图和其他图的联动基本......
  • React魔法堂:echarts-for-react源码略读
    前言在当前工业4.0和智能制造的产业升级浪潮当中,智慧大屏无疑是展示企业IT成果的最有效方式之一。然而其背后怎么能缺少ECharts的身影呢?对于React应用而言,直接使用ECharts......
  • echarts图表自动轮播toolTip,鼠标悬浮则停止
    背景:最近做了很多用【echarts】组件写图表的需求,然后需要自动轮播toolTip,以及鼠标移入自动轮播停止,鼠标移出,自动轮播开始等需求。下面是方法的代码:(function(){let......
  • 动态传参的Echarts图表重载、重新绘制,二次查询时echarts上回遗留上次查询的结果
    动态传参的Echarts图表,需要根据不同参数改变图表的构建时,发现只通过varmyChart=echarts.init(document.getElementById('main'));//<div>容器id:main实例化,在第二次查......
  • Pyecharts交互式图表引入
    什么是Pyecharts?Pyecharts是百度开源数据可视化项目与Python的有效结合,具有良好的交互性,精巧的图表设计,在创建具有交互式图表时,成为数据可视化首选工具。本文创建一组成绩......
  • transform: scale(x,y)缩放后致使echarts图表模糊
    1、将canvas转换成svg在初始化时就指定渲染器为svg:echarts.init(dom,null,{renderer:'svg'});第一个参数是:echarts的容器;第二个参数是:颜色主题......