用户点击页面上的任意一处地方后,在鼠标指针处出现字符!
image

PS:带有@click方法的A元素必须是transition-group这个B元素的父元素(也就是A要包含B),最好B是A的直接子元素(也就是B不会再被其他HTML元素包裹一层)

代码部分

HTML
<div class='section' @click='showInteresting($event)'>
    <transition-group name='fade' tag='div'>
      <div v-for='(item) in texts' :key='item.key' :style='item.style' class='floating-text'>
        {{ item.content }}
      </div>
    </transition-group>
</div>
TS
//  按键出现浮动字符实现
/**
 * 随机颜色数组
 */
const colors = [
  '#E63946',
  '#F1C40F',
  '#2ECC71',
];
/**
 * 随机文本数组
 */
const InterestingText = [
  '你好',
  'awa',
  'QAQ',
  ':(',
  ':)',
  '⭐',
  'Vue3',
  'Pinia',
  'Axios',
  'JAVA',
  'HTML',
  'CSS',
  'JS',
];

let id = 0;  //  每次出现字符的唯一索引
const texts = ref<any[]>([]);  //  被展示的文本存储处

//  防止短时间内大量点击可能导致的问题
watch(() => texts.value.length, (newVal) => {
  if (newVal >= 99999) {
    texts.value = [];
    id = 0;
  }
});
/**
 * 点击鼠标后在鼠标出出现字符
 * @param $event  接受一个鼠标时间(用于定位鼠标位置)
 */
const showInteresting = ($event: MouseEvent) => {
  const randomText = InterestingText[Math.floor(Math.random() * InterestingText.length)];  //  抽取本次展示的文本
  const posX = $event.clientX + 'px';  //  点击时鼠标所在的X轴位置
  const posY = $event.clientY + 'px';  //  点击时鼠标所在的Y轴位置
  const newTextKey = id++; // 为本次文本生成一个唯一的索引
  const randomColor = colors[Math.floor(Math.random() * colors.length)];	//	抽取本次出现文本的颜色

  // 添加新文本到texts数组用以展示
  texts.value.push({
    content: randomText,
    style: {
      left: posX,
      top: posY,
      overflow: 'hidden', // 防止在边缘点击时撑开页面
      cursor: 'default', // 不导致鼠标样式改变
      userSelect: 'none', // 防止被用户选中
      color: randomColor,
    },
    key: newTextKey,
  });

  // 设置定时器,动画结束后移除文本,防止数组过大
  setTimeout(() => {
    texts.value = texts.value.filter(text => text.key !== newTextKey);
  }, 1000); // 这里的1000应与CSS动画时长一致
};
CSS部分
.floating-text {
    z-index: 9999; // 保证文本在所有元素上出现
    font-size: 16px;
    font-weight: bold;
    position: fix; // 防止出现滚动后定位不准确
    animation: floatUp 1s ease forwards; // 文本上浮动画,1s是持续时间
  }

  // 动画部分
  @keyframes floatUp {
    0% {
      transform: translateY(0);
      opacity: 1;
    }
    100% {
      transform: translateY(-50px); // 向上移动的距离
      opacity: 0;
    }
  }

  .fade-enter-active, .fade-leave-active {
    transition: opacity 0.5s;
  }

  .fade-enter, .fade-leave-to {
    opacity: 0;
  }