JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
console.clear();
let $ = {};
/*===========================================
Utility
===========================================*/
$.PI = Math.PI;
$.HALFPI = $.PI * 0.5;
$.TAU = $.PI * 2;
$.dist = ( x1, y1, x2, y2 ) => {
let dx = x1 - x2;
let dy = y1 - y2;
return Math.sqrt( dx * dx + dy * dy );
};
$.rand = ( min, max ) => {
return Math.random() * ( max - min ) + min;
};
$.hsla = ( h, s, l, a ) => {
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
};
/*===========================================
Star
===========================================*/
$.Star = class {
constructor() {
this.radius = $.rand( 1, 4 );
this.radiusBase = this.radius;
this.x = $.rand( 20, $.w - 20 );
this.y = $.rand( 20, $.h - 20 );
this.pulse = $.rand( 0, 100 );
}
step() {
this.radius = this.radiusBase + Math.sin( this.pulse * 0.05 ) * this.radiusBase * 0.5;
this.pulse++;
}
draw() {
$.ctx.beginPath();
$.ctx.arc( this.x, this.y, this.radius, 0, $.TAU );
$.ctx.fill();
}
};
/*===========================================
Meteor
===========================================*/
$.Meteor = class {
constructor() {
this.angle = $.HALFPI - ( 45 / 360 ) * $.TAU;
this.reset();
}
reset() {
this.radius = $.rand( 4, 10 );
this.radiusBase = this.radius;
this.x = $.rand( -$.w, $.w );
this.y = $.rand( -$.h, -this.radius * 2 - 10 );
this.vel = this.radius * 0.15;
this.tail = this.radius * 16;
this.sx = 0;
this.sy = 0;
this.ex = 0;
this.ey = 0;
this.pulse = $.rand( 0, 100 );
this.anglePulse = 0;
}
step() {
this.pulse++;
this.anglePulse = Math.sin( this.pulse * 0.1 ) * 0.1;
this.x += Math.cos( this.angle ) * this.vel;
this.y += Math.sin( this.angle ) * this.vel;
this.sx = this.x + Math.cos( this.angle + $.PI ) * this.radius * 2;
this.sy = this.y + Math.sin( this.angle + $.PI ) * this.radius * 2;
this.ex = this.sx + Math.cos( this.angle + $.PI ) * this.tail;
this.ey = this.sy + Math.sin( this.angle + $.PI ) * this.tail;
if( this.ey > $.h + 10 ) {
this.reset();
}
}
draw() {
$.ctx.lineWidth = this.radius * 0.35;
// body
$.ctx.beginPath();
$.ctx.arc( this.x, this.y, this.radius, 0, $.TAU );
$.ctx.fill();
// shockwave
$.ctx.beginPath();
$.ctx.arc( this.x, this.y, this.radius * 2, this.angle - $.HALFPI + this.anglePulse, this.angle + $.HALFPI + this.anglePulse );
$.ctx.stroke();
// tail
$.ctx.beginPath();
$.ctx.moveTo( this.sx, this.sy );
$.ctx.lineTo( this.ex, this.ey );
$.ctx.stroke();
}
};
/*===========================================
Initialize
===========================================*/
$.init = () => {
$.c = document.querySelector( 'canvas' )
$.ctx = $.c.getContext( '2d' );
$.w = $.c.width = 600;
$.h = $.c.height = 600;
$.meteors = [];
$.stars = [];
$.meteorCount = 10;
$.starCount = 20;
$.colorCount = 5;
$.ctx.lineCap = 'round';
$.ctx.strokeStyle = '#fff';
$.gradient = $.ctx.createLinearGradient( 0, 0, $.w, $.h );
for( let i = 0; i < $.colorCount; i++ ) {
let color = $.hsla( 244 + i * 5, 25, 12 + i * 3, 1 );
let pos1 = i / $.colorCount;
let pos2 = ( i + 1 ) / $.colorCount;
$.gradient.addColorStop( pos1, color );
$.gradient.addColorStop( pos2, color );
}
for( let j = 0; j < $.meteorCount; j++ ) {
$.meteors.push( new $.Meteor() );
}
for( let k = 0; k < $.starCount; k++ ) {
$.stars.push( new $.Star() );
}
$.loop();
};
/*===========================================
Step
===========================================*/
$.step = () => {
$.meteors.forEach( ( item ) => { item.step() } );
$.stars.forEach( ( item ) => { item.step() } );
};
/*===========================================
Draw
===========================================*/
$.draw = () => {
$.ctx.fillStyle = $.gradient;
$.ctx.fillRect( 0, 0, $.w, $.h );
$.ctx.fillStyle = '#fff';
$.meteors.forEach( ( item ) => { item.draw() } );
$.stars.forEach( ( item ) => { item.draw() } );
};
/*===========================================
Loop
===========================================*/
$.loop = () => {
requestAnimationFrame( $.loop );
$.step();
$.draw();
};
/*===========================================
Begin
===========================================*/
$.init();