300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 原生 js 实现类 3d 地图大屏展示自动高亮轮播 显示悬浮提示 tootip 的方案:sv

原生 js 实现类 3d 地图大屏展示自动高亮轮播 显示悬浮提示 tootip 的方案:sv

时间:2022-01-09 23:15:30

相关推荐

原生 js 实现类 3d 地图大屏展示自动高亮轮播 显示悬浮提示 tootip 的方案:sv

要实现的效果

如下图,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="/@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="/@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="/@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="/2000/svg" xmlns:xlink="/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: 22},{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 定位引擎

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。