新增第105个小实例:喜庆绚烂的新年烟花特效

This commit is contained in:
DESKTOP-BM6RJU5\wyanh 2022-01-30 17:34:26 +08:00
parent db82484f73
commit 7719c9cd0b
6 changed files with 412 additions and 1 deletions

View File

@ -108,4 +108,5 @@
101. HTML5+CSS3小实例浮雕效果的彩色loading动画
102. HTML5+CSS3+JS小实例切片式轮播图
103. HTML5+CSS3小实例纯CSS实现百叶窗图片切换效果
104. HTML5+CSS3小实例单选按钮的创意动画
104. HTML5+CSS3小实例单选按钮的创意动画
105. HTML5+CSS3+JS小实例喜庆绚烂的新年烟花特效

48
css/105.css Normal file
View File

@ -0,0 +1,48 @@
/* 引入网络字体Montserrat */
@import url("http://fonts.googleapis.com/css?family=Montserrat:200,300,400,500,600,700,800,900&display=swap");
*{
/* 初始化 */
margin: 0;
padding: 0;
}
body{
/* 100%窗口高度 */
height: 100vh;
background: url("../images/yj.jpg") no-repeat;
background-size: cover;
background-position: center;
/* 溢出隐藏 */
overflow: hidden;
/* 禁止文本被选取 */
user-select: none;
}
canvas{
/* 设置混合模式:变亮 */
mix-blend-mode: lighten;
}
.container{
/* 绝对定位 居中 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
/* 设置混合模式:颜色减淡 */
mix-blend-mode: color-dodge;
}
.year{
font-size: 30vw;
color: #aaa;
/* 字体设置为上面引入的字体 */
font-family: Montserrat;
font-weight: 700;
/* 字间距 */
letter-spacing: 15px;
}
.greetings{
color: #eee;
font-size: 3.5vw;
font-weight: bold;
text-align: center;
letter-spacing: 10px;
}

23
html/105.html Normal file
View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>新年到了,怎能少了烟花表演!祝大家新年快乐!!</title>
<link rel="stylesheet" href="../css/105.css">
</head>
<body>
<div class="container">
<div class="year">2022</div>
<div class="greetings">新年快乐!</div>
</div>
<!-- 接下来重头戏,烟花来了 -->
<!-- 这两个js文件我提前准备好了太多了就不带着大家手敲了大家可以找我拿 -->
<script src="../js/105_vector.js"></script>
<script src="../js/105_fireworks.js"></script>
</body>
</html>

BIN
images/yj.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

188
js/105_fireworks.js Normal file
View File

@ -0,0 +1,188 @@
const canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight,
HalfPI = Math.PI / 2,
gravity = vector.create(0, 0.35)
let objects = [];
let startFireworks = true;
document.body.appendChild(canvas);
function random255() {
return Math.floor(Math.random() * 100 + 155);
}
function randomColor() {
let r = random255(),
g = random255(),
b = random255();
return `rgb(${r}, ${g}, ${b})`;
}
class PhysicsBody {
constructor() {
objects.push(this);
}
PhysicsUpdate() {
this.lastPosition = this.position.duplicate();
this.position.addTo(this.velocity);
this.velocity.addTo(gravity);
}
deleteObject() {
objects[objects.indexOf(this)] = undefined;
}}
class firework extends PhysicsBody {
constructor() {
super();
this.position = vector.create(Math.random() * width, height);
let Velocity = vector.create(0, 0);
Velocity.setLength(Math.random() * 10 + 15);
Velocity.setAngle(Math.PI * 1.35 + Math.random() * Math.PI * 0.30);
this.velocity = Velocity;
this.trail = Math.floor(Math.random() * 4) != 1;
this.trailColor = this.trail ? randomColor() : undefined;
this.trailWidth = 2;
this.TimeCreated = new Date().getTime();
this.TimeExpired = this.TimeCreated + (Math.random() * 5 + 7) * 100;
this.BlastParticleCount = Math.floor(Math.random() * 50) + 25;
this.funky = Math.floor(Math.random() * 5) == 1;
this.exposionColor = randomColor();
}
draw() {
context.strokeStyle = this.trailColor;
context.lineWidth = this.trailWidth;
let p = this.position,
lp = this.lastPosition;
context.beginPath();
context.moveTo(lp.getX(), lp.getY());
context.lineTo(p.getX(), p.getY());
context.stroke();
}
funkyfire() {
var funky = this.funky;
for (var i = 0; i < Math.floor(Math.random() * 10); i++) {
new BlastParticle({ firework: this, funky });
}
}
explode() {
var funky = this.funky;
for (var i = 0; i < this.BlastParticleCount; i++) {
new BlastParticle({ firework: this, funky });
}
this.deleteObject();
}
checkExpire() {
let now = new Date().getTime();
if (now >= this.TimeExpired) this.explode();
}
render() {
if (this.trail) this.draw();
if (this.funky) this.funkyfire();
this.checkExpire();
}}
class BlastParticle extends PhysicsBody {
constructor({ firework, funky }) {
super();
this.position = firework.position.duplicate();
let Velocity = vector.create(0, 0);
if (!this.funky) {
Velocity.setLength(Math.random() * 6 + 2);
Velocity.setAngle(Math.random() * Math.PI * 2);
} else {
Velocity.setLength(Math.random() * 3 + 1);
Velocity.setAngle(firework.getAngle + Math.PI / 2 - Math.PI * 0.25 + Math.PI * .5);
}
this.velocity = Velocity;
this.color = firework.exposionColor;
this.particleSize = Math.random() * 4;
this.TimeCreated = new Date().getTime();
this.TimeExpired = this.TimeCreated + (Math.random() * 4 + 3.5) * 100;
}
draw() {
context.strokeStyle = this.color;
context.lineWidth = this.particleSize;
let p = this.position,
lp = this.lastPosition;
context.beginPath();
context.moveTo(lp.getX(), lp.getY());
context.lineTo(p.getX(), p.getY());
context.stroke();
}
checkExpire() {
let now = new Date().getTime();
if (now >= this.TimeExpired) this.deleteObject();
}
render() {
this.draw();
this.checkExpire();
}}
document.body.addEventListener('mousedown', function (e) {
let color = randomColor();
for (var i = 0; i < Math.floor(Math.random() * 20) + 25; i++) {
new BlastParticle({
firework: {
position: vector.create(e.pageX, e.pageY),
velocity: vector.create(0, 0),
exposionColor: color },
funky: false });
}
});
setInterval(function () {
if (!startFireworks) return;
for (var i = 0; i < Math.floor(Math.random() * 4); i++) {
new firework();
}
}, 500);
function cleanupObjects() {
objects = objects.filter(o => o != undefined);
}
function loop() {
context.fillStyle = 'rgba(0,0,0,0.085)';
context.fillRect(0, 0, width, height);
let unusedObjectCount = 0;
objects.map(o => {
if (!o) {unusedObjectCount++;return;}
o.PhysicsUpdate();
o.render();
});
if (unusedObjectCount > 100) cleanupObjects();
requestAnimationFrame(loop);
}
loop();

151
js/105_vector.js Normal file
View File

@ -0,0 +1,151 @@
var vector = {
_x: 1,
_y: 0,
create: function(x, y) {
var obj = Object.create(this);
obj.setX(x);
obj.setY(y);
return obj;
},
duplicate: function() {
return vector.create(this._x, this._y);
},
random: function(maxX, maxY, minX, minY){
var x = Math.random() * (maxX-minX) + minX;
var y = Math.random() * (maxY-minY) + minY;
return vector.create(x,y);
},
setX: function(value) {
this._x = value;
},
getX: function() {
return this._x;
},
setY: function(value) {
this._y = value;
},
getY: function() {
return this._y;
},
bounds: function(size, mX, mY){
var mapsize = size;
if(this._x > mX + mapsize){ this._x = -size; }
if(this._x < -mapsize){ this._x = mX + size; }
if(this._y > mY + mapsize){ this._y = -size; }
if(this._y < -mapsize){ this._y = mY + size; }
},
outOfBounds: function(sx, sy, ex, ey){
if(this._x < sx){ return true; }
if(this._x > ex){ return true; }
if(this._y < sy){ return true; }
if(this._y > ey){ return true; }
},
setAngle: function(angle) {
var length = this.getLength();
this._x = Math.cos(angle) * length;
this._y = Math.sin(angle) * length;
},
getAngle: function() {
return Math.atan2(this._y, this._x);
},
angleTo: function(p2) {
return Math.atan2(p2.getY() - this._y, p2.getX() - this._x);
},
distanceTo: function(p2) {
var dx = p2.getX() - this._x,
dy = p2.getY() - this._y;
return Math.sqrt(dx * dx + dy * dy);
},
setLength: function(length) {
var angle = this.getAngle();
this._x = Math.cos(angle) * length;
this._y = Math.sin(angle) * length;
},
gravitateTo: function(p2, mass, mymass) {
var grav = Vector.create(0, 0),
dist = mypos.distanceTo(p2);
//grav.setLength(mass / (dist * dist));
grav.setLength((G*mass*mymass) / (dist * dist));
grav.setAngle(this.angleTo(p2));
this.addTo(grav);
},
getLength: function() {
return Math.sqrt(this._x * this._x + this._y * this._y);
},
maxSpeed: function(s){
if(this.getLength() > s){
this.setLength(s);
}
},
add: function(v2) {
return vector.create(this._x + v2.getX(), this._y + v2.getY());
},
subtract: function(v2) {
return vector.create(this._x - v2.getX(), this._y - v2.getY());
},
multiply: function(val) {
return vector.create(this._x * val, this._y * val);
},
divide: function(val) {
return vector.create(this._x / val, this._y / val);
},
addTo: function(v2) {
this._x += v2.getX();
this._y += v2.getY();
},
subtractFrom: function(v2) {
this._x -= v2.getX();
this._y -= v2.getY();
},
multiplyBy: function(val) {
this._x *= val;
this._y *= val;
},
divideBy: function(val) {
this._x /= val;
this._y /= val;
},
normalize: function(scale){
var norm = Math.sqrt(this._x * this._x + this._y * this._y);
if (norm != 0) {
return vector.create(
scale * this._x / norm,
scale * this._y / norm
);
}
},
dot: function(v2){
return this._x * v2._x + this._y * v2._y;
}
};