画布点击粒子爆炸效果不针对鼠标位置

时间:2017-07-25 18:11:05

标签: javascript html typescript canvas ionic2

我试图做一个简单的粒子爆炸效果,所以当用户点击应用程序的某个位置时,它会获得用户点击位置,创建画布,创建爆炸效果,然后移除画布。

我对画布全新,并从此网站获得了这个想法: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,但爆炸发生在点击区域之外。

image

提前致谢。

1 个答案:

答案 0 :(得分:0)

我无法看到您设置画布分辨率,您只是设置画布显示大小。这可以解释渲染和用户IO之间的不匹配。

创建画布时尝试以下操作

c.style.width = (c.width = innerWidth) + 'px'; 
c.style.height = (c.height = innerHeight) + 'px';

这将使画布分辨率与显示尺寸相匹配,这样您将在正确的像素位置进行渲染。