123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import Vue from 'vue'
- import {computePosition, offset, flip, shift, arrow} from '@floating-ui/dom';
- let tooltipNode = null
- let intervalId = null
- function removeTooltip() {
- try {
- clearInterval(intervalId)
- document.body.removeChild(tooltipNode)
- } catch(e) {
- console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
- }
- }
- Vue.directive('tooltip', {
- bind: function (el, binding) {
- if (!binding.value) {
- return
- }
- el.addEventListener('mouseenter', function(e) {
- tooltipNode = document.createElement('div')
- tooltipNode.style.position = 'fixed'
- tooltipNode.style.zIndex = 100
- tooltipNode.style.backgroundColor = '#191A1C'
- tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
- tooltipNode.style.borderRadius = '3px'
- tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
- tooltipNode.style.boxShadow = '0px 2px 12px 0px rgba(0, 0, 0, 0.06)'
- tooltipNode.style.padding = '8px 8px'
- tooltipNode.style.fontSize = '12px'
- tooltipNode.style.cursor = 'default'
- tooltipNode.style.pointerEvents = 'none'
- tooltipNode.style.wordBreak = 'keep-all'
- tooltipNode.style.whiteSpace = 'pre'
- tooltipNode.style.fontSize = '12px'
- tooltipNode.style.lineHeight = '17px'
- tooltipNode.style.color = 'rgba(255, 255, 255, 0.6)'
- tooltipNode.innerText = binding.value
- const arrowNode = document.createElement('div')
- arrowNode.style.position = 'absolute'
- arrowNode.style.backgroundColor = 'inherit'
- arrowNode.style.boxSizing = 'border-box'
- arrowNode.style.width = '12px'
- arrowNode.style.height = '12px'
- arrowNode.style.border = '1px solid transparent'
- arrowNode.style.borderRight = 'inherit'
- arrowNode.style.borderBottom = 'inherit'
- arrowNode.style.transform = 'rotate(45deg)'
-
- tooltipNode.appendChild(arrowNode)
- document.body.appendChild(tooltipNode)
- computePosition(el, tooltipNode, {
- placement: 'top',
- middleware: [
- offset(13),
- flip(),
- shift({padding: 12}),
- arrow({
- element: arrowNode,
- padding: 3,
- }),
- ],
- }).then(({x, y, placement, middlewareData}) => {
- Object.assign(tooltipNode.style, {
- left: `${x}px`,
- top: `${y}px`,
- });
- const {x: arrowX, y: arrowY} = middlewareData.arrow;
- const staticSide = {
- top: 'bottom',
- right: 'left',
- bottom: 'top',
- left: 'right',
- }[placement.split('-')[0]];
-
- Object.assign(arrowNode.style, {
- left: arrowX != null ? `${arrowX}px` : '',
- [staticSide]: '-6px',
- });
- }).catch((err) => {
- console.log('计算tooltip位置时出现异常,可能因为目标元素已经被卸载。')
- });
- intervalId = setInterval(() => {
- if (!document.contains(el)) {
- removeTooltip()
- }
- }, 300);
- }, {
- passive: false,
- })
- el.addEventListener('mouseleave', removeTooltip)
- el.addEventListener('mousedown', removeTooltip)
- el.addEventListener('keydown', removeTooltip)
- el.addEventListener('scroll', removeTooltip)
- el.addEventListener('dragstart', removeTooltip)
- el.addEventListener('dragstart', removeTooltip)
- el.addEventListener('dragleave', removeTooltip)
- },
- })
|