当前位置: 首页 > article >正文

HTML爱心流星雨

目录

写在前面

完整代码

代码分析

推荐系列

写在后面


在前面

如何用HTML代码实现爱心+流星雨的动态效果?本期博主将带着大家探索神奇的HTML。

完整代码

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>爱心流星雨</title>
  <style>
    html,
    body {
      height: 100%;
      padding: 0;
      margin: 0;
      background-color: black;
    }
    canvas {
      position: absolute;
      width: 100%;
      height: 100%;
    }
</style>
</head>
<body>
  <canvas id="pinkboard"></canvas>
  <canvas id="stars"></canvas>
  <script>
    var context;
    var arr = new Array();
    var starCount = 800;
    var rains = new Array();
    var rainCount = 20;
    //初始化画布及context
    function init() {
      //获取canvas
      var stars = document.getElementById("stars");
      windowWidth = window.innerWidth; //当前的窗口的高度
      stars.width = windowWidth;
      stars.height = window.innerHeight;
      //获取context
      context = stars.getContext("2d");
    }
    //创建一个星星对象
    var Star = function () {
      this.x = windowWidth * Math.random();//横坐标
      this.y = 5000 * Math.random();//纵坐标
      this.text = "❤";//文本
      this.color = "#ea80b0";//颜色
      //产生随机颜色
      this.getColor = function () {
        var _r = Math.random();
        if (_r < 0.5) {
          this.color = "#333";
        } else {
          this.color = "#ea80b0";
        }
      }
      //初始化
      this.init = function () {
        this.getColor();
      }
      //绘制
      this.draw = function () {
        context.fillStyle = this.color;
        context.fillText(this.text, this.x, this.y);
      }
    }
    //页面加载的时候
    window.onload = function () {
      init();
      //画星星
      for (var i = 0; i < starCount; i++) {
        var star = new Star();
        star.init();
        star.draw();
        arr.push(star);
      }
      //画流星
      for (var i = 0; i < rainCount; i++) {
        var rain = new MeteorRain();
        rain.init();
        rain.draw();
        rains.push(rain);
      }
      playStars();//绘制闪动的星星
      playRains();//绘制流星
    }
    //星星闪起来
    function playStars() {
      for (var n = 0; n < starCount; n++) {
        arr[n].getColor();
        arr[n].draw();
      }
      setTimeout("playStars()", 100);
    }
    var MeteorRain = function () {
      this.x = -1;
      this.y = -1;
      this.length = -1;//长度
      this.angle = 30; //倾斜角度
      this.width = -1;//宽度
      this.height = -1;//高度
      this.speed = 1;//速度
      this.offset_x = -1;//横轴移动偏移量
      this.offset_y = -1;//纵轴移动偏移量
      this.alpha = 1; //透明度
      this.color1 = "#ea80b0";//流星的色彩
      this.color2 = "";  //流星的色彩
      this.init = function () //初始化
{
        this.getPos();
        this.alpha = 1;//透明度
        this.getRandomColor();
        //最小长度,最大长度
        var x = Math.random() * 80 + 150;
        this.length = Math.ceil(x);
        //                  x = Math.random()*10+30;
        this.angle = 30; //流星倾斜角
        x = Math.random() + 0.5;
        this.speed = Math.ceil(x); //流星的速度
        var cos = Math.cos(this.angle * 3.14 / 180);
        var sin = Math.sin(this.angle * 3.14 / 180);
        this.width = this.length * cos;  //流星所占宽度
        this.height = this.length * sin;//流星所占高度
        this.offset_x = this.speed * cos;
        this.offset_y = this.speed * sin;
      }
      this.getRandomColor = function () {
        var a = Math.ceil(255 - 240 * Math.random());
        //中段颜色
        this.color1 = "rgba(" + a + "," + a + "," + a + ",1)";
        //结束颜色
        this.color2 = "black";
      }
      this.countPos = function ()//
{
        //往左下移动,x减少,y增加
        this.x = this.x - this.offset_x;
        this.y = this.y + this.offset_y;
      }
      this.getPos = function () //
{
        //横坐标200--1200
        this.x = Math.random() * window.innerWidth; //窗口高度
        //纵坐标小于600
        this.y = Math.random() * window.innerHeight;  //窗口宽度
      }
      this.draw = function () //绘制一个流星的函数
{
        context.save();
        context.beginPath();
        context.lineWidth = 1; //宽度
        context.globalAlpha = this.alpha; //设置透明度
        //创建横向渐变颜色,起点坐标至终点坐标
        var line = context.createLinearGradient(this.x, this.y,
          this.x + this.width,
          this.y - this.height);
        //分段设置颜色
        line.addColorStop(0, "#ea80b0");
        line.addColorStop(0.3, this.color1);
        line.addColorStop(0.6, this.color2);
        context.strokeStyle = line;
        //起点
        context.moveTo(this.x, this.y);
        //终点
        context.lineTo(this.x + this.width, this.y - this.height);
        context.closePath();
        context.stroke();
        context.restore();
      }
      this.move = function () {
        //清空流星像素
        var x = this.x + this.width - this.offset_x;
        var y = this.y - this.height;
        context.clearRect(x - 3, y - 3, this.offset_x + 5, this.offset_y + 5);
        //                  context.strokeStyle="red";
        //                  context.strokeRect(x,y-1,this.offset_x+1,this.offset_y+1);
        //重新计算位置,往左下移动
        this.countPos();
        //透明度增加
        this.alpha -= 0.002;
        //重绘
        this.draw();
      }
    }
    //绘制流星
    function playRains() {

      for (var n = 0; n < rainCount; n++) {
        var rain = rains[n];
        rain.move();//移动
        if (rain.y > window.innerHeight) {//超出界限后重来
          context.clearRect(rain.x, rain.y - rain.height, rain.width, rain.height);
          rains[n] = new MeteorRain();
          rains[n].init();
        }
      }
      setTimeout("playRains()", 2);
    }
    var settings = {
      particles: {
        length: 500, 
        duration: 2, 
        velocity: 100, 
        effect: -0.75, 
        size: 20, 
      },
    };
    (function () {
      var b = 0;
      var c = ["ms", "moz", "webkit", "o"];
      for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) { window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[c[a] + "CancelAnimationFrame"] || window[c[a] + "CancelRequestAnimationFrame"] }
      if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function (h, e) { var d = new Date().getTime(); var f = Math.max(0, 16 - (d - b)); var g = window.setTimeout(function () { h(d + f) }, f); b = d + f; return g }
      } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (d) { clearTimeout(d) } }
    }());
    var Point = (function () {
      function Point(x, y) {
        this.x = (typeof x !== 'undefined') ? x : 0;
        this.y = (typeof y !== 'undefined') ? y : 0;
      }
      Point.prototype.clone = function () {
        return new Point(this.x, this.y);
      };
      Point.prototype.length = function (length) {
        if (typeof length == 'undefined')
          return Math.sqrt(this.x * this.x + this.y * this.y);
        this.normalize();
        this.x *= length;
        this.y *= length;
        return this;
      };
      Point.prototype.normalize = function () {
        var length = this.length();
        this.x /= length;
        this.y /= length;
        return this;
      };
      return Point;
    })();
    var Particle = (function () {
      function Particle() {
        this.position = new Point();
        this.velocity = new Point();
        this.acceleration = new Point();
        this.age = 0;
      }
      Particle.prototype.initialize = function (x, y, dx, dy) {
        this.position.x = x;
        this.position.y = y;
        this.velocity.x = dx;
        this.velocity.y = dy;
        this.acceleration.x = dx * settings.particles.effect;
        this.acceleration.y = dy * settings.particles.effect;
        this.age = 0;
      };
      Particle.prototype.update = function (deltaTime) {
        this.position.x += this.velocity.x * deltaTime;
        this.position.y += this.velocity.y * deltaTime;
        this.velocity.x += this.acceleration.x * deltaTime;
        this.velocity.y += this.acceleration.y * deltaTime;
        this.age += deltaTime;
      };
      Particle.prototype.draw = function (context, image) {
        function ease(t) {
          return (--t) * t * t + 1;
        }
        var size = image.width * ease(this.age / settings.particles.duration);
        context.globalAlpha = 1 - this.age / settings.particles.duration;
        context.drawImage(image, this.position.x - size / 2, this.position.y - size / 2, size, size);
      };
      return Particle;
    })();
    var ParticlePool = (function () {
      var particles,
        firstActive = 0,
        firstFree = 0,
        duration = settings.particles.duration;
      function ParticlePool(length) {
        particles = new Array(length);
        for (var i = 0; i < particles.length; i++)
          particles[i] = new Particle();
      }
      ParticlePool.prototype.add = function (x, y, dx, dy) {
        particles[firstFree].initialize(x, y, dx, dy);
        firstFree++;
        if (firstFree == particles.length) firstFree = 0;
        if (firstActive == firstFree) firstActive++;
        if (firstActive == particles.length) firstActive = 0;
      };
      ParticlePool.prototype.update = function (deltaTime) {
        var i;
        if (firstActive < firstFree) {
          for (i = firstActive; i < firstFree; i++)
            particles[i].update(deltaTime);
        }
        if (firstFree < firstActive) {
          for (i = firstActive; i < particles.length; i++)
            particles[i].update(deltaTime);
          for (i = 0; i < firstFree; i++)
            particles[i].update(deltaTime);
        }
        while (particles[firstActive].age >= duration && firstActive != firstFree) {
          firstActive++;
          if (firstActive == particles.length) firstActive = 0;
        }
      };
      ParticlePool.prototype.draw = function (context, image) {
        if (firstActive < firstFree) {
          for (i = firstActive; i < firstFree; i++)
            particles[i].draw(context, image);
        }
        if (firstFree < firstActive) {
          for (i = firstActive; i < particles.length; i++)
            particles[i].draw(context, image);
          for (i = 0; i < firstFree; i++)
            particles[i].draw(context, image);
        }
      };
      return ParticlePool;
    })();
    (function (canvas) {
      var context = canvas.getContext('2d'),
        particles = new ParticlePool(settings.particles.length),
        particleRate = settings.particles.length / settings.particles.duration, 
        time;
      function pointOnHeart(t) {
        return new Point(
          160 * Math.pow(Math.sin(t), 3),
          130 * Math.cos(t) - 50 * Math.cos(2 * t) - 20 * Math.cos(3 * t) - 10 * Math.cos(4 * t) + 25
        );
      }
      var image = (function () {
        var canvas = document.createElement('canvas'),
          context = canvas.getContext('2d');
        canvas.width = settings.particles.size;
        canvas.height = settings.particles.size;
        function to(t) {
          var point = pointOnHeart(t);
          point.x = settings.particles.size / 2 + point.x * settings.particles.size / 350;
          point.y = settings.particles.size / 2 - point.y * settings.particles.size / 350;
          return point;
        }
        context.beginPath();
        var t = -Math.PI;
        var point = to(t);
        context.moveTo(point.x, point.y);
        while (t < Math.PI) {
          t += 0.01;
          point = to(t);
          context.lineTo(point.x, point.y);
        }
        context.closePath();
        context.fillStyle = '#ea80b0';
        context.fill();
        var image = new Image();
        image.src = canvas.toDataURL();
        return image;
      })();
      function render() {
        requestAnimationFrame(render);
        var newTime = new Date().getTime() / 1000,
          deltaTime = newTime - (time || newTime);
        time = newTime;
        context.clearRect(0, 0, canvas.width, canvas.height);
        var amount = particleRate * deltaTime;
        for (var i = 0; i < amount; i++) {
          var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());
          var dir = pos.clone().length(settings.particles.velocity);
          particles.add(canvas.width / 2 + pos.x, canvas.height / 2 - pos.y, dir.x, -dir.y);
        }
        particles.update(deltaTime);
        particles.draw(context, image);
      }
      function onResize() {
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
      }
      window.onresize = onResize;
      setTimeout(function () {
        onResize();
        render();
      }, 10);
    })(document.getElementById('pinkboard'));
</script>
</body>
</html>

代码分析

HTML和CSS

页面主要包含两个部分:一个<canvas>标签用于绘制粒子爱心效果,另一个<canvas>标签用于绘制闪烁的心形和流星动画。CSS设置了整个页面的背景颜色为黑色,并使两个画布覆盖整个浏览器窗口。

JavaScript

JavaScript部分主要通过window.onload事件来初始化画布和启动动画。init()函数设置了stars画布的宽度和高度,并获取其绘图上下文。

心形动画

心形动画由一个Star类实现,该类有以下属性和方法:

  • x:心形的横坐标。

  • y:心形的纵坐标。

  • text:显示的文本(心形符号)。

  • color:心形的颜色。

  • getColor():随机设置心形颜色。

  • init():初始化心形的颜色。

  • draw():在画布上绘制心形。

在页面加载时,会创建大量的Star对象,并调用其init()draw()方法进行绘制。playStars()函数使心形闪烁,通过不断调用getColor()draw()方法,并使用setTimeout定时器循环实现。

流星动画

流星动画由一个MeteorRain类实现,该类有以下属性和方法:

  • xy:流星的起始位置。

  • length:流星的长度。

  • angle:流星的倾斜角度。

  • widthheight:流星的宽高。

  • speed:流星的速度。

  • offset_xoffset_y:流星的横向和纵向位移量。

  • alpha:流星的透明度。

  • color1color2:流星的颜色(使用渐变效果)。

  • init():初始化流星的起始位置、速度和颜色。

  • getRandomColor():随机生成流星的颜色。

  • countPos():计算流星的位置。

  • getPos():生成流星的起始位置。

  • draw():在画布上绘制流星。

  • move():更新流星的位置。

在页面加载时,会创建一定数量的MeteorRain对象,并调用其init()draw()方法进行绘制。playRains()函数通过不断调用move()方法来更新流星的位置,并使用setTimeout定时器循环实现。

爱心动画

粒子爱心效果由多个类实现,包括PointParticleParticlePool。

  • Point类:表示二维平面上的一个点,提供克隆、长度和归一化方法。

  • Particle类:表示一个粒子,具有位置、速度、加速度和年龄等属性,提供初始化、更新和绘制方法。

  • ParticlePool类:管理粒子的池,提供添加、更新和绘制粒子的方法。

粒子爱心效果通过pointOnHeart(t)函数生成心形路径上的点。粒子池管理和更新这些粒子,并在每一帧动画中绘制它们。

在初始化时,会创建一个心形路径的粒子图像,并通过requestAnimationFrame实现动画的逐帧渲染。render()函数是动画的核心,负责更新时间、清空画布、创建新粒子、更新和绘制粒子。onResize()函数确保画布在窗口大小改变时自适应调整。

总结

整个代码通过HTML、CSS和JavaScript实现了一个视觉效果丰富的网页动画,展示了闪烁的心形和流星,以及中心的粒子爱心效果。通过使用canvas和逐帧动画技术,代码创造了一个生动的视觉体验。

推荐系列

序号目录
1HTML满屏跳动的爱心(可写字)
2HTML五彩缤纷的爱心
3HTML满屏漂浮爱心
4HTML情人节快乐
5HTML蓝色爱心射线
6HTML跳动的爱心(简易版)
7HTML粒子爱心
8HTML蓝色动态爱心
9HTML跳动的爱心(双心版)
10HTML橙色动态粒子爱心
11HTML旋转爱心
12HTML爱情树
13HTML3D相册
14HTML旋转相册
15HTML基础烟花秀
16HTML炫酷烟花秀
17HTML粉色烟花秀
18HTML新春烟花
19HTML龙年大吉
20HTML圣诞树
21HTML大雪纷飞
22HTML想见你
23HTML元素周期表
24HTML飞舞的花瓣
25HTML星空特效
26HTML黑客帝国字母雨
27HTML哆啦A梦
28HTML流星雨
29HTML沙漏爱心
30HTML爱心字母雨
31HTML爱心流星雨

写在后面

我是一只有趣的兔子,感谢你的喜欢!


http://www.kler.cn/news/284224.html

相关文章:

  • 6种有效的时间序列数据特征工程技术(使用Python)
  • 产品经理角度分析:朋友圈点赞与评论仅共同好友可见
  • 华为 2024 届校园招聘-硬件通⽤/单板开发——第一套(部分题目分享,完整版带答案,共十套)
  • 【机器学习-监督学习】神经网络与多层感知机
  • 影视会员充值API接口如何开发?
  • 从插件plugin和钩子hook 到“智能化自动化”架构
  • ubuntu环境下部署LNMP集成环境超详细图文教程
  • Linux的常见指令
  • WireShark网络分析~环境搭建
  • IDEA2023版本创建SSM项目框架
  • 自动化代码报错:ElementClickInterceptedException 解决方案
  • 计算机网络速成(三)
  • SQLi-LABS通关攻略【51-55关】
  • 使用SparkGraphX进行图计算时的编码问题
  • 用Python在PDF文档中创建动作
  • OpenCV+Python识别机读卡
  • python从列表元素中查找最小的元组坐标
  • Vue——认识day05_监视属性
  • 安装jmeter的梯度压测线程组(Custom Thread Groups)的插件
  • 10款必备的电脑监控软件推荐,实用又方便!顶尖产品一网打尽!2024纯干货
  • 【JAVA入门】Day28 - 数据结构
  • JavaScript 中,不同的赋值方式适用场景
  • OpenAI“草莓项目”最快今年秋季发布!苹果将于9月10号推出首款AI iPhone|AI日报
  • C/C++ 编译过程概述
  • 睡岗检测数据集(工作 课堂等) 3100张 增强 睡岗趴睡 带标注 voc yolo
  • Springboot3整合ELK实现日志可视化
  • Spring Boot中Tomcat、Jetty、Undertow哪个嵌入式服务器最好?
  • 线性代数基础
  • 实训day29(8.15)
  • 探索未知,悦享惊喜 —— 您的专属盲盒小程序,即将开启奇妙之旅