说说如何基于 Vue.js 、element UI 与 Echart 实现一张地图展示多个区域提示框
1 需求变更

省级区域图实现效果给客户看了之后,客户希望可以一次性把所有区域的数据展示在地图周围。
原计划是想用 echart 的 tooltip 提示框组件来实现。实验之后发现 echart 地图只支持弹出一个 tooltip 提示框。这样显然无法满足要求。
转而考虑使用 element UI 的 tooltip 组件。
实现效果:

2 element UI Tooltip 组件
Tooltip 组件常用于展示鼠标 hover 时的提示信息。
Tooltip 组件使用 content 属性来决定 hover 时的提示信息。由 placement 属性决定展示效果: placement 属性值为:方向 - 对齐位置;四个方向: top、left、right、bottom ;三种对齐位置: start , end ,默认为空。如 placement ="left-end ",则提示信息出现在目标元素的左侧,且提示信息的底部与目标元素的底部对齐。
它包含以下属性参数:
| 参数 | 类型 | 可选值 | 默认值 | 说明 |
|---|---|---|---|---|
| effect | String | dark/light | dark | 主题颜色,目前只提供了两种主题。 |
| content | String | - | - | 显示的内容。 |
| placement | String | top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end | bottom | Tooltip 的出现位置。 |
| value | Boolean | - | false | 是否可见。 |
| disabled | Boolean | - | false | Tooltip 是否可用。 |
| offset | Number | - | 0 | 出现位置的偏移量。 |
| transition | String | - | el-fade-in-linear | 定义渐变动画。 |
| visible-arrow | Boolean | - | true | 是否显示 Tooltip 箭头。 |
| popper-options | Object | - | { boundariesElement: ‘body’, gpuAcceleration: false } | popper.js 的参数 |
| open-delay | Number | - | 0 | 延迟出现,单位毫秒。 |
| manual | Boolean | - | false | 手动控制模式,设置为 true 后,mouseenter 和 mouseleave 事件将不会生效。 |
| popper-class | String | - | - | 为 Tooltip 的 popper 添加类名。 |
| enterable | Boolean | - | true | 鼠标是否可进入到 tooltip 中。 |
| hide-after | number | - | 0 | Tooltip 出现后自动隐藏延时,单位毫秒,为 0 则不会自动隐藏。 |
| tabindex | number | - | 0 | Tooltip 组件的 tabindex。 |
如果需要显示多行内容,可以使用具名 slot 来分发 content ,从而替代 tooltip 中的 content 属性。示例代码:
<el-tooltip placement="top">
<div slot="content">多行信息<br/>第二行信息</div>
<el-button>Top center</el-button>
</el-tooltip>
- 因为之前用的是深蓝背景,所以这里把 effect 设置为 dark,让其看起来更协调。
- 因为要显示多行内容,所以打算采用具名 slot 来分发 content。
- 希望加载页面后,自动出现提示框,所以把 value 设为可见。
- 为了避免鼠标滑动到提示框后,提示框自动消失,我们把 manual 设置为手动控制。
- 因为地图上的每个区域位置不同,所以我们必须根据提示框所在的位置,来调整 placement 的位置,让整体看起来更协调。
3 CSS 绝对定位
Echart 的地图本质是通过 Canvas 实现的,所以新的提示框必须以绝对定位的方式,环绕在地图周围展示。
position 设置为 absolute 之后,就可以将网页元素对象从文档流中拖出,然后使用 left , right , top , bottom 等属性进行绝对定位。而其层叠可通过 css z-index 属性进行定义。此时对象不具有边距,但仍有补白和边框。
像这种环绕在地图周围展示的不规律布局,可以很方便地使用 position 进行绝对定位。
示例 position:absolute;left:10px;top:10px 表示离父级左侧距离间距为 10px ,距离父级上边距离为 10px 。
注意: 如果父级不使用 position:relative ,而直接使用 position:absolute 进行绝对定位,无论位于 DIV 多少层结构,都会以 body 标签为父级进行绝对定位。
绝对定位很好用,但不要滥用,因为有可能造成 CSS 代码臃肿。
4 隐藏 CSS 元素

因为 element UI 的 Tooltip 组件,默认会带有一个按钮,所以必须将其隐藏,这样整体更协调。
CSS 隐藏元素可以使用 display:none 或 visibility:hidden。
注意: 这两种方法会产生不同的结果 。visibility:hidden 可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间。也就是说,该元素虽然被隐藏了,但仍然会影响布局。而 display:none 可以隐藏某个元素,且隐藏的元素不会占用任何空间。也就是说,该元素不但被隐藏了,而且该元素原本占用的空间也会从页面布局中消失。
因为提示框是以这个按钮元素作为相对定位的,所以我们必须使用 visibility:hidden,让其即使隐藏后,仍然占有空间,作为提示框的定位基准。
CSS3 中加入了 opacity 属性,用于设定元素的不透明级别。我们将其设置为 0,也可以达到 visibility:hidden 的效果。
5 实现
(1) 首先在相应的 vue 组件页面中,定义好数据集(示例中的 company_and_seat_data):
data() {
return {
company_and_seat_data: [
{
area: '福州市',
placement:'right',
style: 'position: absolute;z-index: 100;left:700px;top:480px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
},
{
area: '莆田市',
placement:'right-start',
style: 'position: absolute;z-index: 100;left:720px;top:600px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
},
{
area: '宁德市',
placement:'right',
style: 'position: absolute;z-index: 100;left:700px;top:350px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '南平市',
placement:'left',
style: 'position: absolute;z-index: 100;left:450px;top:300px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '三明市',
placement:'left',
style: 'position: absolute;z-index: 100;left:400px;top:400px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '龙岩市',
placement:'left',
style: 'position: absolute;z-index: 100;left:360px;top:520px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '漳州市',
placement:'left',
style: 'position: absolute;z-index: 100;left:430px;top:700px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '泉州市',
placement:'right-start',
style: 'position: absolute;z-index: 100;left:600px;top:620px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}, {
area: '厦门市',
placement:'bottom',
style: 'position: absolute;z-index: 100;left:550px;top:680px;',
company_num: this.getRandomNumber(100, 1000),
seat_num: this.getRandomNumber(1000, 10000)
}
]
}
},
这个数据集定义了几个属性:
| 属性 | 说明 |
|---|---|
| area | 地市名称 |
| placement | 提示框位置。 |
| style | 样式。 |
| company_num | 企业数。 |
| seat_num | 坐席数。 |
这个数据集除了前三个是必须的之外,其它两个都是自定义属性。如有需要,我们可以对其进行扩展。
每个区域的位置不同,所以绝对定位的 left 与 top 也不同,这个需要打开浏览器的 F12 调试模式进行微调,比较费时。
**(2)**利用 Vue 的 v-for 列表渲染指令、 v-bind、绑定 style 语法,把刚才定义好的数据,渲染出来。
<div class='container'>
<div v-for="d in company_and_seat_data">
<el-tooltip :style=d.style
class="item" effect="dark" :placement=d.placement value="true" manual="true">
<div slot="content" style="font-size:14px;line-height:20px;">
{{d.area}}<br/>企业数:{{d.company_num}}<br/>坐席数:{{d.seat_num}}
</div>
<el-button style="opacity:0;"></el-button>
</el-tooltip>
</div>
<div class='mychart' id='mychart'></div>
</div>
6 最后效果

更多推荐


所有评论(0)