利用python和前端三件套来一场线上烟花秀

目录

python烟花秀

效果展示:

全部代码如下:

前端三件套(JS、CSS、HTML)的烟花秀

HTML部分:定义网页内容

CSS部分:描述网页布局

JS部分:控制网页行为

End


✨✨✨✨✨✨✨

元旦节就要来了,线下没有烟花看,线上不得整点烟花酷炫一下嘛!!

啥?过啥圣诞节?过啥洋节,咱们过元旦节好吧!

✨✨✨✨✨✨✨

python烟花秀

效果展示:

image-20211230214422492

image-20211230214448245

    

在这里,我们设计一个对象,表示烟花事件中的每个粒子。每个粒子都会有一些重要的属性,支配了它的外观和移动状况:大小,颜色,位置,速度等等。

'''
particles 类
​
粒子在空中随机生成随机,变成一个圈、下坠、消失
​
属性:
    - id: 粒子的id
    - x, y: 粒子的坐标
    - vx, vy: 在坐标的变化速度
    - total: 总数
    - age: 粒子存在的时长
    - color: 颜色
    - cv: 画布
    - lifespan: 最高存在时长
​
'''
class part:
​
    def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx = 0., vy = 0., size=2., color = 'red', lifespan = 2, **kwargs):
        self.id = idx
        self.x = x
        self.y = y
        self.initial_speed = explosion_speed
        self.vx = vx
        self.vy = vy
        self.total = total
        self.age = 0self.color = color
        self.cv = cv
        self.cid = self.cv.create_oval(
            x - size, y - size, x + size,
            y + size, fill=self.color)
        self.lifespan = lifespan

除了属性,这个对象肯定还要有其所固定的方法,这里我们定义了其三个方法,分别是“膨胀”“坠落”和“消失”,这些函数分别如示范:

def update(self, dt):
    # 粒子膨胀if self.alive() and self.expand():
        move_x = cos(radians(self.id*360/self.total))*self.initial_speed
        move_y = sin(radians(self.id*360/self.total))*self.initial_speed
        self.vx = move_x/(float(dt)*1000)
        self.vy = move_y/(float(dt)*1000)
        self.cv.move(self.cid, move_x, move_y)
​
    # 以自由落体坠落
    elif self.alive():
        move_x = cos(radians(self.id*360/self.total))
        # we technically don't need to update x, y because move will do the job
        self.cv.move(self.cid, self.vx + move_x, self.vy+GRAVITY*dt)
        self.vy += GRAVITY*dt
​
    # 如果粒子的生命周期已过,就将其移除
    elif self.cid is not None:
        cv.delete(self.cid)
        self.cid = None

除此之外,为达到烟花更好的效果,我们这里也定义了烟花种每一个粒子的绽放时间和坠落时间,这里可以自己多尝试几组参数以达到·最好的效果:

# 定义膨胀效果的时间帧
def expand (self):
    return self.age <= 1.2
​
# 检查粒子是否仍在生命周期内
def alive(self):
    return self.age <= self.lifespan
利用Tkinter快速创建GUI应用程序:

import tkinter as tk
root = tk.Tk()

对于每个小烟花里边的粒子的定义:创建一列列表,每个子列表是一个烟花,其包含一列粒子。每个列表中的例子有相同的x,y坐标、大小、颜色、初始速度。

numb_explode = randint(6,10)
# 为所有模拟烟花绽放的全部粒子创建一列列表
for point in range(numb_explode):
    objects = []
    x_cordi = randint(50,550)
    y_cordi = randint(50, 150)       
    size = uniform (0.5,3)
    color = choice(colors)
    explosion_speed = uniform(0.2, 1)
    total_particles = randint(10,50)
    for i in range(1,total_particles):
        r = part(cv, idx = i, total = total_particles, explosion_speed = explosion_speed, x = x_cordi, y = y_cordi, 
        color=color, size = size, lifespan = uniform(0.6,1.75))
        objects.append(r)
explode_points.append(objects)

定义每个粒子定期更新粒子的属性,这里我们设置让粒子每0.01秒更新它们的状态,在1.8秒之后停止更新(这意味着每个粒子的存在时间为1.6秒,其中1.2秒为“绽放”状态,0.4秒为“坠落”状态,0.2秒处于Tkinter将其完全移除前的边缘状态)。

total_time = .0
# 在1.8秒时间帧内保持更新
while total_time < 1.8:
    sleep(0.01)
    tnew = time()
    t, dt = tnew, tnew - t
    for point in explode_points:
        for part in point:
            part.update(dt)
    cv.update()
    total_time += dt

值得注意的是,为了增加视觉上的效果,我们可以增加一个美丽的背景图放在当前目录:

    
image = Image.open("./image1.jpg")

全部代码如下:

import tkinter as tk
from PIL import Image, ImageTk
from time import time, sleep
from random import choice, uniform, randint
from math import sin, cos, radians
​
# 模拟重力
GRAVITY = 0.05
# 颜色选项(随机或者按顺序)
colors = ['red', 'blue', 'yellow', 'green', 'orange', 'purple', 'seagreen', 'indigo', 'cornflowerblue']
​
'''
particles 类
​
粒子在空中随机生成随机,变成一个圈、下坠、消失
​
属性:
    - id: 粒子的id
    - x, y: 粒子的坐标
    - vx, vy: 在坐标的变化速度
    - total: 总数
    - age: 粒子存在的时长
    - color: 颜色
    - cv: 画布
    - lifespan: 最高存在时长
​
'''
class Particle:
​
    def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx=0., vy=0., size=2., color='red', lifespan=2,
                 **kwargs):
        self.id = idx
        self.x = x
        self.y = y
        self.initial_speed = explosion_speed
        self.vx = vx
        self.vy = vy
        self.total = total
        self.age = 0
        self.color = color
        self.cv = cv
        self.cid = self.cv.create_oval(
            x - size, y - size, x + size,
            y + size, fill=self.color)
        self.lifespan = lifespan
​
    def update(self, dt):
        self.age += dt
​
        # 粒子范围扩大
        if self.alive() and self.expand():
            move_x = cos(radians(self.id * 360 / self.total)) * self.initial_speed
            move_y = sin(radians(self.id * 360 / self.total)) * self.initial_speed
            self.cv.move(self.cid, move_x, move_y)
            self.vx = move_x / (float(dt) * 1000)
​
        # 以自由落体坠落
        elif self.alive():
            move_x = cos(radians(self.id * 360 / self.total))
            # we technically don't need to update x, y because move will do the job
            self.cv.move(self.cid, self.vx + move_x, self.vy + GRAVITY * dt)
            self.vy += GRAVITY * dt
​
        # 移除超过最高时长的粒子
        elif self.cid is not None:
            cv.delete(self.cid)
            self.cid = None
​
    # 扩大的时间
    def expand (self):
        return self.age <= 1.2
​
    # 粒子是否在最高存在时长内
    def alive(self):
        return self.age <= self.lifespan
​
'''
循环调用保持不停
'''
def simulate(cv):
    t = time()
    explode_points = []
    wait_time = randint(10, 100)
    numb_explode = randint(6, 10)
    # 创建一个所有粒子同时扩大的二维列表
    for point in range(numb_explode):
        objects = []
        x_cordi = randint(50, 500)
        y_cordi = randint(50, 250)
        speed = uniform(0.5, 1.5)
        size = uniform(0.5, 2)
        color = choice(colors)
        explosion_speed = uniform(0.2, 1)
        total_particles = randint(10, 100)
        for i in range(1, total_particles):
            r = Particle(cv, idx=i, total=total_particles, explosion_speed=explosion_speed, x=x_cordi, y=y_cordi,
                         vx=speed, vy=speed, color=color, size=size, lifespan=uniform(0.6, 1.75))
            objects.append(r)
        explode_points.append(objects)
​
    total_time = .0
    # 1.8s内一直扩大
    while total_time < 1.8:
        sleep(0.01)
        tnew = time()
        t, dt = tnew, tnew - t
        for point in explode_points:
            for item in point:
                item.update(dt)
        cv.update()
        total_time += dt
    # 循环调用
    root.after(wait_time, simulate, cv)
​
​
def close(*ignore):
    """退出程序、关闭窗口"""
    global root
    root.quit()
​
​
if __name__ == '__main__':
    root = tk.Tk()
    cv = tk.Canvas(root, height=600, width=800)
    # 选一个好看的背景会让效果更惊艳!
    image = Image.open("./image1.jpg")
    photo = ImageTk.PhotoImage(image)
​
    cv.create_image(0, 0, image=photo, anchor='nw')
    cv.pack()
​
    root.protocol("WM_DELETE_WINDOW", close)
    root.after(100, simulate, cv)
    root.mainloop()

reference:https://zhuanlan.zhihu.com/p/187481893

前端三件套(JS、CSS、HTML)的烟花秀

接下来我们要做的就是在实现烟花效果的同时把前端三件套也学了!!

听着就很刺激!

👏👏👏

先展示图片效果:

image-20211230201751260

image-20211230214930637

HTML部分:定义网页内容

首先要理解HTML是干嘛的?

实现网页文字、图片、视频、音频、链接、表格等,并以静态的方式呈现在网页上。

代码:

<div id="gui"></div>        
<div id="canvas-container">
  <div id="mountains2"></div>
  <div id="mountains1"></div>
  <div id="skyline"></div>
</div>

CSS部分:描述网页布局

CSS 是层叠样式表单,是用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言

其主要作用:就是用来调整内容的样式的!

语法格式如下:

image-20211230220114693

实例:

image-20211230220155335

image-20211230220415279

一般情况下,将CSS样式写成一个单独的 css 文件, 再通过 link 标签引入即可复用。

image-20211230220538012

扯哪里去了?

咱们是来聊烟花的🤣

上代码:

html, body {
    margin: 0;  
    padding: 0;
}
​
body {
    background: #171717;
    color: #999;
    font: 100%/18px helvetica, arial, sans-serif;
}
​
a {
    color: #2fa1d6;
    font-weight: bold;
    text-decoration: none;
}
​
a:hover {
    color: #fff;    
}
​
#canvas-container {
    background: #000 url(https://gitee.com/aaalds/aaalds_note/raw/master/image.jpg);
  height: 400px;
    left: 50%;
    margin: -200px 0 0 -300px;
    position: absolute;
    top: 50%;
  width: 600px;
    z-index: 2;
}
        
canvas {
    cursor: crosshair;
    display: block;
    position: relative;
    z-index: 3;
}
​
canvas:active {
    cursor: crosshair;
}
​
#skyline {
    background: url(https://jackrugile.com/lab/fireworks-v2/images/skyline.png) repeat-x 50% 0;
    bottom: 0;
    height: 135px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1; 
}
​
#mountains1 {
    background: url(https://jackrugile.com/lab/fireworks-v2/images/mountains1.png) repeat-x 40% 0;
    bottom: 0;
    height: 200px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1; 
}
​
#mountains2 {
    background: url(https://jackrugile.com/lab/fireworks-v2/images/mountains2.png) repeat-x 30% 0;
    bottom: 0;
    height: 250px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1; 
}
​
#gui {
    right: 0;
    position: fixed;
    top: 0;
    z-index: 3;
}

JS部分:控制网页行为

Javascript 语言(客户端脚本语言)诞生主要是完成页面的数据验证。 因此它运行在客户端, 需要运行浏览器来解析执行 JavaScript 代码。

术语一点说,JS是一种页面脚本,通过执行程序脚本片段,我们可以对页面及页面上的元素进行操作,实现特定的功能与效果。 有一些东西,我们用高级编程语言是实现不了的,而用JS,可能几行代码就可搞定,比如,显示当前系统时间等。

更清楚的解释可以这样说:

JavaScript可以被认为是常见的是浏览器程序。

我们都知道,浏览一个网页,有两个很主要的“电脑”在共同运行,一台是远程的,为你提供网页数据的“服务器”,一台是你正在使用的客户端电脑,你在访问 一个网页的时候,服务器会根据URL,我们一般说成是网址,来判断你访问的哪一个网页。然后服务器会将这个网页传送到你的电脑上。

而你的电脑上查看网页的应用程序叫做“浏览器”,浏览器可以对网页进行“解释”,其中包括HTML和CSS的解析,以及JavaScript的运行。

JavaScript程序本身是从服务器传给你的,然后浏览器会将它当做程序来运行。

这样,你的浏览器在执行JavaScript的时候,可以实现以下的功能:

  1. 浏览器与用户之间进行操作交互,比如按个按钮、反馈个信息什么的;

  2. 网页上面的动画,比如图片的轮播;

  3. 浏览器与服务器进行数据通讯,比如现在最流行的Ajax异步传输;

  4. 浏览器在你的电脑上进行数据的判断、计算等等;

以上是JavaScript在浏览器上的主要功能体现;

当然,还有其它的地方会使用到JavaScript,一些内置了JavaScript的应用程序,也可以用JavaScript来做点它能做到的事情,这个就看要用它来做什么了,功能很多。

image-20211230220747837

各种事件介绍

  • 加载完成事件

  • 单击事件

  • 失去焦点事件

  • 内容发生改变事件

  • 表单提交事件

事件对应函数

DOM模型

DOM 全称是 Document Object Model 文档对象模型 大白话, 就是把文档中的标签, 属性, 文本, 转换成为对象来管理。

image-20211230221803268

Document 对象的理解:

  • 第一点: Document 它管理了所有的 HTML 文档内容。

  • 第二点: document 它是一种树结构的文档。 有层级关系。

  • 第三点: 它让我们把所有的标签 都 对象化

  • 第四点: 我们可以通过 document 访问所有的标签对象。

Document 对象还有各种方法

  • 通过标签的 id 属性查找标签 dom 对象, elementId 是标签的 id 属性值

  • 通过标签的 name 属性查找标签 dom 对象, elementName 标签的 name 属性值

  • 通过标签名查找标签 dom 对象。 tagname 是标签名

  • 通过给定的标签名, 创建一个标签对象

又扯远了!

上烟花代码:

var Fireworks = function(){
    /*=============================================================================*/   
    /* Utility
    /*=============================================================================*/
    var self = this;
    var rand = function(rMi, rMa){return ~~((Math.random()*(rMa-rMi+1))+rMi);}
    window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}();
    
    /*=============================================================================*/   
    /* Initialize
    /*=============================================================================*/
    self.init = function(){ 
    self.dt = 0;
        self.oldTime = Date.now();
        self.canvas = document.createElement('canvas');             
        self.canvasContainer = $('#canvas-container');
        
        var canvasContainerDisabled = document.getElementById('canvas-container');
        self.canvas.onselectstart = function() {
            return false;
        };
        
        self.canvas.width = self.cw = 600;
        self.canvas.height = self.ch = 400; 
        
        self.particles = [];    
        self.partCount = 30;
        self.fireworks = [];    
        self.mx = self.cw/2;
        self.my = self.ch/2;
        self.currentHue = 170;
        self.partSpeed = 5;
        self.partSpeedVariance = 10;
        self.partWind = 50;
        self.partFriction = 5;
        self.partGravity = 1;
        self.hueMin = 150;
        self.hueMax = 200;
        self.fworkSpeed = 2;
        self.fworkAccel = 4;
        self.hueVariance = 30;
        self.flickerDensity = 20;
        self.showShockwave = false;
        self.showTarget = true;
        self.clearAlpha = 25;
​
        self.canvasContainer.append(self.canvas);
        self.ctx = self.canvas.getContext('2d');
        self.ctx.lineCap = 'round';
        self.ctx.lineJoin = 'round';
        self.lineWidth = 1;
        self.bindEvents();          
        self.canvasLoop();
        
        self.canvas.onselectstart = function() {
            return false;
        };
    
        
    };      
    
    /*=============================================================================*/   
    /* Particle Constructor
    /*=============================================================================*/
    var Particle = function(x, y, hue){
        this.x = x;
        this.y = y;
        this.coordLast = [
            {x: x, y: y},
            {x: x, y: y},
            {x: x, y: y}
        ];
        this.angle = rand(0, 360);
        this.speed = rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance));
        this.friction = 1 - self.partFriction/100;
        this.gravity = self.partGravity/2;
        this.hue = rand(hue-self.hueVariance, hue+self.hueVariance);
        this.brightness = rand(50, 80);
        this.alpha = rand(40,100)/100;
        this.decay = rand(10, 50)/1000;
        this.wind = (rand(0, self.partWind) - (self.partWind/2))/25;
        this.lineWidth = self.lineWidth;
    };
    
    Particle.prototype.update = function(index){
        var radians = this.angle * Math.PI / 180;
        var vx = Math.cos(radians) * this.speed;
        var vy = Math.sin(radians) * this.speed + this.gravity;
        this.speed *= this.friction;
                        
        this.coordLast[2].x = this.coordLast[1].x;
        this.coordLast[2].y = this.coordLast[1].y;
        this.coordLast[1].x = this.coordLast[0].x;
        this.coordLast[1].y = this.coordLast[0].y;
        this.coordLast[0].x = this.x;
        this.coordLast[0].y = this.y;
        
        this.x += vx * self.dt;
        this.y += vy * self.dt;
        
        this.angle += this.wind;                
        this.alpha -= this.decay;
        
        if(this.alpha < .05){                   
            self.particles.splice(index, 1);    
        }           
    };
    
    Particle.prototype.draw = function(){
        var coordRand = (rand(1,3)-1);
        self.ctx.beginPath();                               
        self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
        self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
        self.ctx.closePath();               
        self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
        self.ctx.stroke();              
        
        if(self.flickerDensity > 0){
            var inverseDensity = 50 - self.flickerDensity;                  
            if(rand(0, inverseDensity) === inverseDensity){
                self.ctx.beginPath();
                self.ctx.arc(Math.round(this.x), Math.round(this.y), rand(this.lineWidth,this.lineWidth+3)/2, 0, Math.PI*2, false)
                self.ctx.closePath();
                var randAlpha = rand(50,100)/100;
                self.ctx.fillStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+randAlpha+')';
                self.ctx.fill();
            }   
        }
    };
    
    /*=============================================================================*/   
    /* Create Particles
    /*=============================================================================*/
    self.createParticles = function(x,y, hue){
        var countdown = self.partCount;
        while(countdown--){                     
            self.particles.push(new Particle(x, y, hue));
        }
    };
    
    /*=============================================================================*/   
    /* Update Particles
    /*=============================================================================*/       
    self.updateParticles = function(){
        var i = self.particles.length;
        while(i--){
            var p = self.particles[i];
            p.update(i);
        };
    };
    
    /*=============================================================================*/   
    /* Draw Particles
    /*=============================================================================*/
    self.drawParticles = function(){
        var i = self.particles.length;
        while(i--){
            var p = self.particles[i];              
            p.draw();               
        };
    };
    
    /*=============================================================================*/   
    /* Firework Constructor
    /*=============================================================================*/
    var Firework = function(startX, startY, targetX, targetY){
        this.x = startX;
        this.y = startY;
        this.startX = startX;
        this.startY = startY;
        this.hitX = false;
        this.hitY = false;
        this.coordLast = [
            {x: startX, y: startY},
            {x: startX, y: startY},
            {x: startX, y: startY}
        ];
        this.targetX = targetX;
        this.targetY = targetY;
        this.speed = self.fworkSpeed;
        this.angle = Math.atan2(targetY - startY, targetX - startX);
        this.shockwaveAngle = Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180));
        this.acceleration = self.fworkAccel/100;
        this.hue = self.currentHue;
        this.brightness = rand(50, 80);
        this.alpha = rand(50,100)/100;
        this.lineWidth = self.lineWidth;
        this.targetRadius = 1;
    };
    
    Firework.prototype.update = function(index){
        self.ctx.lineWidth = this.lineWidth;
            
        vx = Math.cos(this.angle) * this.speed,
        vy = Math.sin(this.angle) * this.speed;
        this.speed *= 1 + this.acceleration;                
        this.coordLast[2].x = this.coordLast[1].x;
        this.coordLast[2].y = this.coordLast[1].y;
        this.coordLast[1].x = this.coordLast[0].x;
        this.coordLast[1].y = this.coordLast[0].y;
        this.coordLast[0].x = this.x;
        this.coordLast[0].y = this.y;
        
        if(self.showTarget){
            if(this.targetRadius < 8){
                this.targetRadius += .25 * self.dt;
            } else {
                this.targetRadius = 1 * self.dt;    
            }
        }
        
        if(this.startX >= this.targetX){
            if(this.x + vx <= this.targetX){
                this.x = this.targetX;
                this.hitX = true;
            } else {
                this.x += vx * self.dt;
            }
        } else {
            if(this.x + vx >= this.targetX){
                this.x = this.targetX;
                this.hitX = true;
            } else {
                this.x += vx * self.dt;
            }
        }
        
        if(this.startY >= this.targetY){
            if(this.y + vy <= this.targetY){
                this.y = this.targetY;
                this.hitY = true;
            } else {
                this.y += vy * self.dt;
            }
        } else {
            if(this.y + vy >= this.targetY){
                this.y = this.targetY;
                this.hitY = true;
            } else {
                this.y += vy * self.dt;
            }
        }               
        
        if(this.hitX && this.hitY){
            var randExplosion = rand(0, 9);
            self.createParticles(this.targetX, this.targetY, this.hue);
            self.fireworks.splice(index, 1);                    
        }
    };
    
    Firework.prototype.draw = function(){
        self.ctx.lineWidth = this.lineWidth;
            
        var coordRand = (rand(1,3)-1);                  
        self.ctx.beginPath();                           
        self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
        self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
        self.ctx.closePath();
        self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
        self.ctx.stroke();  
        
        if(self.showTarget){
            self.ctx.save();
            self.ctx.beginPath();
            self.ctx.arc(Math.round(this.targetX), Math.round(this.targetY), this.targetRadius, 0, Math.PI*2, false)
            self.ctx.closePath();
            self.ctx.lineWidth = 1;
            self.ctx.stroke();
            self.ctx.restore();
        }
            
        if(self.showShockwave){
            self.ctx.save();
            self.ctx.translate(Math.round(this.x), Math.round(this.y));
            self.ctx.rotate(this.shockwaveAngle);
            self.ctx.beginPath();
            self.ctx.arc(0, 0, 1*(this.speed/5), 0, Math.PI, true);
            self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+rand(25, 60)/100+')';
            self.ctx.lineWidth = this.lineWidth;
            self.ctx.stroke();
            self.ctx.restore();
        }                                
    };
    
    /*=============================================================================*/   
    /* Create Fireworks
    /*=============================================================================*/
    self.createFireworks = function(startX, startY, targetX, targetY){          
        self.fireworks.push(new Firework(startX, startY, targetX, targetY));
    };
    
    /*=============================================================================*/   
    /* Update Fireworks
    /*=============================================================================*/       
    self.updateFireworks = function(){
        var i = self.fireworks.length;
        while(i--){
            var f = self.fireworks[i];
            f.update(i);
        };
    };
    
    /*=============================================================================*/   
    /* Draw Fireworks
    /*=============================================================================*/
    self.drawFireworks = function(){
        var i = self.fireworks.length;          
        while(i--){
            var f = self.fireworks[i];      
            f.draw();
        };
    };
    
    /*=============================================================================*/   
    /* Events
    /*=============================================================================*/
    self.bindEvents = function(){
        $(window).on('resize', function(){          
            clearTimeout(self.timeout);
            self.timeout = setTimeout(function() {
                self.ctx.lineCap = 'round';
                self.ctx.lineJoin = 'round';
            }, 100);
        });
        
        $(self.canvas).on('mousedown', function(e){
            var randLaunch = rand(0, 5);
            self.mx = e.pageX - self.canvasContainer.offset().left;
            self.my = e.pageY - self.canvasContainer.offset().top;
            self.currentHue = rand(self.hueMin, self.hueMax);
            self.createFireworks(self.cw/2, self.ch, self.mx, self.my); 
            
            $(self.canvas).on('mousemove.fireworks', function(e){
                var randLaunch = rand(0, 5);
                self.mx = e.pageX - self.canvasContainer.offset().left;
                self.my = e.pageY - self.canvasContainer.offset().top;
                self.currentHue = rand(self.hueMin, self.hueMax);
                self.createFireworks(self.cw/2, self.ch, self.mx, self.my);                                 
            }); 
            
        });
        
        $(self.canvas).on('mouseup', function(e){
            $(self.canvas).off('mousemove.fireworks');                                  
        });
                    
    }
    
    /*=============================================================================*/   
    /* Clear Canvas
    /*=============================================================================*/
    self.clear = function(){
        self.particles = [];
        self.fireworks = [];
        self.ctx.clearRect(0, 0, self.cw, self.ch);
    };
  
  /*=============================================================================*/ 
    /* Delta
    /*=============================================================================*/
  self.updateDelta = function(){
        var newTime = Date.now();
        self.dt = (newTime - self.oldTime)/16;
        self.dt = (self.dt > 5) ? 5 : self.dt;
        self.oldTime = newTime; 
    }
    
    /*=============================================================================*/   
    /* Main Loop
    /*=============================================================================*/
    self.canvasLoop = function(){
        requestAnimFrame(self.canvasLoop, self.canvas);
    self.updateDelta();
        self.ctx.globalCompositeOperation = 'destination-out';
        self.ctx.fillStyle = 'rgba(0,0,0,'+self.clearAlpha/100+')';
        self.ctx.fillRect(0,0,self.cw,self.ch);
        self.ctx.globalCompositeOperation = 'lighter';
        self.updateFireworks();
        self.updateParticles();
        self.drawFireworks();           
        self.drawParticles();           
    };
    
    self.init();
  
  var initialLaunchCount = 10;
  while(initialLaunchCount--){
    setTimeout(function(){
        self.fireworks.push(new Firework(self.cw/2, self.ch, rand(50, self.cw-50), rand(50, self.ch/2)-50));
    }, initialLaunchCount*200);
  }
    
}
​
/*=============================================================================*/   
/* GUI
/*=============================================================================*/   
var guiPresets = {
              "preset": "Default",
              "remembered": {
                "Default": {
                  "0": {
                    "fworkSpeed": 2,
                    "fworkAccel": 4,
                    "showShockwave": false,
                    "showTarget": true,
                    "partCount": 30,
                    "partSpeed": 5,
                    "partSpeedVariance": 10,
                    "partWind": 50,
                    "partFriction": 5,
                    "partGravity": 1,
                    "flickerDensity": 20,
                    "hueMin": 150,
                    "hueMax": 200,
                    "hueVariance": 30,
                    "lineWidth": 1,
                    "clearAlpha": 25
                  }
                },
                "Anti Gravity": {
                  "0": {
                    "fworkSpeed": 4,
                    "fworkAccel": 10,
                    "showShockwave": true,
                    "showTarget": false,
                    "partCount": 150,
                    "partSpeed": 5,
                    "partSpeedVariance": 10,
                    "partWind": 10,
                    "partFriction": 10,
                    "partGravity": -10,
                    "flickerDensity": 30,
                    "hueMin": 0,
                    "hueMax": 360,
                    "hueVariance": 30,
                    "lineWidth": 1,
                    "clearAlpha": 50
                  }
                },
                "Battle Field": {
                  "0": {
                    "fworkSpeed": 10,
                    "fworkAccel": 20,
                    "showShockwave": true,
                    "showTarget": true,
                    "partCount": 200,
                    "partSpeed": 30,
                    "partSpeedVariance": 5,
                    "partWind": 0,
                    "partFriction": 5,
                    "partGravity": 0,
                    "flickerDensity": 0,
                    "hueMin": 20,
                    "hueMax": 30,
                    "hueVariance": 10,
                    "lineWidth": 1,
                    "clearAlpha": 40
                  }
                },
                "Mega Blast": {
                  "0": {
                    "fworkSpeed": 3,
                    "fworkAccel": 3,
                    "showShockwave": true,
                    "showTarget": true,
                    "partCount": 500,
                    "partSpeed": 50,
                    "partSpeedVariance": 5,
                    "partWind": 0,
                    "partFriction": 0,
                    "partGravity": 0,
                    "flickerDensity": 0,
                    "hueMin": 0,
                    "hueMax": 360,
                    "hueVariance": 30,
                    "lineWidth": 20,
                    "clearAlpha": 20
                  }
                },
                "Nimble": {
                  "0": {
                    "fworkSpeed": 10,
                    "fworkAccel": 50,
                    "showShockwave": false,
                    "showTarget": false,
                    "partCount": 120,
                    "partSpeed": 10,
                    "partSpeedVariance": 10,
                    "partWind": 100,
                    "partFriction": 50,
                    "partGravity": 0,
                    "flickerDensity": 20,
                    "hueMin": 0,
                    "hueMax": 360,
                    "hueVariance": 30,
                    "lineWidth": 1,
                    "clearAlpha": 80
                  }
                },
                "Slow Launch": {
                  "0": {
                    "fworkSpeed": 2,
                    "fworkAccel": 2,
                    "showShockwave": false,
                    "showTarget": false,
                    "partCount": 200,
                    "partSpeed": 10,
                    "partSpeedVariance": 0,
                    "partWind": 100,
                    "partFriction": 0,
                    "partGravity": 2,
                    "flickerDensity": 50,
                    "hueMin": 0,
                    "hueMax": 360,
                    "hueVariance": 20,
                    "lineWidth": 4,
                    "clearAlpha": 10
                  }
                },
                "Perma Trail": {
                  "0": {
                    "fworkSpeed": 4,
                    "fworkAccel": 10,
                    "showShockwave": false,
                    "showTarget": false,
                    "partCount": 150,
                    "partSpeed": 10,
                    "partSpeedVariance": 10,
                    "partWind": 100,
                    "partFriction": 3,
                    "partGravity": 0,
                    "flickerDensity": 0,
                    "hueMin": 0,
                    "hueMax": 360,
                    "hueVariance": 20,
                    "lineWidth": 1,
                    "clearAlpha": 0
                  }
                }
              },
              "closed": true,
              "folders": {
                "Fireworks": {
                  "preset": "Default",
                  "closed": false,
                  "folders": {}
                },
                "Particles": {
                  "preset": "Default",
                  "closed": true,
                  "folders": {}
                },
                "Color": {
                  "preset": "Default",
                  "closed": true,
                  "folders": {}
                },
                "Other": {
                  "preset": "Default",
                  "closed": true,
                  "folders": {}
                }
              }
            };
​
​
var fworks = new Fireworks();
var gui = new dat.GUI({
    autoPlace: false,
    load: guiPresets,
    preset: 'Default'
});
var customContainer = document.getElementById('gui');
customContainer.appendChild(gui.domElement);
​
var guiFireworks = gui.addFolder('Fireworks');
guiFireworks.add(fworks, 'fworkSpeed').min(1).max(10).step(1);
guiFireworks.add(fworks, 'fworkAccel').min(0).max(50).step(1);
guiFireworks.add(fworks, 'showShockwave');
guiFireworks.add(fworks, 'showTarget');
​
var guiParticles = gui.addFolder('Particles');
guiParticles.add(fworks, 'partCount').min(0).max(500).step(1);  
guiParticles.add(fworks, 'partSpeed').min(1).max(100).step(1);
guiParticles.add(fworks, 'partSpeedVariance').min(0).max(50).step(1);
guiParticles.add(fworks, 'partWind').min(0).max(100).step(1);
guiParticles.add(fworks, 'partFriction').min(0).max(50).step(1);
guiParticles.add(fworks, 'partGravity').min(-20).max(20).step(1);
guiParticles.add(fworks, 'flickerDensity').min(0).max(50).step(1);
​
var guiColor = gui.addFolder('Color');
guiColor.add(fworks, 'hueMin').min(0).max(360).step(1);
guiColor.add(fworks, 'hueMax').min(0).max(360).step(1);
guiColor.add(fworks, 'hueVariance').min(0).max(180).step(1);
​
var guiOther = gui.addFolder('Other');
guiOther.add(fworks, 'lineWidth').min(1).max(20).step(1);
guiOther.add(fworks, 'clearAlpha').min(0).max(100).step(1);
guiOther.add(fworks, 'clear').name('Clear');
​
gui.remember(fworks);

对了,忘说了,为了增加页面的效果,这里我挑了几个比较好的背景图,如是下:

image

image-20211230210134111

前端三件套完整代码:

链接:百度网盘 请输入提取码 提取码:8888

End

记得点赞、评论呦!

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向521

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值