要实现的效果

如下图,3d 地图高亮自动轮播,展示白云区各个镇街的人口数局。

原由

为什么想到这个方案,是因为我在用 echarts-gl 实现 3d 地图效果的过程中,我发现通过 dispatchAction 触发不了 3d 的高亮。不知道大家有没有遇到,所以我实现不出自动轮播的 3d 效果,因为显示悬浮提示 tooltip 不出来,必须要 hover 的时候才行。(不知道是不是我的配置问题,如果大家有好的 3d 地图自动轮播方案,欢迎在下面评论分享。)

于是,我在想能不能用 svg 直接渲染成 dom,然后在定时的修改对应 dom 的样式,并且显示出对应标签的 tooltip 提示。我觉得可以一试,于是我找了一些相关资料,简单的实现了一下。

代码实现

1、修改地图的视觉提供地图的 svg 图

由于 svg 的字符过多,博客放不下,这里就不展示 svg 的全部代码了。

主要的就是为了方便激活地块,快速的找到 dom 元素,我们需要给地块加一些 id,还有标签定位 tooltip,方便获取跟标记。

<g id="plot" name="地块" transform="translate(0.000000, -0.000000)"><g id="plot_yuncheng"><use fill="#eee" fill-rule="evenodd" xlink:href="#path-47"></use><use fill="black" fill-opacity="1" filter="url(#filter-48)" xlink:href="#path-47"></use><use stroke="#aaa" stroke-width="2" xlink:href="#path-47"></use></g>
...
</g>
<g id="label" name="标签" transform="translate(80.000000, 128.000000)"><g id="label_renhe" transform="translate(176.000000, 81.000000)"><g id="编组-77备份-3"><path d="M71.0581411,-0.5 L71.0581411,24.3372098 L-0.5,24.3372098 L-0.5,-0.5 L71.0581411,-0.5 Z"id="矩形备份-37" stroke="#fff" fill="orange"></path><pathd="M70.5581411,19.8643415 L70.5581411,23.8372098 L66.8722681,23.8372098 L70.5581411,19.8643415 Z M3.68587304,0 L0,3.97286831 L0,0 L3.68587304,0 Z"id="形状结合" fill="#fff"></path></g><text id="人和镇" font-family="PingFangSC-Medium, PingFang SC" font-size="14" font-weight="400" fill="#FFFFFF"><tspan x="14.1116282" y="16.9186049">人和镇</tspan></text></g>...
</g>

2、引入 popper.js 定位引擎

官网:TOOLTIP & POPOVER POSITIONING ENGINE

第一种使用方式:

npm i @popperjs/core -s
import { createPopper } from '@popperjs/core';
const popcorn = document.querySelector('#popcorn');
const tooltip = document.querySelector('#tooltip');
createPopper(popcorn, tooltip, {placement: 'top',
});

第二种使用方式:

在 html 中引入 popper.js 定位引擎:

<script src="https://unpkg.com/@popperjs/core@2"></script>
<!DOCTYPE html>
<html><head><title>Popper Tutorial</title></head><body><button id="button" aria-describedby="tooltip">My button</button><div id="tooltip" role="tooltip">My tooltip</div><script src="https://unpkg.com/@popperjs/core@2"></script><script>const button = document.querySelector('#button');const tooltip = document.querySelector('#tooltip');const popperInstance = Popper.createPopper(button, tooltip);</script></body>
</html>

3、激活地块

需要给 use 元素设置激活的 style 属性

let activedStyle = "fill:blue"; // 地块激活样式
// 激活地块
function addPlotActive(index) {baiyunSvgDom.getElementById(`plot_${plotArrs[index]}`).getElementsByTagName('use')[0].setAttribute("style", activedStyle);
}

4、tooltip 定位

我们需要找到当前轮播的标签元素,以及提示框的元素,然后通过 Popper.createPopper 设置就行。

// 设置标签提示定位
function setCreatePopper() {Popper.createPopper(baiyunSvgDom.getElementById(`label_${plotArrs[index]}`), mapTooltipsDom, {placement: 'top-start',positionFixed: true});
}

5、自动轮播跟赋值

自动轮播的话主要需要注意第一次跟最后一次就行,另外赋值的时候,innerHTML 不要写错了。具体代码的话看逻辑代码即可。

逻辑代码

这里的代码缺失了 svg 里的内容。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>SVG地图轮播</title><style>.svg-geo-map-tooltips {min-width: 160px;background-color: rgba(0,0,0,.8);border-radius: 8px;text-align: center;padding: 18px 8px;transition: .4s;left: 20px !important;bottom: 5px !important;}.svg-geo-map-tooltips .name {font-size: 16px;font-weight: 400;color: #ffffff;height: 22px;line-height: 22px;margin-bottom: 8px;}.svg-geo-map-tooltips .value {color: #ffffff;}.svg-geo-map-tooltips .value .num {font-size: 24px;font-weight: bold;height: 32px;line-height: 32px;}.svg-geo-map-tooltips .value .unit {font-size: 14px;}</style><script src="https://unpkg.com/@popperjs/core@2"></script>
</head>
<body><div class='svg-geo-map-chart'><svg id="baiyunSvg" width="804px" height="597px" viewBox="0 0 804 597" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg><!-- 提示 --><div class="svg-geo-map-tooltips"><div class="name"></div><div class="value"><span class="num"></span><span class="unit">人</span></div></div></div><script>let curPlotName = ""; // 当前激活的地块名let curPlotValue = 0; // 当前激活的地块服务量数let interval = 1000; // 时间间隔毫秒数let index = 0; // 播放所在下标let timer = null;let activedStyle = "fill:blue"; // 地块激活样式let baiyunSvgDom = null; // svg 的 dom 元素let mapTooltipsDom = null; // 提示的 dom 元素let baiyunPlotDataList = [{id: "jianggao",name: "江高镇",value: 883945},{id: "renhe",name: "人和镇",value: 4567992},{id: "taihe",name: "太和镇",value: 4567323},{id: "zhongluotan",name: "钟落潭镇",value: 497863},{id: "longgui",name: "龙归街",value: 3486257},{id: "dayuan",name: "大源街",value: 897435},{id: "sanyuanli",name: "三元里街",value: 46809544},{id: "songzhou",name: "松洲街",value: 123403},{id: "jingtai",name: "景泰街",value: 342256677},{id: "tongde",name: "同德街",value: 234677},{id: "huangshi",name: "黄石街",value: 976542},{id: "tangjing",name: "棠景街",value: 33456},{id: "xinshi",name: "新市街",value: 3455602},{id: "tonghe",name: "同和街",value: 487654},{id: "jingxi",name: "京溪街",value: 3876735},{id: "yongping",name: "永平街",value: 6677544},{id: "jiahe",name: "嘉禾街",value: 34526784},{id: "junhe",name: "均禾街",value: 8756534},{id: "shijing",name: "石井街",value: 220232},{id: "jinsha",name: "金沙街",value: 3352256},{id: "yuncheng",name: "云城街",value: 335677},{id: "helong",name: "鹤龙街",value: 334225},{id: "baiyunhu",name: "白云湖街",value: 34556},{id: "shimen",name: "石门街",value: 1354667}]; // 默认地块数据let plotArrs = baiyunPlotDataList.map(el => el.id); // 地块的id数据// 数字加千位分隔符function numToThsSprtr (num) {let res = num.toString().replace(/\d+/, function (n) { // 先提取整数部分return n.replace(/(\d)(?=(\d{3})+$)/g, function ($1) {return $1 + ',';});})return res;}// 初始化function initRender() {// 获取 dom 元素baiyunSvgDom = document.getElementById('baiyunSvg');mapTooltipsDom = document.querySelector('.svg-geo-map-tooltips');// 地块的id数据plotArrs = baiyunPlotDataList.map(el => el.id);// 初始化激活颜色this.addPlotActive(index);// 赋值setPlotValue();console.log(index, plotArrs[index], curPlotName, curPlotValue);// 初始化定位this.setCreatePopper();}// 设置轮播function setIntervalSvg() {timer = setInterval(() => {// 先清除上一次的激活效果if(index !== -1) {removePlotActive(index);}// 索引自增index++;// 地块激活this.addPlotActive(index);// 赋值setPlotValue();console.log(index, plotArrs[index], curPlotName, curPlotValue);// 进行提示定位this.setCreatePopper();// 处理最后一个地块激活问题if(index === plotArrs.length - 1) {let tempTimer = setTimeout(() => {// 移除地块最后一个的激活removePlotActive(plotArrs.length - 1);clearTimeout(tempTimer);}, interval);index = -1;}}, interval);}// 激活地块function addPlotActive(index) {baiyunSvgDom.getElementById(`plot_${plotArrs[index]}`).getElementsByTagName('use')[0].setAttribute("style", activedStyle);}// 赋值function setPlotValue() {curPlotName = baiyunPlotDataList[index].name;curPlotValue = numToThsSprtr(baiyunPlotDataList[index].value);mapTooltipsDom.querySelector('.name').innerHTML = `${curPlotName}常住人口`;mapTooltipsDom.querySelector('.num').innerHTML = curPlotValue;}// 移除地块激活function removePlotActive(index) {baiyunSvgDom.getElementById(`plot_${plotArrs[index]}`).getElementsByTagName('use')[0].removeAttribute("style", activedStyle);}// 设置标签提示定位function setCreatePopper() {Popper.createPopper(baiyunSvgDom.getElementById(`label_${plotArrs[index]}`), mapTooltipsDom, {placement: 'top-start',positionFixed: true});}// 初始化initRender();// 设置轮播setIntervalSvg();</script>
</body>
</html>

完整代码

里面包含视频,图片,全部代码,由于展示不了 svg 的全部代码。下面我整理了资源,有需要的可以下载。

完整资源下载

参考资料

  • TOOLTIP & POPOVER POSITIONING ENGINE

原生 js 实现类 3d 地图大屏展示自动高亮轮播、显示悬浮提示 tootip 的方案:svg + popper.js 定位引擎相关推荐

  1. 基于js+echarts实现数据可视化大屏展示

    vue+echarts大屏数据可视化展示点击进入 写在前面: 本项目中使用的是echarts图表库,ECharts 提供了常规的折线图.柱状图.散点图.饼图.K线图,用于统计的盒形图,用于地理数据可视 ...

  2. react + dataV + three.js + blender 实现3D可视化大屏效果

    效果图 3D 可视化展示是一个很不错的方向,但是纯three.js 开发效率低,简单展示类的可视化,可以考虑使用blender 等3D 绘制工具,快速,高效. 文章目录 效果图 前言 一.DataV ...

  3. 智慧管廊可视化3d监控大屏展示的应用及优势

    随着城市建设越来越智能化,管廊设备及线路越来越多,动环检测数据越来越多,对管廊管理手段面临极大的挑战.智慧管廊可视化三维虚拟检修管控系统集宏观场景.设备及数据进行三维仿真还原和可视化实时呈现,实现日常 ...

  4. 使用Three.js实现炫酷的赛博朋克风格3D数字地球大屏

    声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 背景 近期工作有涉及到数字大屏的需求,于是利用业余时间,结合 Three.js ...

  5. 如何使用 WEB 技术编写前端代码,实现大屏展示和地图显示功能

    使用 WEB 技术编写前端代码实现大屏展示和地图显示功能可以采用以下步骤: 使用 HTML.CSS.JavaScript 等前端技术构建页面布局和样式. 使用 JavaScript 库或框架,如 jQ ...

  6. iPortal地图大屏自定义组件示例--立体地图

    作者:刘大 通过iPortal地图大屏自定义组件要点梳理这篇文章,我们基本了解了地图大屏如何进行自定义,也准备好了开发环境,那我们就接着进行实际操作下吧. 立体建筑实质是mapboxgl中的" ...

  7. Three.js之GeoJson 3D地图数据可视化飞行线实战

    Three.js之GeoJson 3D地图数据可视化飞行线实战 GeoJSON是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法的地理空间信息数据交换格式.GeoJSON对象可 ...

  8. web大屏展示用到的组件_基于 HTML5 的工业组态高炉炼铁 3D 大屏可视化

    前言 在大数据盛行的现在,大屏数据可视化也已经成为了一个热门的话题.大屏可视化可以运用在众多领域中,比如工业互联网.医疗.交通.工业控制等等.将各项重要指标数据以图表.各种图形等形式表现在一个页面上, ...

  9. 3D可视化大屏是如何实现的?

    3D可视化是指拥有3D效果的数据可视化,对于所要展示的数据可视化内容还原出真实场景,并实时接入数据,在面对复杂操作时灵活应对,使得整个场景在大屏上的展示更具立体.更具科技感.更具易用性. 物联网时代, ...

最新文章

  1. 【camera】5.相机内嵌图像处理(ISP)介绍
  2. foreach遍历进阶_“枚举器“/GetEnumerator()方法
  3. go.sum中特殊hash如何计算
  4. cad显示有点暗_CAD参照的图框颜色太暗怎么调整?
  5. Struts2的自动装配
  6. emui内核支持kvm吗_KVM虚拟化详解
  7. python如何在列表中查找元素位置_查找元素在list中的位置以及折半查询
  8. idea git和svn间切换
  9. 三菱FX系列PLC-编程1
  10. ORACLE11g升级19c,报ORA-01017
  11. 转录组:STAR-Fusion融合基因
  12. App登录功能(用户名+密码)
  13. CSS实现播放暂停按钮样式
  14. android配置jni cmake,Android JNI之青春期 Cmake(android studio)
  15. 箱线图(Boxplot)
  16. 自己动手写一个番茄小助手
  17. Excel文件显示“文件已损坏,无法打开”情况的解决办法
  18. 双击打开Excel文件要反应很久之后才能打开,先开excel程序,再打开文件就很快的解决办法...
  19. python 使用wxpy实现获取微信好友列表 头像 群成员
  20. 程序员七夕特刊,绝无狗粮添加

热门文章

  1. steamVR学习笔记
  2. 一二三四五六七八酒十!
  3. DayOfWeek转换成日一二三四五六
  4. git 创建本地仓库与 gitcafe 关联
  5. 复变函数 | 第二部分 复变函数与解析函数
  6. 我们参观机器人产业园的感想_产业园观后感
  7. matlab如何进对图像进行透视变换,如何根据已知的内在和外在参数在Matlab中进行透视校正?...
  8. 充分利用好自己的阿里云服务器,让服务器的价值最大化
  9. 【Educoder作业】CC++函数实训
  10. 创建一个简单的守护进程