考虑过使用antdesign的tooltip或者popover,但是发现并不适合我,我不希望点击外部关闭它就需要重新修改交互,并且还要重置样式等,索性自己上手撸一个。实现弹出框
本文主要分享弹出框的实现,内部的按钮等样式不给出具体的样式
1. 首先写一个基础的盒子实现样式,button等样式不在代码中体现。
<div class="tooltip">
<span>我是小v主人有何吩咐</span>
<div class="button">
<div>打开支付宝</div>
<div>查看今天天气</div>
</div>
</div>
<style lang="less">
.tooltip {
width: 251px;
height: 80px;
border-radius: 8px;
padding: 12px 12px;
background: rgba(11, 23, 54, 0.9);
border: 1px solid rgba(91, 111, 255, 0.62);
}
<style>
2. 实现右边的小三角,可以看出三角有底色,并且还有一个边框,我的做法是叠加两个通过定位错位来实现。有大量的博主分享了三角形的花样画法,提到通过filter来实现边框。但是考虑到兼容性问题不采用。
<style lang="less">
.tooltip {
&:before, &:after{
content: '';
position: absolute;
top: 50%;
margin-top: -3px;
right: -12px;
width: 0;
height: 0;
border: 6px solid transparent;
border-left-color:rgba(91, 111, 255, 0.62);
transition: opacity 0.2s;
}
&:after {
content: '';
border-left-color: rgba(11, 23, 54);
right: -11px;
}
}
</style>
通过before和after伪类定位实现两个三角形,before使用盒子边框蓝色,after使用背景蓝黑色。after盖住before,after设置right缩进一个像素即可达到以上的效果。
3. tooltip展开收起动画
到这一步我们实现了基本的气泡框,但是每次点击打开关闭的时候都显得很生硬。要实现展开收起的动效也不难,通过css3的transition就能实现。首先我们得知道收起展开变化的是什么,这里我们使用宽度变化来实现,展开的时候宽度从0~251px,收起则反之。但是由于收起的时候宽度变小文字会被不断的挤压高度变高,效果非常差,所以不能让它换行,同时当盒子的宽度不足时要隐藏超出部分。由于盒子设置了padding和border,当盒子宽度变为0,padding还存在,所以结合透明度关闭时将透明度设置为0。
* showTooltip为点击机器人打开/关闭气泡的变量
<div class="tooltip" :class="show: showTooltip">
<span>我是小v主人有何吩咐</span>
<div class="button">
<div>打开支付宝</div>
<div>查看今天天气</div>
</div>
</div>
<style lang="less">
.tooltip {
width: 0; // 默认为0
height: 80px;
border-radius: 8px;
padding: 12px 12px;
background: rgba(11, 23, 54, 0.9);
border: 1px solid rgba(91, 111, 255, 0.62);
transition: all .2s; //属性的过渡动画
overflow: hidden;
white-space: nowrap;
opacity: 0;
}
.show {
width: 251px;
opacity: 1;
}
<style>
4. 到这里我们基本实现了有动画效果的弹出框,定睛一看,what?小三角不见了,为什么呢?是由于小三角定位在盒子的外部,但由于盒子又设置了overflow:hidden。所以被隐藏了。如何解决呢,那就是将小三角拎出来,将它写在父盒子上,内容部分写在子盒子内,设置内容的宽度并且在内容部分设置overflow即可。完整代码如下
<div class="tooltip" :class="show: showTooltip">
<div class="tooltip-content">
<span>我是小v主人有何吩咐</span>
<div class="button">
<div>打开支付宝</div>
<div>查看今天天气</div>
</div>
</div>
</div>
<style lang="less">
.tooltip {
position: absolute;
bottom: 12px;
right: 100px;
&:before, &:after{
content: '';
position: absolute;
top: 50%;
margin-top: -3px;
right: -12px;
width: 0;
height: 0;
opacity: 0;
border: 6px solid transparent;
border-left-color:rgba(91, 111, 255, 0.62);
transition: opacity 0.2s;
}
&:after {
content: '';
border-left-color: rgba(11, 23, 54);
right: -11px;
}
}
.tooltip-content {
width: 0; // 默认为0
height: 80px;
border-radius: 8px;
padding: 12px 12px;
background: rgba(11, 23, 54, 0.9);
border: 1px solid rgba(91, 111, 255, 0.62);
transition: all .2s; //属性的过渡动画
overflow: hidden;
white-space: nowrap;
opacity: 0;
}
.show {
&:before,&:after {
opacity: 1
}
.tooltip-content {
width: 251px;
opacity: 1;
}
}
<style>
5. 效果展示