基本思路
将气泡卡片分为两部分,分别为箭头和内容部分,通过方法getBoundingClientRect获取按钮相对于视口的位置,具体细节可以复习:点击复习getBoundingClientRect
然后再将箭头和内容定位到合适的位置,关于trigger的方法实现通过click、mouseover、mouseleave、mouseup事件很容易实现,在此不再赘述。
因为后面还要做tooltip组件,所以把获取箭头和内容部分的位置封装为单独的函数。
//getArrowStyle.js
const getArrowStyle = function (placement, refDOMRect, color) {
let res = {}
const width = 12
switch (placement) {
case 'bottom':
res = {
borderBottomColor: color,
left: refDOMRect.right - refDOMRect.width / 2 - width / 2 + 'px',
top: refDOMRect.bottom + 'px',
filter: 'drop-shadow(2px -2px 2px rgba(0, 0, 0, .1))'
}
break;
case 'top':
res = {
borderTopColor: color,
left: refDOMRect.right - refDOMRect.width / 2 - width / 2 + 'px',
top: refDOMRect.top - width + 'px',
filter: 'drop-shadow(2px 2px 2px rgba(0, 0, 0, .1))'
}
break;
case 'left':
res = {
borderLeftColor: color,
left: refDOMRect.left - width + 'px',
top: refDOMRect.bottom - refDOMRect.height / 2 - width / 2 + 'px',
filter: 'drop-shadow(2px 2px 2px rgba(0, 0, 0, .1))'
}
break;
case 'right':
res = {
borderRightColor: color,
left: refDOMRect.right + 'px',
top: refDOMRect.bottom - refDOMRect.height / 2 - width / 2 + 'px',
filter: 'drop-shadow(-2px 2px 2px rgba(0, 0, 0, .1))'
}
break;
default:
res = { borderBottomColor: color }
break;
}
return res
}
export {
getArrowStyle
}
//getPlainStyle.js
const getPlainStyle = function (Contentwidth, placement, refDOMRect) {
const width = Number(Contentwidth) + 40
const arrowWidth = 12
let res = {}
switch (placement) {
case 'bottom':
res = {
left: refDOMRect.right - refDOMRect.width / 2 - width / 2 + 'px',
top: refDOMRect.bottom + arrowWidth + 'px'
}
break;
case 'top':
res = {
left: refDOMRect.right - refDOMRect.width / 2 - width / 2 + 'px',
bottom: document.body.clientHeight - (refDOMRect.top - arrowWidth) + 'px'
}
break;
case 'left':
res = {
transformOrigin: 'right',
left: refDOMRect.left - arrowWidth - width + 'px',
top: refDOMRect.bottom - refDOMRect.height / 2 + 'px',
transform: 'translate(0,-50%)',
}
break;
case 'right':
res = {
transformOrigin: 'left',
transform: 'translate(0,-50%)',
left: refDOMRect.right + arrowWidth + 'px',
top: refDOMRect.bottom - refDOMRect.height / 2 + 'px',
}
break;
default:
break;
}
return res
}
export {
getPlainStyle
}
如何定位获取DOM位置呢?
通过ref定位按钮组件
<div class="popover-reference" ref="reference" >
<slot name="reference">
</slot>
</div>
在setup的onMounted中获取到实际的元素位置
setup(){
let reference = ref(null)
let refDOMRect = reactive({})
onMounted(() => {
const DOMRect = reference.value.getBoundingClientRect()
for (let key in DOMRect) {
if (typeof DOMRect[key] !== 'function') {
refDOMRect[key] = DOMRect[key]
}
}
return {
//别忘记return出去,不然没法获得动态数据
reference,
refDOMRect,
}
}