效果
组件属性
| 属性名 | 描述 | 示例 |
|---|---|---|
| width | 组件的宽度 | 字符串:'300rpx' |
| text | 文本内容 | 字符串:'这是气泡提示' |
| arrowSize | 箭头大小,单位rpx | 数字:16 |
| arrowDistance | 箭头距离气泡框的距离 | 字符串:'16rpx' |
| position | 箭头在气泡框的位置 | 字符串:'top-left',第一个值是在气泡框的哪条边、第二个值是边的那个位置 |
| background | 气泡框背景色 | 字符串:'#fff' |
| shadowColor | 气泡框阴影颜色 | 字符串:'#eee' |
| borderColor | 气泡框边框颜色 | 字符串:'#ddd' |
| tipStyle | 气泡框的样式 | 对象:{} |
注意
- tipStyle中设置的背景色、阴影颜色、边框颜色都无法生效,请使用组件提供的属性单独设置(这是为了保证箭头的颜色与气泡框保持一致)
- 气泡框的内容可以使用默认插槽插入自定义的内容,但是如果使用了插槽,参数text会失效
position 属性值
- top-left
- top-center
- top-right
- bottom-left
- bottom-center
- bottom-right
- left-top
- left-center
- left-bottom
- right-top
- right-center
- right-bottom
代码
<template>
<div class="tooltip" :style="tipStyle">
<slot>
<text>{{ props.text }}</text>
</slot>
<div class="before" :style="beforeStyle"></div>
<div class="after" :style="afterStyle"></div>
</div>
</template>
<script setup>
import { ref, onMounted, computed, watchEffect, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const { proxy } = getCurrentInstance();
const example = proxy;
const props = defineProps({
width: {
type: String,
default: 'max-content',
},
text: {
type: String,
default: '这是气泡提示',
},
arrowSize: {
type: Number,
default: 16,
},
arrowDistance: {
type: String,
default: '16px',
},
position: {
type: String,
default: 'top-left',
},
background: {
type: String,
default: '#fff',
},
shadowColor: {
type: String,
default: '#eee',
},
borderColor: {
type: String,
default: '#ddd',
},
tipStyle: {
type: Object,
default: {},
},
});
onMounted(() => {
tipStyle.value = {
width: props.width,
padding: '20rpx',
'border-radius': '20rpx',
border: '2rpx solid',
...props.tipStyle,
background: props.background,
borderColor: props.borderColor,
filter: `drop-shadow(0 0 10rpx ${props.shadowColor})`,
};
let publicStyle = {
border: `${props.arrowSize}rpx solid transparent`,
content: '',
display: 'block',
width: 0,
height: 0,
overflow: 'hidden',
position: 'absolute',
'z-index': 101,
};
let mainStyle = {
'z-index': 99,
};
if (
props.position == 'top-left' ||
props.position == 'top-center' ||
props.position == 'top-right'
) {
publicStyle = {
...publicStyle,
top: `-${props.arrowSize}rpx`,
'border-top': 0,
'border-bottom-color': props.background,
};
switch (props.position) {
case 'top-left':
publicStyle = {
...publicStyle,
left: props.arrowDistance,
};
break;
case 'top-center':
publicStyle = {
...publicStyle,
left: '50%',
transform: 'translateX(-50%)',
};
break;
case 'top-right':
publicStyle = {
...publicStyle,
right: props.arrowDistance,
};
break;
}
mainStyle = {
...publicStyle,
...mainStyle,
top: `-${props.arrowSize + 2}rpx`,
'border-bottom-color': props.borderColor,
};
}
if (
props.position == 'bottom-left' ||
props.position == 'bottom-center' ||
props.position == 'bottom-right'
) {
publicStyle = {
...publicStyle,
bottom: `-${props.arrowSize}rpx`,
'border-bottom': 0,
'border-top-color': props.background,
};
switch (props.position) {
case 'bottom-left':
publicStyle = {
...publicStyle,
left: props.arrowDistance,
};
break;
case 'bottom-center':
publicStyle = {
...publicStyle,
left: '50%',
transform: 'translateX(-50%)',
};
break;
case 'bottom-right':
publicStyle = {
...publicStyle,
right: props.arrowDistance,
};
break;
}
mainStyle = {
...publicStyle,
...mainStyle,
bottom: `-${props.arrowSize + 2}rpx`,
'border-top-color': props.borderColor,
};
}
if (
props.position == 'left-top' ||
props.position == 'left-center' ||
props.position == 'left-bottom'
) {
publicStyle = {
...publicStyle,
left: `-${props.arrowSize}rpx`,
'border-left': 0,
'border-right-color': props.background,
};
switch (props.position) {
case 'left-top':
publicStyle = {
...publicStyle,
top: props.arrowDistance,
};
break;
case 'left-center':
publicStyle = {
...publicStyle,
top: '50%',
transform: 'translateY(-50%)',
};
break;
case 'left-bottom':
publicStyle = {
...publicStyle,
bottom: props.arrowDistance,
};
break;
}
mainStyle = {
...publicStyle,
...mainStyle,
left: `-${props.arrowSize + 2}rpx`,
'border-right-color': props.borderColor,
};
}
if (
props.position == 'right-top' ||
props.position == 'right-center' ||
props.position == 'right-bottom'
) {
publicStyle = {
...publicStyle,
right: `-${props.arrowSize}rpx`,
'border-right': 0,
'border-left-color': props.background,
};
switch (props.position) {
case 'right-top':
publicStyle = {
...publicStyle,
top: props.arrowDistance,
};
break;
case 'right-center':
publicStyle = {
...publicStyle,
top: '50%',
transform: 'translateY(-50%)',
};
break;
case 'right-bottom':
publicStyle = {
...publicStyle,
bottom: props.arrowDistance,
};
break;
}
mainStyle = {
...publicStyle,
...mainStyle,
right: `-${props.arrowSize + 2}rpx`,
'border-left-color': props.borderColor,
};
}
afterStyle.value = publicStyle;
beforeStyle.value = mainStyle;
});
let tipStyle = ref({});
let afterStyle = ref('');
let beforeStyle = ref('');
</script>
<style lang="scss" scoped>
.tooltip {
position: relative;
.before,
.after {
position: absolute;
}
}
</style>
页面使用
<myTooltip
position="left-top"
:text="tipText"
width="300rpx"
:arrowSize="10"
background="#E91E63"
:tipStyle="{
'border-radius': '30rpx',
'font-size': '36rpx',
'font-weight': 700,
color: '#fff',
}"
>
<!-- 默认插槽,自定义内容 -->
<div class="tip-box">
<image
src="https://douleoss.oss-cn-shenzhen.aliyuncs.com/test/66236de1e4b0fb16c4b0c307.jpg"
mode="scaleToFill"
/>
<text>{{ tipText }}</text>
</div>
</myTooltip>
let tipText=ref('')
气泡框的内容可以使用默认插槽插入自定义的内容