pixi+victor实现跟随鼠标彩虹发光烟花粒子动画效果代码
代码语言:html
所属分类:粒子
代码描述:pixi+victor实现跟随鼠标彩虹发光烟花粒子动画效果代码
代码标签: pixi victor 跟随 鼠标 彩虹 发光 烟花 粒子 动画
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> html, body { padding: 0; margin: 0; overflow: hidden; } </style> </head> <body> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/pixi.7.2.4.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/victor.1.1.0.js"></script> <script type="module"> console.clear(); const SHOW_FLOW_FIELD = false; const PARTICLE_COUNT = 30000; const GRID_RESOLUTION = 30; function hslToHex(h, s, l) { l /= 100; const a = s * Math.min(l, 1 - l) / 100; const f = n => { const k = (n + h / 30) % 12; const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed }; return `#${f(0)}${f(8)}${f(4)}`; } class Walker { constructor (texture, size, radius) { this.radius = radius this.size = size; this.speed = 0; this.startSpeed = 10; this.hue = 0; this.sparkleCount = 1; this.vectorWeight = 1; this.sprite = new PIXI.Sprite(texture); this.sprite.anchor.set(0.5); this.vector = new Victor( Math.random() * 2 - 1, Math.random() * 2 - 1) this.sprite.x = (this.size.x * 0.5) * (this.size.grid + this.size.gutter) this.sprite.y = (this.size.y * 0.5) * (this.size.grid + this.size.gutter) this.sprite.scale.set(0) } reset(position, direction, distance, hue, explode) { this.hue = hue this.startSpeed = Math.max(3, Math.min(explode ? 15 : 10, distance)) this.vector = direction this.sparkleCount = 0.2; this.speed = this.startSpeed * (explode ? 0.7 + Math.random() * 0.3 : Math.random() * 1); this.sprite.x = position.x; this.sprite.y = position.y; if(explode) this.vectorWeight = 0; } move(gridVector, delta) { this.vectorWeight += 0.05 * delta; if(this.vectorWeight > 1) this.vectorWeight = 1; this.speed -= 0.06 * delta ; if(this.speed <= 0.06) this.speed = 0 this.vector.mix(gridVector, 0.7 * this.vectorWeight).normalize() let newX = this.sprite.x + this.vector.x * this.speed; let newY = this.sprite.y + this.vector.y * this.speed; const TL = new Victor(this.radius, this.radius); const BR = new Victor( this.size.x * (this.size.grid + this.size.gutter) - this.radius, this.size.y * (this.size.grid + this.size.gutter) - this.radius ) if(newX < TL.x || newX > BR.x ) this.vector.invertX(); if(newY < TL.y || newY > BR.y ) this.vector.invertY(); if(newX < TL.x) this.sprite.x = TL.x; if(newX > BR.x) this.sprite.x = BR.x; if(newY < TL.y) this.sprite.y = TL.y; if(newY > BR.y) this.sprite.y = BR.y; this.sprite.x += (this.vector.x * delta) * this.speed; this.sprite.y += (this.vector.y * delta) * this.speed; if(this.speed > 4 && Math.random() > 0.99) this.sparkleCount = 1; this.sparkleCount -= 0.1; if(this.sparkleCount < 0) this.sparkleCount = 0; const sparkling = this.sparkleCount > 0 && this.speed > 0.1 this.sprite.scale.set(sparkling ? 1 : this.speed / this.startSpeed) this.sprite.tint = hslToHex(this.hue, 100, 50 + ( sparkling ? 50 : 0)) } clampX (x) { return Math.max(0, Math.min(this.size.x - 1, Math.round(x))) } clampY (y) { return Math.max(0, Math.min(this.size.y - 1, Math.round(y))) } get x () { return this.clampX(this.sprite.x / (this.size.grid + this.size.gutter)) } get y () { return this.clampY(this.sprite.y / (this.size.grid + this.size.gutter)) } } class App { constructor() { this.pixi = new PIXI.Application({ background: '#1c1c1c', resizeTo: window }); document.body.appendChild(this.pixi.view); this.size = { grid: GRID_RESOLUTION, gutter: 1, border: 0, x: 0, y: 0 } this.hueCount = 0; this.walkers = []; this.walkerTotal = PARTICLE_COUNT; this.walkerCount = 0; this.interacted = false; this.cursorPoints = [] this.cursorPosition = new Victor(0, 0); this.cursorDirection = new Victor(0, 0); let arrowGraphic = new PIXI.Graphics() arrowGraphic.lineStyle(0); arrowGraphic.beginFill(0xffffff, 1); arrowGraphic.drawPolygon([ this.size.grid * 0.6, this.size.grid * 0.35, this.size.grid * 0.8, this.size.grid * 0.5, this.size.grid * 0.6, this.size.grid * 0.65, ]) arrowGraphic.drawRect(this.size.grid * 0.1, this.size.grid * 0.5 - 0.5, this.size.grid * 0.5, 1); arrowGraphic.endFill(); this.arrowTexture = this.pixi.renderer.generateTexture(arrowGraphic); this.points = 0; this.grid = null; this.arrows = []; this.container = new PIXI.Container(); this.pixi.stage.addChild(this.container); this.pixi.renderer.on('resize', () => this.onResize()) this.pixi.stage.interactive = true; this.pixi.stage.hitArea = this.pixi.screen; this.pixi.stage.on("pointermove", (e) => { this.interacted = true; const pos = e.data.global; const newPositionVector = new Victor(pos.x - Math.max(0, this.size.border * 2), pos.y - Math.max(0, this.size.border * 2)) // this.cursorMoved = true; const distance = newPositionVector.distance(this.cursorPosition) const newDirectionVector = newPositionVector.clone().subtract(this.cursorPosition) this.cursorPosition.copy(newPositionVector) this.cursorDirection.mix(newDirectionVector, 0.9) this.cursorPoints.push({ position: this.cursorPosition.clone(), direction: this.cursorDirection.clone(), distance }) }); this.pixi.stage.on("click", (e) => { // console.log(e.data.global) const pos = e.data.global; for(let i = 0; i < 10; i++) { this.cursorPoints.push({ position: new Victor(pos.x, pos.y), direction: new Victor(Math.random() * 2 -1, Math.random() * 2 -1), distance: 30, explode: true }) } }) this.onResize() this.pixi.ticker.add((delta) => this.tick(delta)); } setFlowField() { for(let i = 0; i < this.points * 2; i += 2) { this.grid[i] = Math.sin(i * 0.1); //Math.random() * 2 - 1 this.grid[i+1] = Math.sin((i+1) * 0.05); //Math.rando.........完整代码请登录后点击上方下载按钮下载查看
网友评论0