效果图

在这里插入图片描述

直接在需要的页面引用该组件就行

<template>
    <div id="panel">
    </div>
</template>

<script>
export default {
    methods: {
        mouseMove(e) {
            /*这里获取元素节点*/
            let oPanel = document.getElementById("panel");
            let oSpan = document.createElement(`span`);
            /*浏览器兼容*/
            e = e || window.Event;
            // let x = e.clientX;
            // let y = e.clientY;
            /*获取相关参数*/
            oSpan.style.left = e.clientX + `px`;
            oSpan.style.top = e.clientY - 50 + `px`;
            /*设定随机数存储在size中*/
            let size = Math.random() * 20;
            /*给节点赋值参数数值*/
            oSpan.style.width = 5 + size + `px`;
            oSpan.style.height = 5 + size + `px`;
            /*在body中添加span标签*/
            oPanel.appendChild(oSpan);
            /*设置定时器 间隔时间为2000毫秒*/
            setTimeout(() => {
                /*清除ospan节点*/
                oSpan.remove();
            }, 1000);
        },
    },
    mounted() {
        /*这里是给整个页面添加了一个鼠标移动的监听事件 e为事件对象*/
        document.addEventListener(`mousemove`, this.mouseMove);
    },
    beforeDestroy() {
        document.removeEventListener(`mousemove`, this.mouseMove);
    },
};
</script>

<style lang='less'>
#panel {
    height: 100vh;
    width: 100%;
    // display: flex;
    // align-items: center;
    // justify-content: center;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 0;
    span {
        width: 10px;
        height: 10px;
        background: #55b9f3;
        border-radius: 50%;
        position: absolute;
        box-shadow: 5px 5px 15px #489dcf, -5px -5px 15px #62d5ff;
        animation: blow 4s linear infinite;
        -webkit-animation: blow 4s linear infinite;
    }
}
/*这里是定义里一个动画效果*/

@keyframes blow {
    0% {
        transform: translate(-50%, -50%);
        /*这里是定义初始透明度为1*/
        opacity: 1;
        /*
	这里是初始滤镜效果
	给图像应用色相旋转。"angle"一值设定图像会被调整的色环角度值。
	值为0deg,则图像无变化。若值未设置,默认值是0deg。
	该值虽然没有最大值,超过360deg的值相当于又绕一圈。
	*/
        filter: hue-rotate(0deg);
        /*这里是浏览器兼容*/
        -webkit-transform: translate(-50%, -50%);
        -moz-transform: translate(-50%, -50%);
        -ms-transform: translate(-50%, -50%);
        -o-transform: translate(-50%, -50%);
    }

    100% {
        /*
	2D转化
  	这里是从自身向上平移
  	*/
        transform: translate(-50%, -1000%);
        /*这里是定义结束时透明度为0*/
        opacity: 0;
        /*
	这里是结束滤镜效果
	给图像应用色相旋转。"angle"一值设定图像会被调整的色环角度值。
	值为0deg,则图像无变化。若值未设置,默认值是0deg。
	该值虽然没有最大值,超过360deg的值相当于又绕一圈。
	*/
        filter: hue-rotate(720deg);
        /*这里是浏览器兼容*/
        -webkit-transform: translate(-50%, -1000%);
        -moz-transform: translate(-50%, -1000%);
        -ms-transform: translate(-50%, -1000%);
        -o-transform: translate(-50%, -1000%);
        -webkit-filter: hue-rotate(720deg);
    }
}
</style>

在这里插入图片描述

注意:1.<style lang='less'>全局样式才能作用于创建的元素,2.z-index层级问题,鼠标不能点击 3. filter: hue-rotate(720deg)角度越大,颜色越多

Vue3的Hook版本,只需要一行引入代码即可实现

实现代码

import { onMounted, onUnmounted, ref } from "vue";

export const useMouseAnimate = () => {
  const canvasRef = ref<HTMLCanvasElement>();
  const ctx = ref<CanvasRenderingContext2D | null>(null);
  let balls: Array<{
    x: number;
    y: number;
    opacity: number;
    raduis: number;
    randomColor1: number;
    randomColor2: number;
    randomColor3: number;
  }> = [];

  /**
   * @description 初始化canvas
   */
  const initCanvas = () => {
  // 不想要全局的canvas可以自己手动修改
    const canvasEl = document.createElement("canvas");
    canvasRef.value = canvasEl;
    document.body.appendChild(canvasRef.value!);
    canvasEl.style.position = "fixed";
    canvasEl.style.top = "0";
    canvasEl.style.left = "0";
    canvasEl.style.zIndex = "9999";
    canvasEl.style.pointerEvents = "none";
    canvasEl.width = window.innerWidth;
    canvasEl.height = window.innerHeight;
    
    ctx.value = canvasEl.getContext("2d");
    if (!ctx) return;
    window.addEventListener("mousemove", initBall, true);
    requestAnimationFrame(animte);
  };
  let count = 0;
  const initBall = (event: MouseEvent) => {
    count++;
    // 避免创建太多小球
    if (count >= 3) {
      const x = event.clientX;
      const y = event.clientY;
      const random = (Math.random() + 1) * 6; //随机球的半径
      const randomColor1 = Math.floor(Math.random() * 255); //随机球的颜色
      const randomColor2 = Math.floor(Math.random() * 255); //随机球的颜色
      const randomColor3 = Math.floor(Math.random() * 255); //随机球的颜色
      balls.push({
        x,
        y,
        opacity: 1,
        raduis: random,
        randomColor1,
        randomColor2,
        randomColor3,
      });
      count = 0;
    }
  };

  const animte = () => {
    // 每一帧 将所有小球重新画出来
    ctx.value!.clearRect(0, 0, canvasRef.value!.width, canvasRef.value!.height);
    balls.forEach((ball) => {
      // 小球透明度递减
      ball.opacity -= 0.01;
      // y轴递减
      ball.y += 0.5;
      ctx.value!.beginPath();
      ctx.value!.arc(ball.x, ball.y, ball.raduis, 0, Math.PI * 2);
      ctx.value!.fillStyle = `rgba(${ball.randomColor1},${ball.randomColor2},${ball.randomColor3},${ball.opacity})`;
      ctx.value!.fill();
      // 透明度为0删除
      if (ball.opacity <= 0) {
        balls.shift();
      }
    });
    requestAnimationFrame(animte);
  };
  onMounted(() => {
    initCanvas();
  });
  onUnmounted(() => {
    window.removeEventListener("mousemove", initBall, true);
  });
};

引入

<template></template>

<script lang="ts">
export default { name: "MouseAnimate" };
</script>
<script lang="ts" setup>
import { useMouseAnimate } from "./mouse";

useMouseAnimate();
</script>

<style lang="scss" scoped></style>

在这里插入图片描述
可以将hook里面的球大小颜色等拿出来形成配置,或者不想全局的canvas,可以把canvasRef导出来给自己想要的canvas都可以

Logo

前往低代码交流专区

更多推荐