• 如何实现3D地图效果
  • 发布于 2个月前
  • 132 热度
    0 评论
背景
随着数据可视化近几年的快速发展,我们逐渐不再满足于仅仅是将抽象的数据用简单的图表展示出来;而是希望能够将抽象无序的数据通过可视化、可操作、可交互且视觉效果炫酷的形式表达出来。一般我们会通过通过数据分类、交互设置等附加形式将数据呈现给用户以易于感知的图形符号,让用户交互且直观的理解数据。

做什么?
最近接到一个需求,要求快速交付一套数据驾驶舱。其中主屏视图是由 3D 地图 + 雷达图 + 折线图组成;主要用于展示各区划指标数据及指标变化趋势,同时点击地图或雷达图需要有交互效果,设计图如下。

当接到这种需要快速交付且视觉&交互要求相对高的需求时,首先需要分析本次需求的目的是什么、需要突出什么以及重点是什么;能够通过什么方式能够快速进行交付。

分析
主视图是 3D 地图,地图上需要显示对应区划下的得分以及其组成的指标得分。具体交互为可选择区划查看该区划下各指标得分,也可选择某指标查看全部区划的单一指标得分;并且地图并不要求有可翻转旋转,放大缩小等交互效果。所以为了能够快速交付,地图可以考虑使用伪 3D 效果替代真实 3D 来实现。

拆解
那么如果需要使用平面地图来实现设计效果,就需要通过多层地图叠加来实现伪 3D 的视觉效果,下面就需要将 3D 地图进行拆解。从原型说明我们知道:
1.指标得分总分 100,分为 5 档,每 20 分一档,并且每个区间固定颜色,包块区划边界也需要根据数据显示对应颜色;
2.整个地图边界统一颜色;
3.地图需要有空间角度&厚度,营造3D效果;

4.点击地图后需要突出该区划;


怎么做?
上面我们将地图进行了拆解,发现只需要将 3 ~ 4 层平面地图进行叠加再加上点击效果即可实现需求。开干。

分层
第一层图层
第一层为主视图,主要渲染 5 种色块分布和具体数据信息:
{
  name: "浙江",
  type: "map",
  map: "zhejiang",
  zlevel: 99,
  aspectScale,
  zoom,
  layoutCenter,
  layoutSize,
  roam,
  showLegendSymbol: false,
  silent: true,
  itemStyle: {
    normal: {
      // sth...
    },
    emphasis: {
      areaColor: "transparent",
    },
  },
  markPoint: {
    symbol: "none",
  },
},

第二层图层
第二层图层展示黑底及 5 色区间边框:
{
  map: "zhejiang",
  aspectScale,
  zoom,
  layoutCenter,
  layoutSize,
  roam,
  show: true,
  zlevel: 3,
  label: {
    emphasis: {
      show: false,
    },
  },
  itemStyle: {
    normal: {
      // sth...
    },
  },
},

第三层图层
第三层图层展示透明底及纯色边框:
{
  map: "zhejiangOverview",
  aspectScale,
  zoom,
  layoutCenter,
  layoutSize,
  roam,
  show: true,
  zlevel: 2,
  label: {
    emphasis: {
      show: false,
    },
  },
  itemStyle: {
    normal: {
      // sth...
    },
    emphasis: {
      areaColor: "transparent",
    },
  },
},

合并

按照上述步骤我们能够得到一个不同区划根据数值展示不同颜色的平面地图;

将 3 层地图进行叠加拼接即可:

伪3D
现在我们还缺少地图厚度,我们只需要模拟出地图厚度即可得要一个伪 3D 地图,以下提供两种方案实现。

方案一
再增加第四层地图,通过调整 layoutCenter 使得地图之间错位造成视觉上的 3D 效果。
{
  map: "zhejiang",
  aspectScale,
  zoom,
  layoutCenter: ["50.6%", "52%"],
  layoutSize,
  roam,
  show: true,
  zlevel: 3,
  label: {
    emphasis: {
      show: false,
    },
  },
  itemStyle: {
    normal: {
      // sth...
    },
  },
},

方案二
方案二最省事,可以直接使用背景图贴在地图下即可,但是这套方案有缺陷即:在不同尺寸的屏幕下背景图存在错位(PS: 可以通过媒体查询解决)。
@media screen and (min-height: 1080px) and (max-height: 1080px) {
  .map-echart {
    cursor: pointer;
    background-image: url(XXXXX);
    background-repeat: no-repeat;
    background-size: 110%;
    background-position: -46px 194px;
  }
}

点击高亮
基础效果
增加点击高亮效果,只需要在点击地图时在 series 中的 data 里增加 itemStyle 样式即可;

加钱效果
除了上面说的基础效果,可以通过在 series 中增加散点(气泡)图或者带有涟漪特效动画的散点(气泡)图同时可以设置背景为图片,来增加视觉效果:
// 带有涟漪特效动画的散点(气泡)图
{
  type: "effectScatter",
  coordinateSystem: "geo",
  rippleEffect: {
    color: "#fff",
    scale: 6,
    brushType: "stroke", // fill
  },
  showEffectOn: "render",
  zlevel: 9999,
  symbol: "circle",
  symbolSize: [15, 5],
},
  // 散点(气泡)图
{
  type: "scatter",
  coordinateSystem: "geo",
  symbolSize: [32, 41],
  zlevel: 9999,
  symbol: "image://图片链接",
  symbolOffset: [0, -20],
  showEffectOn: "render",
  rippleEffect: {
    brushType: "stroke",
  },
  hoverAnimation: true,
},
const imageDom = new Image();
imageDom.src = 'https://XXXXXXX';
imageDom.alt = '图片';

 color: {
 image: imageDom,
 repeat: 'repeat'
}

至此我们就能快速的完成一个伪 3D 地图效果的页面。可以看出,根据实际情况对需求进行拆解,可以在一定程度上将某一类需求拆解并转化为另外一种实现成本更低、复杂程度更低、能够快速实现上线的真实需求。

Tips

1、zlevel 决定地图的层级,值越大地图靠上;2、map 对应地图的 Json 文件,文件可从阿里云下载,注意是否需要包含子区域;

3、visualMap 决定颜色的分段,根据以下规则进行划分:

备注: lt(小于,less than),gt(大于,greater than),lte(小于等于 less than or equals),gte(大于等于,greater than or equals)
 // 堆代码 duidaima.com
 visualMap: {
  type: "piecewise",
  show: false,
  pieces: [
    {
      lt: 20,
      color: XXX,
    },
    {
      gte: 20,
      lt: 40,
      color: XXX,
    },
    {
      gte: 40,
      lt: 60,
      color: XXX,
    },
    {
      gte: 60,
      lt: 80,
      color: XXX,
    },
    {
      gte: 80,
      color: XXX,
    },
  ],
},

用户评论