画布上的mousemove

时间:2017-04-10 20:29:55

标签: javascript canvas mouseover

我用JavaScript创建了一些基本的动画,我真的被卡住了。我想创建绘制粒子的动画,当鼠标移过它们时,它将跟随鼠标,但其他所有粒子都会随机出现。我不想使用jQuery或其中一些工作人员。到目前为止我得到了这个。有人可以给我一些提示或建议吗?到目前为止,我收到错误

  

未捕获的TypeError:particles[i].draw不是函数。

window.onload = function() {
    var canvas = document.createElement("canvas"),
        c = canvas.getContext("2d"),
        particles = {},
        particleIndex = 0,
        particleNum = 250;

    function getMousePos(canvas, evt) {
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left,
            y: evt.clientY - rect.top
        };
    }
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    document.body.appendChild(canvas);
    c.fillStyle = "black";
    c.fillRect(0, 0, canvas.width, canvas.height);

    function getRandomArbitrary(min, max) {
        return Math.random() * (max - min) + min;
    }

    function Particle() {
        this.x = getRandomArbitrary(0, 2000);
        this.y = getRandomArbitrary(0, 1000);
        this.r = Math.floor(getRandomArbitrary(0, 255));
        this.g = Math.floor(getRandomArbitrary(0, 255));
        this.b = Math.floor(getRandomArbitrary(0, 255));
        this.l = getRandomArbitrary(0, 25);
        particleIndex++;
        particles[particleIndex] = this;
        this.id = particleIndex;
    }
    canvas.addEventListener('mousemove', function(evt) {
        var mousePos = getMousePos(canvas, evt);
        Particle.prototype.draw = function() {
            this.vx = Math.random();
            this.vy = Math.random();
            this.x += this.vx;
            this.y += this.vy;
            if (this.x <= mousePos.x) {
                particles[this.id].vx = (mousePos.x - canvas.width / 2) / 100;
            }
            if (this.y <= mousePos.y) {
                particles[this.id].vy = (mousePos.y - canvas.width / 2) / 100;
            }
            c.fillStyle = "rgba(" + this.r + "," + this.g + "," + this.b + ",0.2)";
            c.beginPath();
            c.arc(this.x, this.y, this.l, 0, Math.PI * 2, false);
            c.fill();
        };
    }, false);
    for (var i = 0; i <= particleNum; i++) {
        new Particle();
    }
    setInterval(function() {
        c.fillStyle = /*"rgba(255,255,255,0.1)"*/ "black";
        c.fillRect(0, 0, canvas.width, canvas.height);
        c.fillStyle = "rgba(255,255,255,0.1)";
        for (var i in particles) {
            particles[i].draw();
        }
    }, 30);
};

1 个答案:

答案 0 :(得分:1)

在鼠标事件中设置粒子绘制原型没有用。如果你不移动鼠标,你试图绘制原型将不具有绘制功能。 Particle.draw将等于undefined,这不是函数,因而是错误。

您应该在定义Object之后立即设置原型,并且只执行一次。

function Particle() {
    this.x = getRandomArbitrary(0, 2000);
    this.y = getRandomArbitrary(0, 1000);
    this.r = Math.floor(getRandomArbitrary(0, 255));
    this.g = Math.floor(getRandomArbitrary(0, 255));
    this.b = Math.floor(getRandomArbitrary(0, 255));
    this.l = getRandomArbitrary(0, 25);
    particleIndex++;
    particles[particleIndex] = this;
    this.id = particleIndex;
}
Particle.prototype.draw = function() {  
    // rest of draw code
}

将其从鼠标事件中删除

应该停止错误

由于还有其他问题,我无法锻炼你想要达到的目标,所以我添加了一个你可能感兴趣的片段。按照我将如何做的方式(以及我如何告诉人们这样做,因为它变得非常复杂以获得高性能粒子而且SO没有给出空间)。

&#13;
&#13;
// Note this code is in ES6 check browser support if you have problems

;(function() {
    const canvas = document.createElement("canvas");
    const c = canvas.getContext("2d");
    const particleNum = 500;
    const particleMouseAttract = 5; // how far the mouse attaction fx ranges
                                    // must be > 0
                                    
    const pMA = 1 + (particleMouseAttract / 100); // alias as I hate long var names in code
    const mouseAttractDistStep = 10;
    const mAD = mouseAttractDistStep; // alias as I hate long var names in code
    canvas.width = innerWidth;
    canvas.height = innerHeight;
    const maxPSize = 10
    const pWidth = innerWidth + maxPSize * 2;
    const pHeight = innerHeight + maxPSize * 2;
    document.body.appendChild(canvas);
    canvas.addEventListener('mousemove', getMousePos); 
    requestAnimationFrame(update);    
    const mousePos = { x : 0, y : 0 }; 
    const rand = (min, max = min + (min = 0))=> Math.random() * (max - min) + min;
    const randI = (min, max)=> Math.floor(rand(min, max));
    
    
    const particle = {
        init(){  // call to create
            this.x = rand(canvas.width);
            this.y = rand(canvas.height);
            this.vx = rand(-0.1, 0.1);
            this.vy = rand(-0.1, 0.1);
            this.rad = rand(1,maxPSize);
            this.col = `rgba(${randI(255)},${randI(255)},${randI(255)},0.8)`;
            return this;  // returns referance to this particle
        },
        update () {
            var x,y,mDist,p; 
            p = this;
            p.vx += rand(-0.1, 0.1);
            p.vy += rand(-0.1, 0.1);
            // limit speed
            mDist = Math.max(1,Math.sqrt(p.vx * p.vx + p.vy * p.vy));
            p.vx = (p.vx / (mDist * mDist)) * 2;
            p.vy = (p.vy / (mDist * mDist)) * 2;            

            //paticle to the mouse as vector
            x = mousePos.x - this.x;            
            y = mousePos.y - this.y;
            // get dist
            mDist = Math.max(0.001,Math.sqrt(x * x + y * y)); // stop div by zero below
            x /= mDist;  // normalise vector to mouse
            y /= mDist;
            // apply inverted s curve that results in a value 1 for 
            // particles very close (mDist=0) and 0 for particles that
            // are infinitly far. pMA controle the amount of attraction
            // over dist.
            mDist = - 2 / 1 + Math.pow(pMA, -mDist) + 2;
            // mDist is now in the range 0 to 1 with one very close
            // add the random vector and the to mouse vector parts
            p.vx = p.vx * (1-mDist) + x * mAD * mDist;
            p.vy = p.vy * (1-mDist) + y * mAD * mDist;
            // move the particle
            p.x += p.vx;
            p.y += p.vy;
            // keep on the canvas
            p.x = (((p.x + maxPSize) % pWidth) + pWidth) % pWidth - maxPSize;
            p.y = (((p.y + maxPSize) % pHeight) + pHeight) % pHeight - maxPSize;            
        },
        draw () {
            c.fillStyle = this.col;
            c.beginPath();
            c.arc(this.x, this.y, this.rad, 0, Math.PI * 2); 
            c.fill();
        },       
    }
    const particles = {
        items : [],
        update() { 
            for(var i = 0; i < this.items.length; i ++){ this.items[i].update() } 
        },
        draw() { 
            for(var i = 0; i < this.items.length; i ++){ this.items[i].draw() } 
        },       
        add(particle) { this.items.push(particle) },
    }    
    function start(){
        for (var i = 0; i <= particleNum; i++) {
            particles.add({...particle}.init());
        }    
        requestAnimationFrame(update);
    }
    function getMousePos(evt) {
        var bounds = canvas.getBoundingClientRect(); 
        mousePos.x = evt.clientX - bounds.left;
        mousePos.y = evt.clientY - bounds.top;
    }

    function update(time){
        c.fillStyle = "black";
        c.fillRect(0, 0, canvas.width, canvas.height);
        particles.update()
        particles.draw();
        // get next frame
        requestAnimationFrame(update);
    };
    start();
}());
&#13;
canvas {
   margin : -8px;
   border-width : 0px;
}
   
&#13;
&#13;
&#13;