酷炫一款动态背景+鼠标点击效果(HTML +js canvas)

举报
Fivecc 发表于 2022/08/29 18:06:23 2022/08/29
【摘要】 前言 之前用于装饰个人的Hexo博客背景和点击事件,于是动手弄弄顺便学习学习,现在分享出来给有需要的人。 废话不多说 ,分享一款酷炫的页面动态背景 效果见( https://fivecc.cn ) 动态背景 1. 效果图:

前言

之前用于装饰个人的Hexo博客背景和点击事件,于是动手弄弄顺便学习学习,现在分享出来给有需要的人。

废话不多说 ,分享一款酷炫的页面动态背景 效果见( https://fivecc.cn )

动态背景

1. 效果图:

实例效果:

2. 源码:

<!--背景css-->
<style>
* {
  margin: 0;
  padding: 0;
}
#canvasBg {
  position: fixed;
  background: #ccc;
  overflow: auto;
  z-index: -1;
}
</style>

<!--背景html-->
<canvas id="canvasBg"></canvas>

<!--背景js-->
<script>
window.requestAnimationFrame = (function () {
  return (
    window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    function (callback) {
      window.setTimeout(callback, 1000 / 2);
    }
  );
})();
var myCanvas = document.getElementById("canvasBg");
var ctx = myCanvas.getContext("2d"); //getContext 设置画笔
var num;
var w, h;
var duixiang = [];
var move = {};
function widthheight() {
  w = myCanvas.width = window.innerWidth;
  h = myCanvas.height = window.innerHeight;
  num = Math.floor(w * h * 0.00028); //点的数量。根据屏幕大小确定
  for (var i = 0; i < num; i++) {
    duixiang[i] = {
      x: Math.random() * w,
      y: Math.random() * h,
      cX: Math.random() * 0.6 - 0.3,
      cY: Math.random() * 0.6 - 0.3,
      R: Math.floor(Math.random() * 5) + 2,
      //CC:Math.floor(Math.random()*3)+2,
      r: Math.floor(Math.random() * 254),
      g: Math.floor(Math.random() * 254),
      b: Math.floor(Math.random() * 254),
    };
    // console.log(duixiang[i])
    Cricle(
      duixiang[i].x,
      duixiang[i].y,
      duixiang[i].R,
      duixiang[i].r,
      duixiang[i].g,
      duixiang[i].b
    );
    //Cricle(duixiang[i].x,duixiang[i].y,duixiang[i].R,duixiang[i].CC);
  }
}
widthheight(); //获取浏览器的等宽度等高

function Cricle(x, y, R, r, g, b) {
  ctx.save(); //保存路径
  if (Math.random() > 0.991) {
    ctx.globalAlpha = 0.9;
  } //ctx.fillStyle = "#CCC";}//填充的背景颜色
  else {
    ctx.globalAlpha = 0.47;
  }

  ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
  ctx.beginPath(); //开始绘画
  ctx.arc(x, y, R, Math.PI * 2, 0); //绘画圆 x y 半径(大小) 角度  一个PI 是180 * 2 = 360    真假 0/1 true/false
  ctx.closePath(); //结束绘画
  ctx.fill(); //填充背景颜色
  ctx.restore(); //回复路径
}
Cricle();

!(function draw() {
  ctx.clearRect(0, 0, w, h); //先清除画布上的点
  for (var i = 0; i < num; i++) {
    duixiang[i].x += duixiang[i].cX;
    duixiang[i].y += duixiang[i].cY;
    if (duixiang[i].x > w || duixiang[i].x < 0) {
      duixiang[i].cX = -duixiang[i].cX;
    }
    if (duixiang[i].y > h || duixiang[i].y < 0) {
      duixiang[i].cY = -duixiang[i].cY;
    }
    Cricle(
      duixiang[i].x,
      duixiang[i].y,
      duixiang[i].R,
      duixiang[i].r,
      duixiang[i].g,
      duixiang[i].b
    );
    //勾股定理判断两点是否连线
    for (var j = i + 1; j < num; j++) {
      if (
        (duixiang[i].x - duixiang[j].x) * (duixiang[i].x - duixiang[j].x) +
          (duixiang[i].y - duixiang[j].y) * (duixiang[i].y - duixiang[j].y) <=
        55 * 55
      ) {
        line(
          duixiang[i].x,
          duixiang[i].y,
          duixiang[j].x,
          duixiang[j].y,
          0,
          i,
          j
        );
      }
      if (move.x) {
        if (
          (duixiang[i].x - move.x) * (duixiang[i].x - move.x) +
            (duixiang[i].y - move.y) * (duixiang[i].y - move.y) <=
          100 * 100
        ) {
          line(duixiang[i].x, duixiang[i].y, move.x, move.y, 1, i, 1);
        }
      }
    }
  }
  window.requestAnimationFrame(draw);
})();

//绘制线条
function line(x1, y1, x2, y2, flag, i, j) {
  if (flag) {
    var color = ctx.createLinearGradient(x1, y1, x2, y2);
    ctx.globalAlpha = 0.5;
    color.addColorStop(
      0,
      "rgb(" + duixiang[i].r + "," + duixiang[i].g + "," + duixiang[i].b + ")"
    );
    color.addColorStop(0.8, "#019ee5");
  } else {
    var color = ctx.createLinearGradient(x1, y1, x2, y2);
    ctx.globalAlpha = 0.9;
    color.addColorStop(
      0,
      "rgb(" + duixiang[i].r + "," + duixiang[i].g + "," + duixiang[i].b + ")"
    );
    color.addColorStop(
      1,
      "rgb(" + duixiang[j].r + "," + duixiang[j].g + "," + duixiang[j].b + ")"
    );
  }
  ctx.save();
  ctx.strokeStyle = color;
  ctx.lineWidth = 0.5;
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.stroke();
  //ctx.restore();
}

//document.onmousemove = function(e){
//   move.x = e.clientX;
//  move.y = e.clientY;
//}
//console.log(move)//去掉注释 ,可以与背景互动

window.onresize = function () {
  location.reload();
};
</script>

鼠标点击特效

1.鼠标点击效果

2.鼠标点击效果

<!--鼠标点击css-->
<style>
  #canvasEvent {
  position: fixed;
  pointer-events: none;
  width: 100%;
  height: 100%;
  overflow: auto;
  z-index: 999;
}
</style>

<!--鼠标点击html-->
<canvas id="canvasEvent" style="whdth: 100%;height: 100%"></canvas>

<!--鼠标点击html-->
<script>
var _createClass = (function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
})();
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}
var getRandom = function getRandom(min, max) {
  return Math.random() * (max - min) + min;
};

var getRandomInt = function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
};

var getRandomColor = function getRandomColor() {
  var colors = [
    "rgba(231, 76, 60, 1)", // 红
    "rgba(241, 196, 15, 1)", // 黄
    "rgba(46, 204, 113, 1)", // 绿
    "rgba(52, 152, 219, 1)", // 蓝
    "rgba(155, 89, 182, 1)", // 紫色
  ];

  return colors[getRandomInt(0, colors.length)];
};

// Particle//粒子模块
var Particle = (function () {
  function Particle(system, x, y) {
    _classCallCheck(this, Particle);
    this.system = system;
    this.universe = this.system.world.universe;
    this.x = x;
    this.y = y;
    this.color = getRandomColor();
    this.life = 1;
    this.aging = getRandom(0.99, 0.999); // 0.99, 0.999 || 0.999, 0.9999

    this.r = getRandomInt(12, 16); //初始粒子半径范围
    this.speed = getRandom(18, 18.5); //粒子爆炸速度范围
    this.velocity = [
      getRandom(-this.speed, this.speed),
      getRandom(-this.speed, this.speed),
    ];
  }
  _createClass(Particle, [
    {
      key: "update",
      value: function update(dt) {
        this.life *= this.aging;

        if (
          this.r < 0.1 ||
          this.life === 0 ||
          this.x + this.r < 0 ||
          this.x - this.r > this.universe.width ||
          this.y + this.r < 0 ||
          this.y - this.r > this.universe.height
        ) {
          this.system.removeObject(this);
        }

        this.r *= this.life;
        this.x += this.velocity[0];
        this.y += this.velocity[1];
      },
    },
    {
      key: "render",
      value: function render(ctx) {
        // Main circle //亮圈模块

        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r * 1.2, 0, 2 * Math.PI, false);
        ctx.fill();
        ctx.closePath();

        var r = this.color.match(/([0-9]+)/g)[0];
        var g = this.color.match(/([0-9]+)/g)[1];
        var b = this.color.match(/([0-9]+)/g)[2];

        // Gradient//梯度变化曲线

        var spread = 1.5;
        var gradient = ctx.createRadialGradient(
          this.x,
          this.y,
          this.r,
          this.x,
          this.y,
          this.r * spread
        );

        gradient.addColorStop(0, "rgba(" + r + ", " + g + ", " + b + ", 0.5)");
        gradient.addColorStop(1, "rgba(" + r + ", " + g + ", " + b + ", 0)");

        ctx.globalCompositeOperation = "lighter";
        ctx.fillStyle = gradient;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r * spread, 0, 2 * Math.PI, false);
        ctx.fill();
        ctx.closePath();
        ctx.globalCompositeOperation = "source-over";

        // Aberration//偏差

        var offset = this.r * 0.5;
        var color = "rgba(" + g + ", " + b + ", " + r + ", 0.5)";

        ctx.globalCompositeOperation = "lighter";
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(
          this.x + offset,
          this.y + offset,
          this.r,
          0,
          2 * Math.PI,
          false
        );
        ctx.fill();
        ctx.closePath();
        ctx.globalCompositeOperation = "source-over";
      },
    },
  ]);
  return Particle;
})();

// Crown //水波纹圈模块
var Crown = (function () {
  function Crown(system, x, y) {
    _classCallCheck(this, Crown);
    this.system = system;
    this.x = x;
    this.y = y;
    this.r = getRandomInt(5, 15); // 5, 20  水波纹圈半径范围
    this.mod = 1.1;
    this.life = 0.5; //水波纹线
    this.aging = getRandom(0.83, 0.899);
    this.speed = getRandom(8, 9);
    this.color = {
      r: getRandomInt(236, 242),
      g: getRandomInt(70, 80),
      b: getRandomInt(50, 70),
    };

    this.angle1 = Math.PI * getRandom(0, 2);
    this.angle2 = this.angle1 + Math.PI * getRandom(0.3, 0.4); //水波纹圈完整度
  }
  _createClass(Crown, [
    {
      key: "update",
      value: function update(dt) {
        this.life *= this.aging;

        if (this.life <= 0.0001) this.system.removeObject(this);

        this.r += Math.abs(1 - this.life) * this.speed;

        this.x1 = this.x + this.r * Math.cos(this.angle1);
        this.y1 = this.y + this.r * Math.sin(this.angle1);

        this.angle3 = this.angle1 + (this.angle2 - this.angle1) / 2;
        this.x2 = this.x + this.r * this.mod * Math.cos(this.angle3);
        this.y2 = this.y + this.r * this.mod * Math.sin(this.angle3);
      },
    },
    {
      key: "render",
      value: function render(ctx) {
        var gradient = ctx.createRadialGradient(
          this.x,
          this.y,
          this.r * 0.9,
          this.x,
          this.y,
          this.r
        );

        gradient.addColorStop(
          0,
          "rgba(" +
            this.color.r +
            ", " +
            this.color.g +
            ", " +
            this.color.b +
            ", " +
            this.life +
            ")"
        );
        gradient.addColorStop(
          1,
          "rgba(" +
            this.color.r +
            ", " +
            this.color.g +
            ", " +
            this.color.b +
            ", " +
            this.life * 0.5 +
            ")"
        );

        ctx.fillStyle = gradient;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, this.angle1, this.angle2, false);
        ctx.quadraticCurveTo(this.x2, this.y2, this.x1, this.y1);
        ctx.fill();
        ctx.closePath();
      },
    },
  ]);
  return Crown;
})();

// Explosion //爆炸模块
var Explosion = (function () {
  function Explosion(world, x, y) {
    _classCallCheck(this, Explosion);
    this.world = world;
    this.x = x;
    this.y = y;
    this.objects = [];

    var particles = getRandomInt(10, 30); // 10, 30 //爆炸 粒子数量
    var crowns = particles * getRandom(0.4, 0.5);

    while (crowns-- > 0) {
      this.addCrown();
    }
    while (particles-- > 0) {
      this.addParticle();
    }
  }
  _createClass(Explosion, [
    {
      key: "update",
      value: function update(dt) {
        this.objects.forEach(function (obj) {
          if (obj) obj.update(dt);
        });

        if (this.objects.length <= 0) {
          this.world.clearExplosion(this);
        }
      },
    },
    {
      key: "render",
      value: function render(ctx) {
        this.objects.forEach(function (obj) {
          if (obj) obj.render(ctx);
        });
      },
    },
    {
      key: "addCrown",
      value: function addCrown() {
        this.objects.push(new Crown(this, this.x, this.y));
      },
    },
    {
      key: "addParticle",
      value: function addParticle() {
        this.objects.push(new Particle(this, this.x, this.y));
      },
    },
    {
      key: "removeObject",
      value: function removeObject(obj) {
        var index = this.objects.indexOf(obj);

        if (index !== -1) {
          this.objects.splice(index, 1);
        }
      },
    },
  ]);
  return Explosion;
})();

// World
var ConfettiWorld = (function () {
  function ConfettiWorld() {
    _classCallCheck(this, ConfettiWorld);
  }
  _createClass(ConfettiWorld, [
    {
      key: "init",
      value: function init() {
        this.objects = [];
        window.addEventListener("click", this.explode.bind(this));

        // Initial explosion //初始爆炸
        var counter = 0;
        while (counter-- > 0) {
          this.explode({
            clientX: window.event.clientX, //getRandomInt(10, this.universe.width) ,          //this.universe.width / 2,
            clientY: window.event.clientY, //getRandomInt(10, 50) //this.universe.height / 2
          });
        }
      },
    },
    {
      key: "update",
      value: function update(dt) {
        this.objects.forEach(function (obj) {
          if (obj) obj.update(dt);
        });

        var amount = this.objects.reduce(function (sum, explosion) {
          return (sum += explosion.objects.length);
        }, 0);
      },
    },
    {
      key: "render",
      value: function render(ctx) {
        this.objects.forEach(function (obj) {
          if (obj) obj.render(ctx);
        });
      },
    },
    {
      key: "explode",
      value: function explode(event) {
        var x = event.clientX;
        var y = event.clientY;

        this.objects.push(new Explosion(this, x, y));
      },
    },
    {
      key: "clearExplosion",
      value: function clearExplosion(explosion) {
        var index = this.objects.indexOf(explosion);

        if (index !== -1) {
          this.objects.splice(index, 1);
        }
      },
    },
  ]);
  return ConfettiWorld;
})();

// Time
var Time = (function () {
  function Time() {
    _classCallCheck(this, Time);
    this.now = 0; // 当前粒子时间
    this.prev = 0; // 上一粒子时间
    this.elapsed = 0; //最后粒子时间
    this.delta = 0; // 从上次更新开始的时间
    this.fps = 60; // 期望fps
    this.step = 1 / 60; // 步长
  }
  _createClass(Time, [
    {
      key: "update",
      value: function update(time) {
        this.now = time;
        this.elapsed = (this.now - this.prev) / 1000;
        this.prev = this.now;
        this.delta += this.elapsed;
      },
    },
    {
      key: "raf",
      value: function raf(func) {
        window.requestAnimationFrame(func);
      },
    },
    {
      key: "hasFrames",
      value: function hasFrames() {
        return this.delta >= this.step;
      },
    },
    {
      key: "processFrame",
      value: function processFrame() {
        this.delta -= this.step;
      },
    },
  ]);
  return Time;
})();

// Canvas
var Universe = (function () {
  function Universe(element) {
    _classCallCheck(this, Universe);
    this.el = element;
    this.ctx = this.el.getContext("2d");
    this.pixelRatio = window.devicePixelRatio;
    this.time = new Time();

    this.worlds = {};
    this.world = null; // current state

    this.updateSize();
    window.addEventListener("resize", this.updateSize.bind(this));

    this.addWorld("confetti", ConfettiWorld);
    this.setWorld("confetti");

    this.start();
  }
  _createClass(Universe, [
    {
      key: "start",
      value: function start() {
        this.time.raf(this.tick.bind(this));
      },
    },
    {
      key: "tick",
      value: function tick(time) {
        this.time.update(time);

        if (this.time.hasFrames()) {
          this.update();
          this.time.processFrame();
        }

        this.render();
        this.time.raf(this.tick.bind(this));
      },
    },
    {
      key: "update",
      value: function update() {
        this.world.update(this.time.step);
      },
    },
    {
      key: "render",
      value: function render() {
        var gradient = this.ctx.createLinearGradient(
          0,
          0,
          this.width,
          this.height
        );
        this.ctx.clearRect(0, 0, this.width, this.height);
        this.world.render(this.ctx);
      },

      // Helpers 库
    },
    {
      key: "updateSize",
      value: function updateSize() {
        this.width = window.innerWidth;
        this.height = window.innerHeight;
        this.el.width = this.width * this.pixelRatio;
        this.el.height = this.height * this.pixelRatio;
        this.el.style.width = window.innerWidth + "px";
        this.el.style.height = window.innerHeight + "px";
        this.ctx.scale(this.pixelRatio, this.pixelRatio);
      },
    },
    {
      key: "addWorld",
      value: function addWorld(worldName, World) {
        this.worlds[worldName] = new World();
        this.worlds[worldName].universe = this;
        this.worlds[worldName].init();
      },
    },
    {
      key: "setWorld",
      value: function setWorld(worldName) {
        this.world = this.worlds[worldName];
      },
    },
  ]);
  return Universe;
})();

// Main
console.clear();
var element = document.querySelector("#canvasEvent");
window.Canvas = new Universe(element);

</script>

喜欢就给我点一个大大的赞是👍 外加一个关注

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。