You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
8.8 KiB
Vue
354 lines
8.8 KiB
Vue
|
8 months ago
|
<template>
|
||
|
|
<view
|
||
|
|
class="zb-tooltip"
|
||
|
|
:style="{
|
||
|
|
'--theme-bg-color': color,
|
||
|
|
}"
|
||
|
|
>
|
||
|
|
<view class="zb_tooltip_content" @longpress.stop="handleClick">
|
||
|
|
<slot></slot>
|
||
|
|
<view
|
||
|
|
class="zb_tooltip__mask"
|
||
|
|
@longpress.stop
|
||
|
|
v-show="isShow"
|
||
|
|
@touchstart="close"
|
||
|
|
></view>
|
||
|
|
<view
|
||
|
|
class="zb_tooltip__popper"
|
||
|
|
@tap.stop="() => {}"
|
||
|
|
:style="[
|
||
|
|
style,
|
||
|
|
{
|
||
|
|
visibility: isShow ? 'visible' : 'hidden',
|
||
|
|
color: color === 'white' ? '' : '#fff',
|
||
|
|
boxShadow:
|
||
|
|
color === 'white'
|
||
|
|
? '0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d'
|
||
|
|
: '',
|
||
|
|
},
|
||
|
|
]"
|
||
|
|
>
|
||
|
|
<slot name="content">{{ content }}</slot>
|
||
|
|
<!-- <view
|
||
|
|
class="zb_popper__icon"
|
||
|
|
:style="[arrowStyle]"
|
||
|
|
:class="[
|
||
|
|
{
|
||
|
|
zb_popper__up: placement.indexOf('bottom') === 0,
|
||
|
|
zb_popper__arrow: placement.indexOf('top') === 0,
|
||
|
|
zb_popper__right: placement.indexOf('right') === 0,
|
||
|
|
zb_popper__left: placement.indexOf('left') === 0,
|
||
|
|
},
|
||
|
|
]"
|
||
|
|
>
|
||
|
|
</view> -->
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name: 'Tooltip',
|
||
|
|
props: {
|
||
|
|
visible: Boolean,
|
||
|
|
align: Boolean,
|
||
|
|
color: {
|
||
|
|
type: String,
|
||
|
|
default: '#303133',
|
||
|
|
},
|
||
|
|
// placement: {
|
||
|
|
// type: String,
|
||
|
|
// default: 'top',
|
||
|
|
// },
|
||
|
|
content: {
|
||
|
|
type: String,
|
||
|
|
default: '',
|
||
|
|
},
|
||
|
|
show: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
isShow: this.visible,
|
||
|
|
title: 'Hello',
|
||
|
|
arrowLeft: 0,
|
||
|
|
query: null,
|
||
|
|
style: {},
|
||
|
|
arrowStyle: {},
|
||
|
|
placement: 'top',
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onLoad() {},
|
||
|
|
watch: {
|
||
|
|
isShow: {
|
||
|
|
handler(val) {
|
||
|
|
this.$emit('update:visible', val)
|
||
|
|
},
|
||
|
|
immediate: true,
|
||
|
|
},
|
||
|
|
visible: {
|
||
|
|
handler(val) {
|
||
|
|
if (val) {
|
||
|
|
this.$nextTick(() => {
|
||
|
|
this.getPosition()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
this.isShow = val
|
||
|
|
},
|
||
|
|
immediate: true,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
// #ifdef H5
|
||
|
|
window.addEventListener('click', () => {
|
||
|
|
this.isShow = false
|
||
|
|
})
|
||
|
|
// #endif
|
||
|
|
this.getPosition()
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
close() {
|
||
|
|
this.isShow = false
|
||
|
|
},
|
||
|
|
fixedWrap() {
|
||
|
|
this.isShow = false
|
||
|
|
},
|
||
|
|
async handleClick() {
|
||
|
|
if (this.isShow) {
|
||
|
|
return (this.isShow = false)
|
||
|
|
}
|
||
|
|
await this.getPosition()
|
||
|
|
this.isShow = true
|
||
|
|
},
|
||
|
|
getPosition() {
|
||
|
|
return new Promise((resolve) => {
|
||
|
|
uni
|
||
|
|
.createSelectorQuery()
|
||
|
|
.in(this)
|
||
|
|
.selectAll('.zb_tooltip_content,.zb_tooltip__popper')
|
||
|
|
.boundingClientRect(async (data) => {
|
||
|
|
let { left, bottom, right, top, width, height } = data[0] || {}
|
||
|
|
let obj1 = data[1] || {}
|
||
|
|
let objStyle = {}
|
||
|
|
let objStyle1 = {}
|
||
|
|
if (top <= 300) {
|
||
|
|
this.placement = 'bottom'
|
||
|
|
} else {
|
||
|
|
this.placement = 'top'
|
||
|
|
}
|
||
|
|
switch (this.placement) {
|
||
|
|
case 'top':
|
||
|
|
// if (obj1.width > width) {
|
||
|
|
// objStyle.left = `-${(obj1.width - width + 120) / 2}px`
|
||
|
|
// } else {
|
||
|
|
// objStyle.left = `${Math.abs(obj1.width - width) / 2}px`
|
||
|
|
// }
|
||
|
|
if (this.align) {
|
||
|
|
objStyle.left = '-100px'
|
||
|
|
if (width < 90) {
|
||
|
|
objStyle.left = '-200px'
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
objStyle.left = '50px'
|
||
|
|
}
|
||
|
|
objStyle.bottom = `${height + 8}px`
|
||
|
|
// objStyle.left = '30%'
|
||
|
|
// objStyle1.left = obj1.width - 6 + 'px'
|
||
|
|
break
|
||
|
|
case 'bottom':
|
||
|
|
// if (obj1.width > width) {
|
||
|
|
// objStyle.left = `-${(obj1.width - width) / 2}px`
|
||
|
|
// } else {
|
||
|
|
// objStyle.left = `${Math.abs(obj1.width - width) / 2}px`
|
||
|
|
// }
|
||
|
|
if (this.align) {
|
||
|
|
objStyle.left = '-100px'
|
||
|
|
if (width < 100) {
|
||
|
|
objStyle.left = '-200px'
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
objStyle.left = '50px'
|
||
|
|
}
|
||
|
|
// objStyle.left = `-${obj1.width - width - 100}px`
|
||
|
|
objStyle.top = `${height + 8}px`
|
||
|
|
// objStyle1.left = obj1.width / 2 - 6 + 'px'
|
||
|
|
break
|
||
|
|
// case 'top-start':
|
||
|
|
// objStyle.left = `0px`
|
||
|
|
// objStyle.bottom = `${height + 8}px`
|
||
|
|
// break;
|
||
|
|
// case 'top-end':
|
||
|
|
// objStyle.right = `0px`
|
||
|
|
// objStyle.bottom = `${height + 8}px`
|
||
|
|
// objStyle1.right = `8px`
|
||
|
|
// break;
|
||
|
|
// case 'bottom-start':
|
||
|
|
// objStyle.left = `0px`
|
||
|
|
// objStyle.top = `${height + 8}px`
|
||
|
|
// objStyle1.left = `8px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'bottom-end':
|
||
|
|
// objStyle.right = `0px`
|
||
|
|
// objStyle.top = `${height + 8}px`
|
||
|
|
// objStyle1.right = `8px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'right':
|
||
|
|
// objStyle.left = `${width + 8}px`
|
||
|
|
// if (obj1.height > height) {
|
||
|
|
// objStyle.top = `-${(obj1.height - height) / 2}px`
|
||
|
|
// } else {
|
||
|
|
// objStyle.top = `${Math.abs((obj1.height - height) / 2)}px`
|
||
|
|
// }
|
||
|
|
|
||
|
|
// objStyle1.top = `${obj1.height / 2 - 6}px`
|
||
|
|
// break;
|
||
|
|
// case 'right-start':
|
||
|
|
// objStyle.left = `${width + 8}px`
|
||
|
|
// objStyle.top = `0px`
|
||
|
|
// objStyle1.top = `8px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'right-end':
|
||
|
|
// objStyle.left = `${width + 8}px`
|
||
|
|
// objStyle.bottom = `0px`
|
||
|
|
// objStyle1.bottom = `8px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'left':
|
||
|
|
// objStyle.right = `${width + 8}px`
|
||
|
|
|
||
|
|
// if (obj1.height > height) {
|
||
|
|
// objStyle.top = `-${(obj1.height - height) / 2}px`
|
||
|
|
// } else {
|
||
|
|
// objStyle.top = `${Math.abs((obj1.height - height) / 2)}px`
|
||
|
|
// }
|
||
|
|
|
||
|
|
// objStyle1.top = `${obj1.height / 2 - 6}px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'left-start':
|
||
|
|
// objStyle.right = `${width + 8}px`
|
||
|
|
// objStyle.top = `0px`
|
||
|
|
// objStyle1.top = `8px`
|
||
|
|
// break;
|
||
|
|
|
||
|
|
// case 'left-end':
|
||
|
|
// objStyle.right = `${width + 8}px`
|
||
|
|
// objStyle.bottom = `0px`
|
||
|
|
// objStyle1.bottom = `8px`
|
||
|
|
// break;
|
||
|
|
}
|
||
|
|
this.style = objStyle
|
||
|
|
// 三角形箭头
|
||
|
|
this.arrowStyle = objStyle1
|
||
|
|
resolve()
|
||
|
|
})
|
||
|
|
.exec()
|
||
|
|
})
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="scss" scoped>
|
||
|
|
$theme-bg-color: var(--theme-bg-color);
|
||
|
|
|
||
|
|
.zb-tooltip {
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_tooltip_content {
|
||
|
|
height: 100%;
|
||
|
|
/* float: left; */
|
||
|
|
position: relative;
|
||
|
|
display: inline-block;
|
||
|
|
|
||
|
|
// display: flex;
|
||
|
|
// flex-direction: row;
|
||
|
|
// align-items: center;
|
||
|
|
/* overflow: hidden; */
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_tooltip__popper {
|
||
|
|
/* transform-origin: center top; */
|
||
|
|
background: $theme-bg-color;
|
||
|
|
|
||
|
|
visibility: hidden;
|
||
|
|
// color:'#fff';
|
||
|
|
position: absolute;
|
||
|
|
border-radius: 4px;
|
||
|
|
font-size: 12px;
|
||
|
|
padding: 10px;
|
||
|
|
min-width: 10px;
|
||
|
|
word-wrap: break-word;
|
||
|
|
display: inline-block;
|
||
|
|
white-space: nowrap;
|
||
|
|
z-index: 99;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_tooltip__mask {
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100vw;
|
||
|
|
height: 100vh;
|
||
|
|
overflow: hidden;
|
||
|
|
background-color: rgba(256, 256, 256, 0);
|
||
|
|
z-index: 8;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_popper__icon {
|
||
|
|
width: 0;
|
||
|
|
height: 0;
|
||
|
|
z-index: 9;
|
||
|
|
position: absolute;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_popper__arrow {
|
||
|
|
bottom: -5px;
|
||
|
|
/* transform-origin: center top; */
|
||
|
|
border-left: 6px solid transparent;
|
||
|
|
border-right: 6px solid transparent;
|
||
|
|
border-top: 6px solid $theme-bg-color;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_popper__right {
|
||
|
|
border-top: 6px solid transparent;
|
||
|
|
border-bottom: 6px solid transparent;
|
||
|
|
border-right: 6px solid $theme-bg-color;
|
||
|
|
left: -5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_popper__left {
|
||
|
|
border-top: 6px solid transparent;
|
||
|
|
border-bottom: 6px solid transparent;
|
||
|
|
border-left: 6px solid $theme-bg-color;
|
||
|
|
right: -5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.zb_popper__up {
|
||
|
|
border-left: 6px solid transparent;
|
||
|
|
border-right: 6px solid transparent;
|
||
|
|
border-bottom: 6px solid $theme-bg-color;
|
||
|
|
top: -5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.fixed {
|
||
|
|
position: absolute;
|
||
|
|
width: 100vw;
|
||
|
|
height: 100vh;
|
||
|
|
position: fixed;
|
||
|
|
left: 0;
|
||
|
|
top: 0;
|
||
|
|
pointer-events: auto;
|
||
|
|
background: red;
|
||
|
|
z-index: -1;
|
||
|
|
}
|
||
|
|
</style>
|