使用echartgl构建3D中国地图

先上个最终效果图:
在这里插入图片描述

这周研究了 3D 地图,并在地图上添加柱状图,带有涟漪特效动画的散点图,过程比较波折,遇到不少坑,所以在此记录一下。

**坑一:**涟漪特效的水波纹是二维图表effectScatter,不能用在 echarts 中 geo3D 上,解决方法,把二维地图加上effectScatter,整体作为 geo3D 的背景纹理,贴在上面。

注意: 使用在colorMaterial 属性仅在 shading属性为’color’时有效。

geo3D: {
	map: 'china',
    shading: `color`,
    colorMaterial: {
         detailTexture: mapBg, // 纹理贴图
         textureTiling: 1 // 默认为1,也就是拉伸填满。大于 1 的时候,数字表示纹理平铺重复的次数
     },
}

注意: 使用平铺需要 detailTexture 的高宽是 2 的 n 次方。例如 512512,如果是 200200 的纹理无法使用平铺。

const canvas = document.createElement(`canvas`);
var mapBg = echarts.init(canvas, null, {
    width: 1024,
    height: 1024
});
const chartOption = LoadMapping(name, data);
mapBg.setOption(chartOption);

loadMapping 里是 geo 的地图配置。

这里有一个问题,尽管 mapBg 设置的 1024*1024,textureTiling选择的也是拉伸填满,依然没有铺满,研究了好久,发现 geo里也要设置宽度为 1024 才可以。

geo: {
     map: 'china',
     top: '0',
     width: 1024,
}

坑二: 需求需要地图上的柱子是圆柱形,bar3D 默认长方体柱子,找了好久,没找到能做成圆柱体的方法,只能通过bevelSize, bevelSmoothness 这两个属性配合形成圆柱(不太标准的圆柱)

{
       type: "bar3D",
        coordinateSystem: 'geo3D',
        barSize: 1.2,
        bevelSize: 1,
        bevelSmoothness: 10,
}

**坑三:**地图旋转一周就停了,通过设置 minBeta,maxBeta的值,设置 360 的多少倍就旋转多少圈。

minAlpha: -360000,
maxAlpha: 360000,
minBeta: -360000,
maxBeta: 360000,

**坑四:**下钻功能,click事件失效,网上搜到 getZr() 方法,但是只能获取到点击的x.y坐标,获取不到点击区域的名称,满足不了需求。

网上找到方法说换个版本:

https://echarts.baidu.com/resource/echarts-gl-latest/dist/echarts-gl.min.js

试了下,用这个版本再配合 click 点击事件,果然可以,但是地图颜色失效,变成了白色。

这应该是echarts-gl.min.js包的问题,目前没有找到解决方法,好在点击柱子可以触发click,暂时先这样,大神们如有解决办法可以给我留言。

myChart.on('click', function (param) {
    console.log('下钻成功');
    console.log(param);
});

上完整js代码:

var convertData = function (data) {
    var res = [];
     for (var i = 0; i < data.length; i++) {
         var geoCoord = geoCoordMap[data[i][0].name];
         if (geoCoord) {
             res.push({
                 name: data[i][0].name,
                 value: geoCoord.concat(data[i][0].value)
             });
         }
     }
     console.log(res);
     return res;
 };
 const chinaName = 'china';
 const chinaData = convertData(chinaDatas);
 const myChart = echarts.init(document.getElementById('main'));

 LoadMap(chinaName, chinaData, myChart);

// 下钻
window.onload = function () {
   myChart.on('click', function (param) {
       console.log('下钻成功');
       console.log(param);
       // console.log(param.name);
   });
}

// 配置二维地图贴图
function LoadMapping(name, data) {
    var chartOption = {
        geo: {
            show: true,
            map: name,
            top: '0',
            width: 1024,
            label: {
                position: 'top',
                distance: 5,
                normal: {
                    show: true,
                    textStyle: {
                        color: '#fff'
                    }
                },
                emphasis: {
                    textStyle: {
                        color: '#fff'
                    }
                }
            },
            itemStyle: {
                normal: {
                    areaColor: {
                        type: 'radial',
                        x: 0.5,
                        y: 0.5,
                        r: 0.8,
                        colorStops: [{
                            offset: 0,
                            color: '#09132c' // 0% 处的颜色
                        }, {
                            offset: 1,
                            color: '#274d68'  // 100% 处的颜色
                        }],
                    },
                },
            },
            emphasis: {
                label: {
                    show: true,
                    textStyle: {
                        color: '#fff',
                        fontSize: 13,
                        backgroundColor: 'rgba(0,23,11,1)'
                    }
                },
                itemStyle: {
                    areaColor: '#f00', // 高亮时地图板块颜色改变
                }
            },

        },

        series: [
            {
                type: `effectScatter`,
                coordinateSystem: `geo`,
                showEffectOn: 'render',
                zlevel: 1,
                rippleEffect: {
                    period: 5,
                    scale: 4,
                    brushType: 'fill'
                },

                hoverAnimation: true,
                label: {
                    normal: {
                        formatter: '{b}',
                        position: 'bottom',
                        offset: [15, 0],
                        color: '#fff',
                        show: true,
                        fontSize: 16
                    },
                },
                itemStyle: {
                    normal: {
                        color: '#1DE9B6',
                        // color: function (value) { //随机颜色
                        //     return "#" + ("00000" + ((Math.random() * 16777215 + 0.5) >> 0).toString(16)).slice(-6);
                        // },
                        shadowBlur: 10,
                        shadowColor: '#333'
                    }
                },
                symbolSize: 16,
                data: data,
            },

        ]
    }

    return chartOption;
}


function LoadMap(name, data, myChart) {
    // 先渲染贴图
	const canvas = document.createElement(`canvas`);
	var mapBg = echarts.init(canvas, null, {
	    width: 1024,
	    height: 1024
	});
    const chartOption = LoadMapping(name, data);
    mapBg.setOption(chartOption);
    // 3D地图渲染
    option = {
        backgroundColor: 'rgb(0,0,0,0)',
        visualMap: [{
            type: 'continuous',
            seriesIndex: 0,
            text: ['bar3D'],
            calculable: true,
            min: 1000,
            max: 5000,
            inRange: {
                color: ['#4ab2e5', '#5abead', '#f56321', '#f58f0e', '#d5b314', '#b9be23']
            }
        }],
        geo3D: {
            map: name,
            roam: true,
            shading: `color`,
            width: 1024,
            boxHeight: 20,
            itemStyle: {
                color: '#5a8dce',
                opacity: 1,
                borderWidth: 1,
                borderColor: '#96ebf7'
            },
            emphasis: { //当鼠标放上去  地区区域是否显示名称
                label: {
                    show: true,
                    textStyle: {
                        color: '#fff',
                        fontSize: 13,
                        backgroundColor: 'rgba(0,23,11,1)'
                    }
                },
                itemStyle: {
                    areaColor: '#498fde', // 高亮时地图板块颜色改变
                }
            },
            colorMaterial: {
                detailTexture: mapBg, // 纹理贴图
                textureTiling: 1 // 纹理平铺,1是拉伸,数字表示纹理平铺次数
            },
            environment: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                offset: 0, color: '#176186' // 天空颜色
            }, {
                offset: 0.5, color: '#176186' // 地面颜色
            }, {
                offset: 1, color: '#07101b' // 地面颜色
            }], false),
            viewControl: {
                projection: 'perspective',
                autoRotate: true,//会有自动旋转查看动画出现,可查看每个维度信息
                autoRotateDirection: 'ccw',//物体自传的方向。默认是 'cw' 也就是从上往下看是顺时针方向,也可以取 'ccw',既从上往下看为逆时针方向。
                autoRotateSpeed: 2,//物体自传的速度
                autoRotateAfterStill: 1,//在鼠标间静止操作后恢复自动旋转的时间隔。在开启 autoRotate 后有效。
                // distance:90,//默认视角距离主体的距离(常用)
                // alpha:90,//视角绕 x 轴,即上下旋转的角度(与beta一起控制视野成像效果)
                beta: 90,//视角绕 y 轴,即左右旋转的角度。
                // center:[]//视角中心点,旋转也会围绕这个中心点旋转,默认为[0,0,0]。
                // zlevel://组件所在的层。
                minAlpha: -360000,
                maxAlpha: 360000,
                minBeta: -360000,
                maxBeta: 360000,
                animation: true,
                animationDurationUpdate: 1000, // 过渡动画的时长。[ default: 1000 ]
                animationEasingUpdate: 'cubicInOut'
            },
            light: {
                main: {
                    intensity: 1,
                },
                ambient: {
                    intensity: 1,
                    quality: 'high'
                },
                ambientCubemap: {
                    exposure: 1.0,
                    diffuseIntensity: 2,
                    specularIntensity: 2
                }
            }
        },
        series: [
            {
                type: "bar3D",
                coordinateSystem: 'geo3D',
                barSize: 1.2, 
                bevelSize: 1,
                bevelSmoothness: 10,
                minHeight: 1,
                // shading: 'color',
                // shading: 'lambert',
                shading: "realistic",
                silent: false,//图形是否不响应和触发鼠标事件
                opacity: 0.6,
                itemStyle: {
                    opacity: 0.6,
                },
                label: {
                    show: false,
                    formatter: function (data) {
                        var res = '订单量:' + data.name + " " + data.value[2]
                        return res
                    },
                },
                data: data,
            },
        ],
    }
    myChart.setOption(option, true);
}


  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhuantou000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值