You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.9 KiB
86 lines
2.9 KiB
|
6 years ago
|
import RainDrop from "./RainDrop"
|
||
|
|
|
||
|
6 years ago
|
export default class ReflectRain {
|
||
|
|
constructor(canvas, {rainDropCount = 500, rainColor = 'rgba(150,180,255,0.8)', backgroundColor = '#2d3a4b'} = {}) {
|
||
|
6 years ago
|
this.props = {rainDropCount, rainColor, backgroundColor}
|
||
|
|
this.rainDrops = []
|
||
|
|
this.timer = null
|
||
|
|
this.rAF = null
|
||
|
|
this.stopSign = false
|
||
|
|
this.canvas = canvas
|
||
|
|
this.ctx = canvas.getContext('2d')
|
||
|
6 years ago
|
this.loop = this.loop.bind(this)
|
||
|
6 years ago
|
this.start()
|
||
|
|
}
|
||
|
|
|
||
|
6 years ago
|
start() {
|
||
|
6 years ago
|
this.resizeObserver = new ResizeObserver(() => this.resize())
|
||
|
|
this.resizeObserver.observe(this.canvas)
|
||
|
6 years ago
|
this.resize()
|
||
|
|
this.loop()
|
||
|
|
}
|
||
|
|
|
||
|
|
stop() {
|
||
|
6 years ago
|
if (this.resizeObserver) {
|
||
|
|
this.resizeObserver.disconnect()
|
||
|
|
this.resizeObserver = null
|
||
|
|
}
|
||
|
6 years ago
|
this.stopSign = true
|
||
|
|
this.rainDrops = []
|
||
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
||
|
|
}
|
||
|
|
|
||
|
|
loop() {
|
||
|
|
if (this.stopSign) {
|
||
|
|
this.rAF && window.cancelAnimationFrame(this.rAF)
|
||
|
|
this.timer && window.clearTimeout(this.timer)
|
||
|
|
return
|
||
|
6 years ago
|
}
|
||
|
6 years ago
|
if (this.rainDrops.length < this.props.rainDropCount) {
|
||
|
|
this.timer = window.setTimeout(() => this.rainDrops.push(new RainDrop(this)), Math.random() * 200)
|
||
|
|
}
|
||
|
|
else if (this.timer) {
|
||
|
|
window.clearTimeout(this.timer)
|
||
|
|
this.timer = null
|
||
|
|
}
|
||
|
|
this.draw()
|
||
|
|
this.rAF = window.requestAnimationFrame(this.loop)
|
||
|
6 years ago
|
}
|
||
|
|
|
||
|
|
draw() {
|
||
|
|
this.ctx.fillStyle = this.props.backgroundColor
|
||
|
|
this.ctx.fillRect(0, 0, this.dimensions.width, this.floor)
|
||
|
|
for (let i = 0, len = this.rainDrops.length; i < len; i++) {
|
||
|
|
let rainDrop = this.rainDrops[i]
|
||
|
|
rainDrop.update()
|
||
|
|
this.ctx.fillStyle = this.props.rainColor
|
||
|
|
this.ctx.fillRect(rainDrop.position.x, rainDrop.position.y, rainDrop.size, rainDrop.size)
|
||
|
|
}
|
||
|
|
this.reflect()
|
||
|
|
}
|
||
|
|
|
||
|
|
reflect() {
|
||
|
|
let grad = this.ctx.createLinearGradient(this.dimensions.width / 2, this.floor * 0.6, this.dimensions.width / 2, this.floor)
|
||
|
|
grad.addColorStop(0, 'rgba(80,90,100,1)')
|
||
|
|
grad.addColorStop(1, 'rgba(80,90,100,0)')
|
||
|
|
this.ctx.save()
|
||
|
|
this.ctx.scale(1, -1)
|
||
|
|
this.ctx.translate(0, this.floor * -2)
|
||
|
|
this.ctx.filter = 'blur(3px) saturate(150%)'
|
||
|
|
this.ctx.drawImage(this.canvas, 0, 0, this.dimensions.width, this.floor, 0, 0, this.dimensions.width, this.floor)
|
||
|
|
this.ctx.fillStyle = grad
|
||
|
|
this.ctx.fillRect(0, 0, this.dimensions.width, this.floor)
|
||
|
|
this.ctx.restore()
|
||
|
|
}
|
||
|
|
|
||
|
6 years ago
|
resize() {
|
||
|
|
this.dimensions = {
|
||
|
|
width: window.innerWidth,
|
||
|
|
height: window.innerHeight
|
||
|
6 years ago
|
}
|
||
|
6 years ago
|
this.canvas.width = this.dimensions.width
|
||
|
|
this.canvas.height = this.dimensions.height
|
||
|
|
this.floor = this.dimensions.height * 0.7
|
||
|
6 years ago
|
}
|
||
|
|
}
|