echarts 画3d地球 且画线

3,014 阅读1分钟

前言

有前端朋友问我,这种效果能简单实现吗?那必须能,安排。

注意

需要额外引用:

https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js https://echarts.baidu.com/resource/echarts-gl-latest/dist/echarts-gl.min.js https://www.makeapie.com/dep/echarts/map/js/world.js

代码

CSS

#main{
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background: #000;
}

HTML

<div id="main" ></div>

JS

// 城市、国家 地理坐标
    const geoCoordMap = {
        '上海': [120.52, 30.40],
        '北京': [115.25, 39.90],
        '重庆': [107.7539, 30.1904],
        '芬兰': [24.909912, 60.169095],
        '美国': [-100.696295, 33.679979],
        '日本': [139.710164, 35.706962],
        '韩国': [126.979208, 37.53875],
        '瑞士': [7.445147, 46.956241],
        '德国': [13.402393, 52.518569],
        '英国': [-0.126608, 51.208425]
    };

    let CQData = [
        [{
            name: '重庆'
        }, {
            name: "英国",
            value: 70
        }],
        [{
            name: '重庆'
        }, {
            name: "芬兰",
            value: 80
        }],
        [{
            name: '重庆'
        }, {
            name: "美国",
            value: 80
        }]
    ];

    let BJData = [
        [{
            name: '北京'
        }, {
            name: "日本",
            value: 30
        }],
        [{
            name: '北京'
        }, {
            name: "德国",
            value: 80
        }]
    ];

    let SHData = [
        [{
            name: '上海'
        }, {
            name: "韩国",
            value: 80
        }]
    ];
    // 根据起始位置,获得线的地理位置
    function convertData(data) {

        let res = [];
        for (let i = 0; i < data.length; i++) {

            let dataItem = data[i];
            let [fromCoord, toCoord] = [geoCoordMap[dataItem[1].name], geoCoordMap[dataItem[0].name]];

            if (fromCoord && toCoord) res.push([fromCoord, toCoord]);
        }
        return res;
    }

    let [series2d, series3d] = [
        [],
        []
    ];
    [
        ['重庆', CQData],
        ['北京', BJData],
        ['上海', SHData]
    ].forEach(function(item) {

        // 2d平面地图 + 散点
        series2d.push({
            type: 'effectScatter',
            coordinateSystem: 'geo',
            zlevel: 3,
            rippleEffect: {
                brushType: 'stroke'
            },
            label: {
                fontSize: 24,
                show: true,
                position: 'right',
                formatter: '{b}'
            },
            itemStyle: {
                normal: {
                    color: 'rgba(250,250,250,0.8)'
                }
            },
            data: item[1].map(function(dataItem) {

                return {
                    name: dataItem[1].name,
                    value: geoCoordMap[dataItem[1].name],
                    symbolSize: dataItem[1].value / 4
                };
            })
        }, {
            type: 'effectScatter',
            coordinateSystem: 'geo',
            zlevel: 3,
            rippleEffect: {
                brushType: 'stroke'
            },
            label: {
                show: true,
                position: 'left',
                fontSize: 18,
                formatter: '{b}'
            },
            itemStyle: {
                normal: {
                    color: '#fff'
                }
            },
            data: [{
                name: item[0],
                value: geoCoordMap[item[0]],
                symbolSize: parseInt(Math.random() * 20 + 10),
                label: {
                    position: 'right'
                }
            }]
        });

        // 3d连线
        series3d.push({
            type: 'lines3D',
            effect: {
                show: true,
                period: 3,
                trailLength: 0.1
            },
            lineStyle: {
                color: "rgba(38 ,122, 219, 0.8)",
                width: 1.5,
                opacity: 0.6
            },
            tooltip: {
                show: false
            },
            data: convertData(item[1])
        }, {
            type: 'scatter3D',
            name: 'location',
            coordinateSystem: 'globe',
            blendMode: 'lighter',
            symbolSize: 10,
            itemStyle: {
                color: 'red',
                opacity: 1
            },
            label: {
                show: true,
                formatter: param => param.data.name
            },
            data: [{
                name: '中国',
                value: [116.4551, 40.2539, 0]
            }]
        })
    });

    let chart = echarts.init(document.createElement('canvas'), null, {
        width: 4096,
        height: 2048
    });

    // 添加2d地图 + 散点图
    chart.setOption({
        backgroundColor: '#040438',
        tooltip: {
            backgroundColor: 'red',
            alwaysShowContent: true
        },
        geo: {
            type: 'map',
            map: 'world',
            left: 0,
            top: 0,
            right: 0,
            bottom: 0,
            zoom: 0,
            boundingCoords: [
                [-180, 90],
                [180, -90]
            ],
            roam: false,
            itemStyle: {
                borderColor: "rgb(38 122 219 / 0.4)",
                borderWidth: 1,
                areaColor: "rgb(4 4 63 / 0.6)",
            },
            label: {
                fontSize: 24
            }
        },
        series: series2d
    });

    // 添加地球
    option = {
        backgroundColor: 'transparent',
        globe: {
            baseTexture: chart,
            top: 'middle',
            left: 'center',
            displacementScale: 0,
            shading: 'color',
            viewControl: {
                distance: 240,
                autoRotate: false
            }
        },
        roam: true,
        series: series3d
    };
    var myChart = echarts.init(document.getElementById('main'))
    myChart.setOption(option, true);

示例

2.gif

参考文献

echarts.apache.org/zh/index.ht…