前端开发 之 12个鼠标交互特效上【附完整源码】

前端开发 之 12个鼠标交互特效上【附完整源码】

文章目录

一:彩色空心爱心滑动特效

1.效果展示
2.HTML完整代码
html 复制代码
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>超级炫酷的爱心滑动特效</title>
  <style>
    body {
      overflow: hidden;
      margin: 0;
      background: #222;
    }

    canvas {
      display: block;
    }
  </style>
</head>

<body>
  <canvas></canvas>
  <script>
    var canvas = document.querySelector("canvas"),
      ctx = canvas.getContext("2d");

    var ww, wh;

    function onResize() {
      ww = canvas.width = window.innerWidth;
      wh = canvas.height = window.innerHeight;
    }

    function randomColor() {
      return `hsla(${Math.random() * 360}, 100%, 60%, 1)`;
    }

    var precision = 100;
    var hearts = [];
    var mouseMoved = false;

    function onMove(e) {
      mouseMoved = true;
      for (let i = 0; i < 5; i++) { // 生成更多的爱心
        let x, y;
        if (e.type === "touchmove") {
          x = e.touches[0].clientX;
          y = e.touches[0].clientY;
        } else {
          x = e.clientX;
          y = e.clientY;
        }
        hearts.push(new Heart(x, y));
      }
    }

    var Heart = function (x, y) {
      this.x = x || Math.random() * ww;
      this.y = y || Math.random() * wh;
      this.size = Math.random() * 4 + 1;
      this.shadowBlur = Math.random() * 20;
      this.speedX = (Math.random() - 0.5) * 10;
      this.speedY = (Math.random() - 0.5) * 10;
      this.speedSize = Math.random() * 0.05 + 0.01;
      this.opacity = 1;
      this.color = randomColor();
      this.vertices = [];
      for (var i = 0; i < precision; i++) {
        var step = (i / precision - 0.5) * (Math.PI * 2);
        var vector = {
          x: (15 * Math.pow(Math.sin(step), 3)),
          y: -(13 * Math.cos(step) - 5 * Math.cos(2 * step) - 2 * Math.cos(3 * step) - Math.cos(4 * step))
        }
        this.vertices.push(vector);
      }
    }

    Heart.prototype.draw = function () {
      this.size -= this.speedSize;
      this.x += this.speedX;
      this.y += this.speedY;
      ctx.save();
      ctx.translate(this.x, this.y);
      ctx.scale(this.size, this.size);
      ctx.beginPath();
      ctx.strokeStyle = this.color;
      ctx.shadowBlur = this.shadowBlur;
      ctx.shadowColor = this.color;
      for (var i = 0; i < precision; i++) {
        var vector = this.vertices[i];
        ctx.lineTo(vector.x, vector.y);
      }
      ctx.globalAlpha = this.size;
      ctx.closePath();
      ctx.stroke();
      ctx.restore();
    };

    function render(a) {
      requestAnimationFrame(render);
      ctx.clearRect(0, 0, ww, wh);
      for (var i = 0; i < hearts.length; i++) {
        hearts[i].draw();
        if (hearts[i].size <= 0) {
          hearts.splice(i, 1);
          i--;
        }
      }
    }

    onResize();
    window.addEventListener("mousemove", onMove);
    window.addEventListener("touchmove", onMove);
    window.addEventListener("resize", onResize);
    requestAnimationFrame(render);
  </script>
</body>
</html>

二:彩色实心爱心滑动特效

1.效果展示
2.HTML完整代码
html 复制代码
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>滑动爱心</title>
  <style>
    body {
      overflow: hidden;
      margin: 0;
      background: linear-gradient(to right, #ff9a9e, #fad0c4);
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    canvas {
      position: absolute;
      top: 0;
      left: 0;
    }
  </style>
</head>
<body>
  <canvas></canvas>
  <script>
    var canvas = document.querySelector("canvas"),
      ctx = canvas.getContext("2d");

    var ww, wh;

    function onResize() {
      ww = canvas.width = window.innerWidth;
      wh = canvas.height = window.innerHeight;
    }

    var precision = 50;
    var hearts = [];
    var mouseMoved = false;

    function onMove(e) {
      mouseMoved = true;
      var x, y;
      if (e.type === "touchmove") {
        x = e.touches[0].clientX;
        y = e.touches[0].clientY;
      } else {
        x = e.clientX;
        y = e.clientY;
      }
      hearts.push(new Heart(x, y));
    }

    var Heart = function (x, y) {
      this.x = x || Math.random() * ww;
      this.y = y || Math.random() * wh;
      this.size = Math.random() * 2 + 1;
      this.maxSize = this.size * 1.5;
      this.shadowBlur = Math.random() * 15;
      this.speedX = (Math.random() - 0.5) * 4;
      this.speedY = (Math.random() - 0.5) * 4;
      this.alpha = 1;
      this.fadeSpeed = Math.random() * 0.02 + 0.02;
      this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;
      this.vertices = [];
      for (var i = 0; i < precision; i++) {
        var step = (i / precision - 0.5) * (Math.PI * 2);
        var vector = {
          x: (15 * Math.pow(Math.sin(step), 3)),
          y: -(13 * Math.cos(step) - 5 * Math.cos(2 * step) - 2 * Math.cos(3 * step) - Math.cos(4 * step))
        }
        this.vertices.push(vector);
      }
    }

    Heart.prototype.draw = function () {
      this.x += this.speedX;
      this.y += this.speedY;
      this.size += (this.maxSize - this.size) * 0.1;
      this.alpha -= this.fadeSpeed;

      ctx.save();
      ctx.translate(this.x, this.y);
      ctx.scale(this.size, this.size);
      ctx.beginPath();
      ctx.moveTo(0, 0);
      for (var i = 0; i < precision; i++) {
        var vector = this.vertices[i];
        ctx.lineTo(vector.x, vector.y);
      }
      ctx.closePath();
      ctx.fillStyle = this.color;
      ctx.globalAlpha = this.alpha;
      ctx.shadowBlur = this.shadowBlur;
      ctx.shadowColor = this.color;
      ctx.fill();
      ctx.restore();
    };

    function render(a) {
      requestAnimationFrame(render);
      ctx.clearRect(0, 0, ww, wh);
      for (var i = 0; i < hearts.length; i++) {
        hearts[i].draw();
        if (hearts[i].alpha <= 0) {
          hearts.splice(i, 1);
          i--;
        }
      }
    }

    onResize();
    window.addEventListener("mousemove", onMove);
    window.addEventListener("touchmove", onMove);
    window.addEventListener("resize", onResize);
    requestAnimationFrame(render);
  </script>
</body>
</html>

三:粒子连结特效

1.效果展示
2.HTML完整代码
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced Particle System with Cool Effects</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: linear-gradient(45deg, #000, #333);
            animation: bgGradient 10s ease infinite;
        }

        @keyframes bgGradient {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }

        canvas {
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="particleCanvas"></canvas>
</body>
<script>
const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let particlesArray = [];
const numberOfParticles = 50;
const mouse = {
    x: undefined,
    y: undefined,
};
const maxParticleLifeTime = 1; 

class Particle {
    constructor(x, y, initialLife = 1) {
        this.x = x || Math.random() * canvas.width;
        this.y = y || Math.random() * canvas.height;
        this.size = Math.random() * 2 + 1;
        this.speedX = (Math.random() - 0.5) * 2;
        this.speedY = (Math.random() - 0.5) * 2;
        this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;
        this.alpha = 1;
        this.decay = Math.random() * 0.01 + 0.01;
        this.life = initialLife;
        this.trail = [];
        this.lifeTime = 0; 
    }

    update() {
        this.x += this.speedX;
        this.y += this.speedY;

        if (this.x > canvas.width || this.x < 0) this.speedX *= -1;
        if (this.y > canvas.height || this.y < 0) this.speedY *= -1;

        if (mouse.x && mouse.y) {
            const dx = mouse.x - this.x;
            const dy = mouse.y - this.y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            const force = 1 / distance * 20;
            this.speedX += (dx / distance) * force;
            this.speedY += (dy / distance) * force;
        }

        this.life -= this.decay;
        this.alpha = this.life;
        this.color = `hsl(${(1 - this.life) * 360}, 100%, 50%)`;
        this.lifeTime += 1 / 60; 
        if (this.life <= 0 || this.lifeTime >= maxParticleLifeTime) {
            this.reset();
        }
        this.trail.push({ x: this.x, y: this.y });
        if (this.trail.length > 15) this.trail.shift();

        for (let otherParticle of particlesArray) {
            if (otherParticle !== this) {
                const dx = this.x - otherParticle.x;
                const dy = this.y - otherParticle.y;
                const distance = Math.sqrt(dx * dx + dy * dy);
                if (distance < 50) {
                    const repelForce = 0.1 / distance;
                    this.speedX -= (dx / distance) * repelForce;
                    this.speedY -= (dy / distance) * repelForce;
                }
            }
        }
    }

    draw() {
        ctx.globalAlpha = this.alpha;
        ctx.fillStyle = this.color;

        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.closePath();
        ctx.fill();

        ctx.globalAlpha = 0.7 * this.alpha;
        ctx.beginPath();
        for (let i = 0; i < this.trail.length; i++) {
            ctx.lineTo(this.trail[i].x, this.trail[i].y);
        }
        ctx.strokeStyle = this.color;
        ctx.lineWidth = 0.5;
        ctx.stroke();
        ctx.closePath();
    }

    reset() {
        this.x = Math.random() * canvas.width;
        this.y = Math.random() * canvas.height;
        this.size = Math.random() * 2 + 1;
        this.speedX = (Math.random() - 0.5) * 4;
        this.speedY = (Math.random() - 0.5) * 4;
        this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;
        this.alpha = 1;
        this.life = 1;
        this.decay = Math.random() * 0.01 + 0.01;
        this.trail = [];
        this.lifeTime = 0;
    }
}

function init() {
    particlesArray = [];
    for (let i = 0; i < numberOfParticles; i++) {
        particlesArray.push(new Particle());
    }
}

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (let particle of particlesArray) {
        particle.update();
        particle.draw();
    }

    requestAnimationFrame(animate);
}

window.addEventListener('resize', function() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    init();
});

window.addEventListener('mousemove', function(event) {
    mouse.x = event.x;
    mouse.y = event.y;
});

window.addEventListener('mouseout', function() {
    mouse.x = undefined;
    mouse.y = undefined;
});

window.addEventListener('click', function(event) {
    for (let i = 0; i < 30; i++) {
        const angle = Math.random() * 2 * Math.PI;
        const distance = Math.random() * 50;
        const x = event.x + Math.cos(angle) * distance;
        const y = event.y + Math.sin(angle) * distance;
        particlesArray.push(new Particle(x, y, 1));
    }
});

init();
animate();
</script>
</html>

四:彩色拖尾特效

1.效果展示
2.HTML完整代码
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1234</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: #000;
        }

        #trail-container {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .particle {
            position: absolute;
            width: 3px; /* 减小粒子大小 */
            height: 3px;
            background-color: #fff;
            border-radius: 50%;
            opacity: 1;
            transform: translate(-50%, -50%);
            pointer-events: none;
            mix-blend-mode: screen;
        }

        /* 为粒子添加一个更快的淡出动画 */
        @keyframes fadeOut {
            0% { opacity: 1; }
            100% { opacity: 0; }
        }

        .particle.fade {
            animation: fadeOut 0.5s ease-out forwards; /* 缩短动画持续时间 */
        }
    </style>
</head>
<body>
    <div id="trail-container"></div>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const trailContainer = document.getElementById('trail-container');
            const particles = [];

            // 监听鼠标移动事件
            document.addEventListener('mousemove', (e) => {
                // 在鼠标位置创建粒子
                createParticle(e.clientX, e.clientY);
            });

            // 创建粒子
            function createParticle(x, y) {
                const particle = document.createElement('div');
                particle.classList.add('particle');
                particle.style.left = `${x}px`;
                particle.style.top = `${y}px`;
                // 使用随机颜色或固定颜色
                particle.style.backgroundColor = getRandomColor();
                trailContainer.appendChild(particle);
                particles.push(particle);

                // 几乎立即给粒子添加淡出动画
                setTimeout(() => {
                    particle.classList.add('fade');
                    // 动画结束后移除粒子
                    particle.addEventListener('animationend', () => {
                        particle.remove();
                        particles.splice(particles.indexOf(particle), 1);
                    });
                }, 100); // 非常短的延迟,几乎立即开始淡出
            }

            // 获取随机颜色
            function getRandomColor() {
                const letters = '0123456789ABCDEF';
                let color = '#';
                for (let i = 0; i < 6; i++) {
                    color += letters[Math.floor(Math.random() * 16)];
                }
                return color;
            }

            // 定期清理,动画结束后粒子会自动移除
            setInterval(() => {
                particles.forEach(particle => {
                    if (particle.classList.contains('fade')) {
                        particle.remove();
                        particles.splice(particles.indexOf(particle), 1);
                    }
                });
            }, 1000);
        });
    </script>
</body>
</html>

五:彩色粒子收回特效

1.效果展示
2.HTML完整代码
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced Particle System with Gravity and Wind</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        #particleCanvas {
            display: block;
            width: 100%;
            height: 100%;
            background: linear-gradient(to bottom, #000000, #111111);
        }
    </style>
</head>
<body>
    <canvas id="particleCanvas"></canvas>
    <script>
        const canvas = document.getElementById('particleCanvas');
        const ctx = canvas.getContext('2d');

        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        const particlesArray = [];
        const numberOfParticles = 500; 
        const mouse = {
            x: undefined,
            y: undefined,
        };

        const gravity = 0.05; 
        const wind = {
            x: 0.01, 
            y: 0,
        };

        class Particle {
            constructor() {
                this.x = Math.random() * canvas.width;
                this.y = Math.random() * canvas.height;
                this.size = Math.random() * 5 + 1; 
                this.speedX = (Math.random() - 0.5) * 4; 
                this.speedY = (Math.random() - 0.5) * 4;
                this.color = 'hsl(' + Math.floor(Math.random() * 360) + ', 100%, 50%)';
                this.alpha = 1; 
                this.targetX = this.x;
                this.targetY = this.y;
                this.ease = 0.05;
            }

            update() {
                if (mouse.x !== undefined && mouse.y !== undefined) {
                    this.targetX = mouse.x;
                    this.targetY = mouse.y;
                }
                this.x += (this.targetX - this.x) * this.ease;
                this.y += (this.targetY - this.y) * this.ease;

                this.speedY += gravity;
                this.speedX += wind.x;

                if (this.x > canvas.width || this.x < 0) this.speedX *= -1;
                if (this.y > canvas.height) this.y = canvas.height, this.speedY *= -0.7; 
                this.alpha -= 0.01; 
                if (this.alpha < 0) this.alpha = 0;

                this.draw();
            }

            draw() {
                ctx.globalAlpha = this.alpha;
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.closePath();
                ctx.fill();
            }
        }

        function init() {
            for (let i = 0; i < numberOfParticles; i++) {
                particlesArray.push(new Particle());
            }
        }

        function animate() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            for (let particle of particlesArray) {
                particle.update();
            }

            requestAnimationFrame(animate);
        }

        window.addEventListener('resize', function() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });

        window.addEventListener('mousemove', function(event) {
            mouse.x = event.x;
            mouse.y = event.y;
        });

        window.addEventListener('mouseout', function() {
            mouse.x = undefined;
            mouse.y = undefined;
        });

        window.addEventListener('click', function() {
            for (let i = 0; i < 20; i++) {
                particlesArray.push(new Particle());
            }
        });

        init();
        animate();
    </script>
</body>
</html>

六:彩色粒子交互特效

1.效果展示
2.HTML完整代码
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>彩色粒子交互特效</title>
</head>
<body>
<script>
    !(function () {
      function n(n, e, t) {
        return n.getAttribute(e) || t;
      }
      function e(n) {
        return document.getElementsByTagName(n);
      }
      function t() {
        var t = e("script"),
          o = t.length,
          i = t[o - 1];
        return {
          l: o,
          z: n(i, "zIndex", -1),
          o: n(i, "opacity", 0.6),
          c: n(i, "color", "0,255,0"), 
          n: n(i, "count", 400), // 粒子的数量
        };
      }

      function o() {
        (a = m.width =
          window.innerWidth ||
          document.documentElement.clientWidth ||
          document.body.clientWidth),
          (c = m.height =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight);
      }
      function i() {
        r.clearRect(0, 0, a, c);
        var n, e, t, o, m, l;
        s.forEach(function (particle, index) {
          for (
            particle.x += particle.xa,
            particle.y += particle.ya,
            particle.xa *= particle.x > a || particle.x < 0 ? -1 : 1,
            particle.ya *= particle.y > c || particle.y < 0 ? -1 : 1,
            // 使用粒子的颜色属性进行绘制
            r.fillStyle = particle.color,
            r.fillRect(particle.x - 0.5, particle.y - 0.5, 1, 1),
            e = index + 1;
            e < u.length;
            e++
          ) {
            (n = u[e]),
              null !== n.x &&
              null !== n.y &&
              ((o = particle.x - n.x),
                (m = particle.y - n.y),
                (l = o * o + m * m),
                l < n.max &&
                (n === y &&
                  l >= n.max / 2 &&
                  ((particle.x -= 0.03 * o), (particle.y -= 0.03 * m)),
                  (t = (n.max - l) / n.max),
                  r.beginPath(),
                  (r.lineWidth = t / 2),
                  // 连线颜色和粒子颜色一致
                  r.strokeStyle = particle.color,
                  r.moveTo(particle.x, particle.y),
                  r.lineTo(n.x, n.y),
                  r.stroke()));
          }
        }),
          x(i);
      }
      var fixedColors = [
        "rgba(255, 0, 0, 1.0)",   // 红色
        "rgba(0, 255, 0, 1.0)",   // 绿色
        "rgba(0, 0, 255, 1.0)",   // 蓝色
        "rgba(255, 255, 0, 1.0)", // 黄色
        "rgba(0, 255, 255, 0.8)", // 青色
        "rgba(255, 0, 255, 0.8)", // 紫色
        "rgba(255, 165, 0, 0.8)", // 橙色
        "rgba(127, 255, 212, 1.0)",
          "rgba(0, 255, 127, 1.0)"
      ];
      var a,
        c,
        u,
        m = document.createElement("canvas"),
        d = t(),
        l = "c_n" + d.l,
        r = m.getContext("2d"),
        x =
          window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (n) {
            window.setTimeout(n, 1e3 / 45);
          },
        w = Math.random,
        y = { x: null, y: null, max: 2e4 };
      (m.id = l),
        (m.style.cssText =
          "position:fixed;top:0;left:0;z-index:" + d.z + ";opacity:" + d.o),
        e("body")[0].appendChild(m),
        o(),
        (window.onresize = o),
        (window.onmousemove = function (n) {
          (n = n || window.event), (y.x = n.clientX), (y.y = n.clientY);
        }),
        (window.onmouseout = function () {
          (y.x = null), (y.y = null);
        });

        //固定颜色
        for (var s = [], f = 0; d.n > f; f++) {
        var h = w() * a,
          g = w() * c,
          v = 2 * w() - 1,
          p = 2 * w() - 1,
          // 从固定颜色数组中随机选择一个颜色
          color = fixedColors[Math.floor(Math.random() * fixedColors.length)];
        s.push({ x: h, y: g, xa: v, ya: p, max: 6e3, color: color }); // 使用选定的固定颜色
      }

      (u = s.concat([y])),
        setTimeout(function () {
          i();
        }, 100);
    })();
  </script>
</body>
</html>
相关推荐
NEXT066 分钟前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法
剪刀石头布啊12 分钟前
生成随机数,Math.random的使用
前端
剪刀石头布啊12 分钟前
css外边距重叠问题
前端
剪刀石头布啊13 分钟前
chrome单页签内存分配上限问题,怎么解决
前端
剪刀石头布啊15 分钟前
css实现一个宽高固定百分比的布局的一个方式
前端
剪刀石头布啊18 分钟前
js数组之快速组、慢数组、密集数组、稀松数组
前端
Ro Jace22 分钟前
计算机专业基础教材
java·开发语言
代码游侠38 分钟前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
mango_mangojuice40 分钟前
Linux学习笔记(make/Makefile)1.23
java·linux·前端·笔记·学习
devmoon1 小时前
运行时(Runtime)是什么?为什么 Polkadot 的 Runtime 可以被“像搭积木一样”定制
开发语言·区块链·智能合约·polkadot·runtmie