实现效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ea015793076a112fd5f49aa87c2863b7.png)
实现思路
- 呼吸灯实现:CSS帧动画实现,通过padding改变实现阴影层的大小变化,封装成组件
- 通过传当前点击name的参数对比自己的name判断是否需要显示呼吸灯
- 业务逻辑:可以通过has_data字段用于判断是否有数据,以及对应显示隐藏呼吸灯
结构代码
- 这里Group.png是你的地图图片
- breath_arr存放坐标元素
- cur_p是你当前点击的坐标(省份)
- 所有的light-img都是高亮图片
- has_data代表当前省份是否有数据
<div class="img-box">
<div class="map-div">
<img src="../assets/cindex/Group.png" class="map">
<c-breath v-for="(p, idx) in breath_arr" :key="idx" :name="p.name" :has_data="p.has_data" :cur="cur_p" :idx="idx" :p="p" :style="p.style" :outer_color="p.outer_color" :inner_color="p.inner_color" @click_fun="color_change"></c-breath>
<img v-show="cur_p==='四川省'" src="../assets/cindex/cd.png" style="left: 39%;top: 59.9%;width: 18.2%;" class="light-img">
<img v-show="cur_p==='湖南省'" src="../assets/cindex/cs.png" style="left: 57.6%;top: 70.9%;width: 9%;" class="light-img">
...
</div>
</div>
数据代码
- yellow来标识某个坐标是否被选中
- m_name这里不用管,原本name代表省会,m_name代表省,现在都改为省了
- outer_color设置阴影层颜色,inner_color设置呼吸灯中间圆点颜色
export const breath_arr = [{
name: '北京',
style: 'left: 67.5%; top: 41%;height: 20px',
yellow: false,
has_data: false,
id: 29,
m_name: '北京市'
},
{
name: '四川',
style: 'left: 45%; top: 65%;',
outer_color: 'background-color: #1de05430;',
inner_color: 'background-color: #1de054;',
yellow: false,
has_data: true,
id: 17,
m_name: '四川省'
}]
逻辑代码
- color_change为点击某个坐标的方法,点击之后标记yellow
- 将cur_p设置为当前被点击的坐标的name,让其高亮图片显示
- 这里也可以按需增加自己相应的业务逻辑代码
color_change(p, idx, type=3) {
if(!p.yellow&&type===1) {
setTimeout(()=>{
this.point_arr[idx].yellow = true
})
}else if(p.yellow&&type===2) {
setTimeout(()=>{
this.point_arr[idx].yellow = false
})
} else if(type===3) {
this.point_arr.forEach(p => {
p.yellow = false
})
this.point_arr[idx].yellow = true
this.cur_p = p.name
},
呼吸灯组件代码
- 在breathing的div上添加帧动画实现呼吸效果
- 有数据且没有被点击时显示呼吸灯
- name传省份名字
- cur监听当前被点击的坐标,若和自己的name吻合就设置隐藏自己的呼吸灯
<template>
<div class="c-breath" @click="coord_click">
<div class="breathing" v-if="breath_show&&has_data">
<div class="outer" :style="outer_color">
<div class="inner" :style="inner_color"></div>
</div>
</div>
<span>{{name}}</span>
</div>
</template>
<script>
export default {
name: 'c-breath',
data() {
return {
breath_show: true
}
},
props: {
name: {
type: String,
default() {
return '杭州'
}
},
outer_color: {
type: String,
default() {
return 'background-color: #ffff004d;'
}
},
inner_color: {
type: String,
default() {
return 'background-color: #ff0;'
}
},
p: {
type: Object,
default() {
return {}
}
},
idx: {
type: Number,
default() {
return 0
}
},
cur: {
type: String,
default() {
return ''
}
},
has_data: {
type: Boolean,
default() {
return true
}
}
},
methods: {
coord_click() {
this.$emit('click_fun', this.p, this.idx)
}
},
watch: {
cur(n, o) {
if(n===this.name) {
this.breath_show = false
} else {
this.breath_show = true
}
}
},
created() {
}
}
</script>
<style lang="scss" scoped>
.c-breath {
width: 50px;
height: 50px;
position: absolute;
left: 40%;
top: 40%;
text-align: center;
cursor: pointer;
border-radius: 50%;
z-index: 5;
}
.breathing {
width: 100%;
height: 100%;
padding: 15px;
animation: breath;
animation-duration: 4s;
animation-iteration-count: infinite;
box-sizing: border-box;
}
.outer {
z-index: 2;
width: 100%;
height: 100%;
position: relative;
border-radius: 50%;
background-color: #ffff004d;
}
.inner {
z-index: 3;
width: 10px;
height: 10px;
background-color: #ff0;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
span {
position: absolute;
font-size: 12px;
color: #000;
z-index: 1;
top: 80%;
left: 50%;
transform: translate(-50%, -50%);
}
@keyframes breath {
50% {
padding: 5px;
}
80% {
padding: 20px
}
100% {
padding: 20px
}
}
</style>