const CONFIG = {
kiraRadius : 5,
kiraLineWidth: 2,
kiraSpeed : 0.3,
biuSpeed : 2,
biuAcceleration: 1.02,
biuCollectionCont: 10,
biuLineWidth: 3,
boomSpeed: 10,
boomAcceleration: 0.95,
boomAngel: Math.PI*2,
boomTargetCount: 100,
boomGradient : 0.015,
boomGravity: 0.98,
boomCollectionCont: 2,
boomLineWidth: 3,
boomLineCont: {min: 10, max: 30},
animateTimerTarget: 50
}
let canvas = document.querySelector('#canvas')
let context = canvas.getContext('2d')
let cw = canvas.width = window.innerWidth
let ch = canvas.height = window.innerHeight
function randomColor(){
let num = 3
let color = []
while(num--){
color.push(Math.floor(Math.random()*254+1))
}
return color.join(', ')
}
class Kirakira {
constructor(targetX, targetY){
this.targetLocation = {x: targetX, y: targetY}
this.radius = CONFIG.kiraRadius
}
draw() {
context.beginPath()
context.arc(this.targetLocation.x, this.targetLocation.y, this.radius, 0, Math.PI * 2)
context.lineWidth = CONFIG.kiraLineWidth
context.strokeStyle = `rgba(${randomColor()}, 1)`;
context.stroke()
}
update(){
if(this.radius < CONFIG.kiraRadius){
this.radius += CONFIG.kiraSpeed
}else{
this.radius = 1
}
}
init() {
this.draw()
this.update()
}
}
class Biubiubiu {
constructor(startX, startY, targetX, targetY) {
this.startLocation = {x: startX, y: startY}
this.targetLocation = {x: targetX, y: targetY}
this.nowLoaction = {x: startX, y: startY}
this.targetDistance = this.getDistance(this.startLocation.x, this.startLocation.y, this.targetLocation.x, this.targetLocation.y);
this.speed = CONFIG.biuSpeed
this.acceleration = CONFIG.biuAcceleration
this.angle = Math.atan2(this.targetLocation.y - this.startLocation.y, this.targetLocation.x - this.startLocation.x)
this.collection = new Array(CONFIG.biuCollectionCont)
this.arrived = false
}
draw() {
context.beginPath()
try{
context.moveTo(this.collection[0][0], this.collection[0][1])
}catch(e){
context.moveTo(this.nowLoaction.x, this.nowLoaction.y)
}
context.lineWidth = CONFIG.biuLineWidth
context.lineCap = 'round'
context.lineTo(this.nowLoaction.x, this.nowLoaction.y)
context.strokeStyle = `rgba(${randomColor()}, 1)`;
context.stroke()
}
update() {
this.collection.shift()
this.collection.push([this.nowLoaction.x, this.nowLoaction.y])
this.speed *= this.acceleration
let vx = Math.cos(this.angle) * this.speed
let vy = Math.sin(this.angle) * this.speed
let nowDistance = this.getDistance(this.startLocation.x, this.startLocation.y, this.nowLoaction.x+vx, this.nowLoaction.y+vy)
if(nowDistance >= this.targetDistance){
this.arrived = true
}else{
this.nowLoaction.x += vx
this.nowLoaction.y += vy
this.arrived = false
}
}
getDistance(x0, y0, x1, y1) {
let locX = x1 - x0
let locY = y1 - y0
return Math.sqrt(Math.pow(locX, 2) + Math.pow(locY, 2))
}
init() {
this.draw()
this.update()
}
}
class Boom {
constructor(startX, startY){
this.startLocation = {x: startX, y: startY}
this.nowLocation = {x: startX, y: startY}
this.speed = Math.random()*CONFIG.boomSpeed+2
this.acceleration = CONFIG.boomAcceleration
this.angle = Math.random()*CONFIG.boomAngel
this.targetCount = CONFIG.boomTargetCount
this.nowNum = 1
this.alpha = 1
this.gradient = CONFIG.boomGradient
this.gravity = CONFIG.boomGravity
this.collection = []
this.collection = new Array(CONFIG.boomCollectionCont)
this.arrived = false
}
draw(){
context.beginPath()
try{
context.moveTo(this.collection[0][0], this.collection[0][1])
}catch(e){
context.moveTo(this.nowLocation.x, this.nowLocation.y)
}
context.lineWidth = CONFIG.boomLineWidth
context.lineCap = 'round'
context.lineTo(this.nowLocation.x, this.nowLocation.y)
context.strokeStyle = `rgba(${randomColor()}, ${this.alpha})`
context.stroke()
}
update(){
this.collection.shift()
this.collection.push([this.nowLocation.x, this.nowLocation.y])
this.speed *= this.acceleration
let vx = Math.cos(this.angle) * this.speed
let vy = Math.sin(this.angle) * this.speed + this.gravity
if(this.nowNum >= this.targetCount){
this.alpha -= this.gradient
}else{
this.nowLocation.x += vx
this.nowLocation.y += vy
this.nowNum++
}
if(this.alpha <= 0){
this.arrived = true
}
}
init(){
this.draw()
this.update()
}
}
class Animate {
constructor(){
this.kiras = []
this.bius = []
this.booms = []
this.timerTarget = CONFIG.animateTimerTarget
this.timerNum = 0
}
pushBoom(x, y){
for(let bi = Math.random()*(CONFIG.boomLineCont.max - CONFIG.boomLineCont.min)+CONFIG.boomLineCont.min; bi>0; bi--){
this.booms.push(new Boom(x, y))
}
}
initAnimate(target, cb){
target.map((item, index) => {
if(!(item instanceof Object)){
console.error('数组值错')
return false
}else{
item.init()
if(cb) { cb(index) }
}
})
}
run() {
window.requestAnimationFrame(this.run.bind(this))
context.clearRect(0, 0, cw, ch)
this.initAnimate(this.bius, (i)=>{
this.kiras[i].init()
if(this.bius[i].arrived){
this.pushBoom(this.bius[i].nowLoaction.x, this.bius[i].nowLoaction.y)
this.bius.splice(i, 1)
this.kiras.splice(i, 1)
}
})
this.initAnimate(this.booms, (i)=>{
if(this.booms[i].arrived){
this.booms.splice(i, 1)
}
})
if(this.timerNum >= this.timerTarget){
var startX = Math.random()*(cw/2)
var startY = ch
var targetX = Math.random()*cw
var targetY = Math.random()*(ch/2)
let exBiu = new Biubiubiu(startX, startY, targetX, targetY)
this.bius.push(exBiu)
let exKira = new Kirakira(targetX, targetY)
this.kiras.push(exKira)
this.timerNum = 0
}else{
this.timerNum ++
}
}
}
let a = new Animate()
a.run()