我试图做一个简单的粒子爆炸效果,所以当用户点击应用程序的某个位置时,它会获得用户点击位置,创建画布,创建爆炸效果,然后移除画布。
我对画布全新,并从此网站获得了这个想法:canvas example
案例是它没有为爆炸效果获得正确的点击位置,它应该从点击区域的中心开始。但是我离左/上角越远,越往屏幕,我的效果就会显示出来。
所以这里有一些代码:
在我的app.components.ts
(谁是主文件,我需要它在每个页面上工作,所以我决定把我的代码放在这里)我有以下内容:
import { Particle } from './Particle'; // IMPORT A PARTICLE FUNCTION
// THESE ARE MY PARTICLE OPTIONS
public ANGLE: number = 90;
public SPEED: number = 8;
public PARTICLE_SIZE: number = 1;
public NUMBER_OF_PARTICLES: number = 20;
public RANGE_OF_ANGLE: number = 360;
public PARTICLE_LIFESPAN: number = 15;
public PARTICLE_COLOR: string = 'rgb(255,0,0)';
public particles: any[] = [];
public pCtxWidth: number = window.innerWidth; // not using
public pCtxHeight: number = window.innerHeight; // not using
document.addEventListener('click', (data) => {
// CREATE MY CANVAS HTML ELEMENT AND APPEND IN THE BODY
let c = document.createElement('canvas');
c.className = 'clique';
c.style.position = 'absolute';
c.style.width = String(window.innerWidth) + 'px'; //I'M USING THE WHOLE SCREEN SIZE, BUT IT DOESN'T NEEDS TO BE THAT BIG, IT CAN BE 80px
c.style.height = String(window.innerHeight) + 'px';
c.style.left = '0px';
c.style.top = '0px';
document.body.appendChild(c);
// GET MY PAGE CLICK POSITION, ALSO TRIED WITHOUT - c.offsetLeft
const x = data.pageX - c.offsetLeft,
y = data.pageY - c.offsetTop;
// CREATE MY 2DCONTEXT AND CALL THE SPARK FUNCTION
let pCtx = c.getContext("2d");
this.spark(x, y, this.ANGLE, pCtx, c);
this.smartAudio.play('click');
}, true);
// draw a new series of spark particles
spark = (x, y, angle, pCtx, c) => {
// create 20 particles 10 degrees surrounding the angle
for (var i = 0; i < this.NUMBER_OF_PARTICLES; i++) {
// get an offset between the range of the particle
let offset = Math.round(this.RANGE_OF_ANGLE * Math.random())
- this.RANGE_OF_ANGLE / 2;
let scaleX = Math.round(this.SPEED * Math.random()) + 1;
let scaleY = Math.round(this.SPEED * Math.random()) + 1;
this.particles.push(new Particle(x, y,
Math.cos((angle + offset) * Math.PI / 180) * scaleX,
Math.sin((angle + offset) * Math.PI / 180) * scaleY,
this.PARTICLE_LIFESPAN, this.PARTICLE_COLOR, pCtx));
}
this.animationUpdate(pCtx, c, x, y);
}
animationUpdate = function (pCtx, c, x, y) {
// update and draw particles
pCtx.clearRect(0, 0, x, y);
for (var i = 0; i < this.particles.length; i++) {
if (this.particles[i].dead()) {
this.particles.splice(i, 1);
i--;
}
else {
this.particles[i].update();
this.particles[i].draw(pCtx);
}
}
if (this.particles.length > 0) {
// await next frame
requestAnimationFrame(() => { this.animationUpdate(pCtx, c, x, y) });
} else {
document.body.removeChild(c);
}
}
这是我的Particle
:
export function Particle(x, y, xVelocity, yVelocity, lifespan, color, pCtx) {
// set initial alpha to 1.0 (fully visibile)
this.alpha = 1.0;
// dAlpha is the amount that alpha changes per frame, randomly
// scaled around the provided particle lifespan
this.dAlpha = 1 / (Math.random() * lifespan + 0.001);
// updates the particle's position by its velocity each frame,
// and adjust's the alpha value
this.update = function() {
x += xVelocity;
y -= yVelocity;
this.alpha -= this.dAlpha;
if (this.alpha < 0)
this.alpha = 0;
}
// draw the particle to the screen
this.draw = function(pCtx: any) {
pCtx.save();
pCtx.fillStyle = color;
pCtx.globalAlpha = this.alpha;
pCtx.beginPath();
pCtx.arc(x, y, 1, 0, 2 * Math.PI, false);
pCtx.closePath();
pCtx.fill();
pCtx.restore();
}
// returns TRUE if this particle is "dead":
// i.e. delete and stop updating it if this returns TRUE
this.dead = function() {
return this.alpha <= 0;
}
}
那么我做错了什么?如何让粒子效果在我点击的位置爆炸?
以下是我所获得的图片,我点击了左上角的X,但爆炸发生在点击区域之外。
提前致谢。
答案 0 :(得分:0)
我无法看到您设置画布分辨率,您只是设置画布显示大小。这可以解释渲染和用户IO之间的不匹配。
创建画布时尝试以下操作
c.style.width = (c.width = innerWidth) + 'px';
c.style.height = (c.height = innerHeight) + 'px';
这将使画布分辨率与显示尺寸相匹配,这样您将在正确的像素位置进行渲染。