鼠标悬浮,动态显示文字、换行、自适应

401 阅读1分钟

js原生title属性没有办法换行,大屏用组件UI不友好,故手写一个可以换行的title组件 效果展示:

image.png

根据鼠标事件的按钮位置自适应悬浮框的位置 第一步:写一个命名为title.js

/**
 * 获取文本宽度
 * @param text 文本内容
 * @param fontSize 大小
 * @param unit 字体单位
 */
export function getTextWidth(text: string, fontSize = 32, unit = 'px'): number {
  const div = document.createElement('div');
  div.style.fontSize = `${fontSize}${unit}`;
  div.style.display = 'inline-block';
  div.style.position = 'fixed';
  div.style.top = '400%';
  div.style.left = '400%';
  div.style.whiteSpace = 'nowrap';
  div.innerHTML = text;
  document.body.append(div);
  setTimeout(() => {
    document.body.removeChild(div);
  });
  return div.clientWidth;
}

第二步:写一个命名为toolTip的组件

<template>
  <Teleport to="#app">
    <div
      v-if="props.visible"
      class="absolute z-100 font-sc text-13px leading-20px text-[#e6eeff] bg-[#001a4d] border-1 border-solid border-[#0851ee] whitespace-nowrap w-auto"
      :class="$attrs.class"
      :style="{
        top: props.position === 'bottom' ? y + 30 + 'px' : y - ($refs.content?.clientHeight || 0) - 10 + 'px',
        left: x - ($refs.content?.clientWidth || 0) / 2 + 'px',
      }"
    >
      <div ref="content" class="px-16px py-6px">
        <slot> 点击查看详情 </slot>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
  position: {
    type: String,
    validator(value) {
      return ['top', 'bottom'].includes(value);
    },
    default: 'bottom', // top | bottom
  },
});
const { x, y } = useMouse();
const content = ref(null);
</script>

Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术,这里是直接挂载到跟app平层的dom元素,看下面截图:

image.png

写好了toolTip组件现在看看我们怎么用

第三步:将toolTip组件引进当前文件,title.js的getTextWidth引进来 如:import { getTextWidth } from './title';

html片段代码:

<span
          class="hover-text text-12px w-52px h-18px ml-4px inline-flex justify-center items-center"
          @mouseover.stop="mouseover()"
          @mouseout.stop="mouseout()"
        >
          <span>鼠标事件</span>
          <toolTip :visible="visible">
            <div
              class="title bottom-0 whitespace-nowrap z-100"
              :style="{
                width: getWidth(),
              }"
            >
              <div>第一行内容</div>
              <div>第一行内容</div>
            </div>
          </toolTip>
        </span>

js片段代码:

const visible = ref(false);
// const boxWidth = ref(props.text.dept);
const mouseover = () => {
  visible.value = true;
};
const mouseout = () => {
  visible.value = false;
};
const getWidth = () => {
  const arr = [
    getTextWidth(`第一行内容:, getScale(13), 'px'),
    getTextWidth(`第一行内容:, getScale(13), 'px'),
  ];
  return `${Math.max(...arr)}px`;
};

以上就是全部的代码。