likes
comments
collection
share

有你的地方就是年——请查收你的春节烟花(零点定时跳转)

作者站长头像
站长
· 阅读数 25

“ PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

新年快乐

现在各地纷纷出台政策禁止燃放烟花爆竹,过年确实平白少了很多乐趣。虽然自己已经长大,很多小时候的热爱都已经不再喜欢,但是年底家家户户燃放的烟花,依然是对年味最初的执念。🏮🏮🏮

这种酸酸地不可言说的感情,应该就叫情怀吧。

情感总是我们心中最柔软的地方。这一年,我们依旧忙碌,依旧为生活焦头烂额。断断续续的疫情可能让你的团聚进退两难,虽然不在彼此身边,但是这份新年烟花送去的不仅仅是几秒钟的绚烂,更传递着你我的思念

综述🔦

定时烟花实现一共分为三部分

  1. 第一部分是初始化显示的一个html页面,显示自定义祝愿文字或者悄悄话,鼠标滑动轨迹生成爱心; 有你的地方就是年——请查收你的春节烟花(零点定时跳转)

  2. 第二部分是定时器功能,实现定时跳转到烟花绽放页面;

  3. 第三部分是烟花绽放页面,烟花绽放;✨

有你的地方就是年——请查收你的春节烟花(零点定时跳转)

第一部分:canvas实现爱心轨迹

要在画板上画画,第一步肯定是要有一块画板的吧

//html
<canvas></canvas> 

//js
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");

然后构思画的尺寸,选一块合适大小的画布

var ww,wh;
function onResize(){
// windows窗口的大小
  ww = canvas.width = window.innerWidth;
  wh = canvas.height = window.innerHeight;
}

准备一下作画用的颜料,红黄蓝?

ctx.strokeStyle = "red";
ctx.shadowBlur = 25;
// 色相,饱和度,亮度,透明度
ctx.shadowColor = "hsla(0, 100%, 60%,0.5)";
// https://www.w3schools.com/html/html_colors.asp 这里有关于css中关于颜色的不同定义方法

构思一下到底画一些什么,画多少合适

var Heart = function(x,y){
  this.x = x || Math.random()*ww;
  this.y = y || Math.random()*wh;
  this.size = Math.random()*2 + 1;
  // 阴影模糊度
  this.shadowBlur = Math.random() * 10;
  // 速度
  this.speedX = (Math.random()+0.2-0.6) * 8;
  this.speedY = (Math.random()+0.2-0.6) * 8;
  this.speedSize = Math.random()*0.05 + 0.01;
  this.opacity = 1;
  this.vertices = [];
  for (var i = 0; i < precision; i++) {
    var step = (i / precision - 0.5) * (Math.PI * 2);
    // 使用心型方程式绘制爱心
    var vector = {
      x : (16 * 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();
  // 重新定义画布(0,0)点的位置,之后绘制的图形都基于该点为(0,0)点进行绘制
  ctx.translate(-1000,this.y);
  // 缩放
  ctx.scale(this.size, this.size);

  ctx.beginPath();
  for (var i = 0; i < precision; i++) {
    var vector = this.vertices[i];
    ctx.lineTo(vector.x, vector.y);
  }
  ctx.globalAlpha = this.size;
  ctx.shadowBlur = Math.round((3 - this.size) * 10);
  ctx.shadowColor = "hsla(0, 100%, 60%,0.5)";
  // 设置阴影距形状的水平距离
  ctx.shadowOffsetX = this.x + 1000;
  ctx.globalCompositeOperation = "screen"
  //结束绘制
  ctx.closePath();
  //填充轮廓
  ctx.fill()
  // 上面临时地改变图像状态后, restore()可以恢复以前的值。
  // 也就是爱心消失后,再次绘制时直接使用上次保存的状态绘制爱心
  ctx.restore();
};

现在准备工作都做好了,请开始你的表演

function render(a){
  requestAnimationFrame(render);
  hearts.push(new Heart())
  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);

第二部分:定时跳转

定时跳转大概原理就是通过new date获取时间戳,将定时器时间设为未来时间和现在时间的差值,当两者时间相等时,实现跳转效果。

//页面加载便调用
window.onload=function starttime(){
        time(h1,'2022/1/29');     // 2021年春节时间
        ptimer = setTimeout(starttime,1000); // 添加计时器
}

function time(obj,futimg){
    var nowtime = new Date().getTime() + 1900000; // 现在时间转换为时间戳
    var futruetime =  new Date(futimg).getTime(); // 未来时间转换为时间戳
    
    // 1643385600000
    // console.log(nowtime,'-------',futruetime)

    var msec = futruetime-nowtime; // 毫秒 未来时间-现在时间
    // 定时跳转
    setTimeout("javascript:location.href='demo.html'", msec);

    var time = (msec/1000);  // 毫秒/1000
    var day = parseInt(time/86400); // 天  24*60*60*1000 
    var hour = parseInt(time/3600)-24*day;    // 小时 60*60 总小时数-过去的小时数=现在的小时数 
    var minute = parseInt(time%3600/60); // 分 -(day*24) 以60秒为一整份 取余 剩下秒数 秒数/60 就是分钟数
    var second = parseInt(time%60);  // 以60秒为一整份 取余 剩下秒数
    obj.innerHTML="<p2>小王新年快乐<br>I can never let you go<br></p2>"+"<span>距离2022年还有:<span><br>"+day+"天"+hour+"小时"+minute+"分"+second+"秒"+"<br>"
    return true;
}

第三部分:烟花效果

这里实现烟花效果过程中使用到了jquery,所以需要先引入

<body>
    <div class="demo">
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <script src="index.js"></script>
    <script>
        $('.demo').fireworks({
            sound: true,
            opacity: 0.8,
            width: '100%',
            height: '100%'
        });
    </script>

</body>

创建烟花效果的画布

    var canvas = document.createElement('canvas');
    canvas.id = 'fireworksField';
    canvas.width = SCREEN_WIDTH;
    canvas.height = SCREEN_HEIGHT;
    canvas.style.width  = SCREEN_WIDTH + 'px';
    canvas.style.height = SCREEN_HEIGHT + 'px';
    canvas.style.position = 'absolute';
    canvas.style.top = '0px';
    canvas.style.left = '0px';
    canvas.style.opacity = options.opacity;
    var context = canvas.getContext('2d');

定义烟花粒子基础属性

    function Particle(pos) {
        this.pos = {
            x: pos ? pos.x : 0,
            y: pos ? pos.y : 0
        };
        this.vel = {
            x: 0,
            y: 0
        };
        this.shrink = 0.97;
        this.size = 2;
 
        this.resistance = 1;
        this.gravity = 0;
 
        this.flick = false;
 
        this.alpha = 1;
        this.fade = 0;
 
        this.color = 0;
    }

定义烟花粒子下落时属性的变化

Particle.prototype.update = function() {
    // apply 
    this.vel.x *= this.resistance;
    this.vel.y *= this.resistance;

    // 根据重力下降
    this.vel.y += this.gravity;

    // 根据速度更新位置
    this.pos.x += this.vel.x;
    this.pos.y += this.vel.y;

    // 下落时变小
    this.size *= this.shrink;

    // 淡出
    this.alpha -= this.fade;
};

生成烟花粒子

Particle.prototype.render = function(c) {
    if (!this.exists()) {
        return;
    }
    c.save();
    c.globalCompositeOperation = 'lighter';
    var x = this.pos.x,
        y = this.pos.y,
        r = this.size / 2;
    var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
    gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
    gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")");
    gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");

    c.fillStyle = gradient;

    c.beginPath();
    c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
    c.closePath();
    c.fill();

    c.restore();
};

实现爆炸效果

Rocket.prototype.explode = function() {
    if (options.sound) {
      var randomNumber = function (min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
      }(0, 2);
      audio.src = sounds[randomNumber].prefix + sounds[randomNumber].data;
      audio.play();
    }

    var count = Math.random() * 10 + 80;

    for (var i = 0; i < count; i++) {
        var particle = new Particle(this.pos);
        var angle = Math.random() * Math.PI * 2;

        // emulate 3D effect by using cosine and put more particles in the middle
        var speed = Math.cos(Math.random() * Math.PI / 2) * 15;

        particle.vel.x = Math.cos(angle) * speed;
        particle.vel.y = Math.sin(angle) * speed;

        particle.size = 10;

        particle.gravity = 0.2;
        particle.resistance = 0.92;
        particle.shrink = Math.random() * 0.05 + 0.93;

        particle.flick = true;
        particle.color = this.explosionColor;

        particles.push(particle);
    }
};

源码链接,github.com/ahua-GitHub…,记得帮点亮⭐⭐和💖💖