echarts实现伪3D立体地图+标点涟漪效果

分享一个基于echarts实现的伪3D地图并实现自定义坐标点和坐标点涟漪效果,实现效果如下:

要实现上图中的效果,我们需要配置三种type的echarts图,即:map、effectScatter、scatter,废话不多说,我们直接开干!(echarts版本:^5.4.0,vue版本:2.x)

初始化

初始化部分代码比较简单,不过还是有几点需要注意:

  • 我这里的地图渲染是借助DataV生成的,绘制地图的方法不是唯一,选择最适合你当前业务场景或你自己用起来最顺手的一种即可;
  • initMap方法中接收的info参数是我这边服务端传递的数据,主要是需要标注的坐标点的经纬度和坐标点名称;
  • mapData中对应的key:name、value等是按照echarts文档中散点图和涟漪图配置项进行配置的而不是随意定义的;

代码如下:

xml 复制代码
<template>
    <div class="map-box">
      <div ref="map3d" style="width: 100%; height: 100%;" />
    </div>
</template>
<script>
    import * as echarts from 'echarts'
    data() {
      return {
        // 考点标记图片
        examSite: require('@/assets/screen/exam-site.png')
      }
    },
    methods: {
        /**
         * 初始化地图
         * @param info 坐标点信息
         */
        async initMap(info) {
            const mapJson = (await axios.get('https://geo.datav.aliyun.com/areas_v3/bound/152500_full.json')).data
            const mapChart = echarts.init(this.$refs.map3d)
            mapChart.showLoading()
            // 注册地图
            echarts.registerMap('MapAddress', mapJson)
            const { organizationName, latitude, longitude } = info
            // 地图点坐标,用于散点图和涟漪图
            const mapData = [
              {
                name: organizationName,
                value: [longitude, latitude],
                type: 'normal',
                img: this.examSite
              }
            ]
            const option = { ... }
            mapChart.setOption(option)
            mapChart.hideLoading()
            window.addEventListener('resize', function() {
                 mapChart.resize()
            })
        }
    }
</script>

到这里我们初始化就完成了,其实页面上啥也没有-_-,与其说是初始化,不如说是前期的一些参数接收和配置,接下来才是重头戏

地图配置项

我们在文件目录中新建一个叫做mapOptions的js文件来专门放置地图的一些配置项。

yaml 复制代码
export const mapOptions = {
  // 地理坐标系组件
  geo: [
    {
      // registerMap注册的地图名称
      map: 'MapAddress',
      // 是否可缩放
      roam: false,
      // 地图层级
      zlevel: 5,
      label: {
        normal: {
          show: false
        },
        emphasis: {
          show: false
        }
      },
      left: 10,
      right: 0,
      top: 0,
      bottom: 20,
      itemStyle: {
        areaColor: '#01215c',
        borderWidth: 3,
        borderColor: '#9ffcff',
        // 阴影颜色
        shadowColor: 'rgba(9, 140, 255, 0.9)',
        shadowBlur: 14
      },
      // 高亮样式
      emphasis: {
        itemStyle: {
          areaColor: '#01215c'
        }
      }
    },
    // 这一个是为了仿3D地图,故创建一个低层级的一模一样的地图
    {
      map: 'MapAddress',
      roam: false,
      zlevel: 4,
      label: {
        normal: {
          show: false
        },
        emphasis: {
          show: false
        }
      },
      left: 10,
      right: 0,
      top: 0,
      bottom: 20,
      itemStyle: {
        areaColor: '#01215c',
        shadowColor: '#9ffcff',
        shadowOffsetX: 0,
        shadowOffsetY: 6
      }
    }
  ]
}

在代码中可以看到,我在geo中配置了两个相同的地图,仅仅是改变了层级和itemStyle的配置,然后我们将这个mapOptions文件引入进我们地图组件的option里面

ini 复制代码
const option = {
    ...mapOptions
}

就可以得到下图效果:

此时可以看到边框就会有出现立体效果了,所以说这是伪3D,因为我们是基于平面来实现的。但是现在很明显地图太亮了,并且地图内部的边框和边缘的边框是一样粗的,很影响感观,所以我们对这个地图进行样式上的一些优化。

series type: 'map'

对于地图内容样式的一些优化很简单,大家对照echarts官网中series,type: 'map'的配置项文档对照来看就能看懂,所以不需要过多描述,我认为需要注意的配置项也写了注释。

yaml 复制代码
const option = {
    ...mapOptions,
    series: [
        // map
        {
          type: 'map',
          map: 'MapAddress',
          zlevel: 5,
          // 这个参数用于 scale 地图的长宽比
          aspectScale: 0.75,
          left: 10,
          right: 0,
          top: 0,
          bottom: 20,
          label: {
            normal: {
              show: false
            },
            emphasis: {
              show: false,
              textStyle: {
                color: '#fff'
              }
            }
          },
          roam: false,
          itemStyle: {
            areaColor: '#01215c',
            borderColor: 'rgba(61, 197, 225)',
            borderWidth: 1
          },
          emphasis: {
            disabled: true,
            itemStyle: {
              areaColor: '#01215c'
            }
          },
          // 图形是否不响应和触发鼠标事件,默认为 false,即响应和触发鼠标事件。
          silent: true
        }
    ]

当我们写完了上面的配置后,就会发现我们的地图变得稍微好看了一些,至少中间的边框不会那么粗了。

地图我们渲染好了后就该标记坐标点了,这里我们用到的是scatter散点图,也是对照官方文档进行配置项的编写,同样很简单。

series type: 'scatter'

散点图的配置项直接接着上面map的配置项后面写就可以了,同样我也将type: 'scatter'的文档地址放在这里:echarts.apache.org/zh/option.h...

javascript 复制代码
// 散点图
{
  type: 'scatter',
  coordinateSystem: 'geo',
  zlevel: 6,
  itemStyle: {
    color: '#f00',
    opacity: 1
  },
  // 自定义点样式
  symbol: (value, params) => {
    return `image://${params.data.img}`
  },
  // 动态改变点大小
  symbolSize: (value, params) => {
    return params.data.type === 'normal' ? [130, 30] : [127, 30]
  },
  // 点偏移量
  symbolOffset: [45, -15],
  label: {
    show: true,
    formatter: (params) => {
      return params.data.name
    },
    color: '#fff',
    fontSize: 16,
    align: 'center',
    offset: [10, 0]
  },
  z: 9999,
  data: mapData
}

现在我们就可以看到我们自定义图标的坐标点已经渲染在了地图上,解释一下代码中的动态改变点大小,其实是一种很粗糙的处理方式,考虑到我们坐标点名称长度可能会不一样,所以对symbolSize做了处理,这个处理仅仅是满足我当前的项目。

最后我们将涟漪图配置项按照上面的方式写入代码:

series type: 'effectScatter'

css 复制代码
// 波纹涟漪
{
  type: 'effectScatter',
  coordinateSystem: 'geo',
  zlevel: 5,
  symbol: 'circle',
  rippleEffect: {
    color: '#FDD835',
    number: 2,
    scale: 8,
    brushType: 'fill'
  },
  itemStyle: {
    color: '#FDD835'
  },
  data: mapData
}

至此,我们就能实现文章开头的效果了!

内容不少,但不难,主要就是echarts的配置项,对照官方文档慢慢写就能写出来

写在最后

🥰🥰🥰感谢能看到最后的jym,这篇文章主要是记录自己在项目实现地图的过程,方便以后在其他项目中要用到时可以随时查找,写的不好望多多谅解😅,如果对你们也能有一定的帮助那我就太太太太荣幸了🤘

相关推荐
Redstone Monstrosity几秒前
字节二面
前端·面试
东方翱翔8 分钟前
CSS的三种基本选择器
前端·css
Fan_web31 分钟前
JavaScript高级——闭包应用-自定义js模块
开发语言·前端·javascript·css·html
yanglamei196238 分钟前
基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue
前端·数据库·flask
千穹凌帝39 分钟前
SpinalHDL之结构(二)
开发语言·前端·fpga开发
冯宝宝^43 分钟前
基于mongodb+flask(Python)+vue的实验室器材管理系统
vue.js·python·flask
dot.Net安全矩阵1 小时前
.NET内网实战:通过命令行解密Web.config
前端·学习·安全·web安全·矩阵·.net
Hellc0071 小时前
MacOS升级ruby版本
前端·macos·ruby
前端西瓜哥1 小时前
贝塞尔曲线算法:求贝塞尔曲线和直线的交点
前端·算法
又写了一天BUG1 小时前
npm install安装缓慢及npm更换源
前端·npm·node.js