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>

  1. 因为之前用的是深蓝背景,所以这里把 effect 设置为 dark,让其看起来更协调。
  2. 因为要显示多行内容,所以打算采用具名 slot 来分发 content。
  3. 希望加载页面后,自动出现提示框,所以把 value 设为可见。
  4. 为了避免鼠标滑动到提示框后,提示框自动消失,我们把 manual 设置为手动控制。
  5. 因为地图上的每个区域位置不同,所以我们必须根据提示框所在的位置,来调整 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 最后效果

Logo

更多推荐