javascript - Canvas onClick 添加到数组

标签 javascript arrays html animation canvas

我得到了这个 HTML5 canvas 项目,我正在为此苦苦挣扎。 基本上我试图在点击时添加一个新的粒子。 并将粒子插入粒子阵列,但是 粒子不显示。我可以看到粒子被推到带有鼠标坐标的数组中,但似乎并没有绘制出最后一个粒子。 我做错了什么?

参见示例。

// Request animation frame
var requestAnimationFrame = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame;

// Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Set full-screen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Options
var num = 100;              // Number of particles to draw
var size = 2;               // Particle size
var color = '#dd64e6';      // Particle color
var min_speed = .3;         // Particle min speed
var max_speed = 2;          // Particle max speed
var dist = 100; 		    // Max distance before line gets cut
var dist_sq = dist * dist;  // Dist squared
var line_width = 2;         // Line width
var background = '#181b23'; // Background color
var line_color = '#1d2631'; // Line color
var fps = 60;
var now, delta;
var then = Date.now();
var interval = 1000 / fps;

if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
    num = 10;
    fps = 29;
}

// Particles array
var particles = [];
for (var i = 0; i < num; i++) {
    particles.push(
        new create_particle(false, false)
    );
}

// Lets animate the particle
function draw() {

    // Loop
    requestAnimationFrame(draw);

    now = Date.now();
    delta = now - then;

    if (delta > interval) {

        then = now - (delta % interval);

        // Background
        ctx.fillStyle = background;
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Lets draw particles from the array now
        draw_particles();

    }

}

// Draw particles
function draw_particles() {

    for (var t = 0; t < num; t++) {

        // This particle
        var p = particles[t];

        for (var q = t + 1; q < num; q++) {

            // Check X first, maybe we don't need to
            // calculate Y
            var x = particles[q].x - p.x;
            if ((x *= x) < dist_sq) {

                // Check passed, calculate Y
                var y = particles[q].y - p.y;
                if (x + (y * y) < dist_sq) {

                    // Check passed, draw line
                    draw_line(p.x, p.y, particles[q].x, particles[q].y);

                }

            }

        }

        // Color
        ctx.fillStyle = color;

        // Circle path
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.radius, Math.PI * 2, false);
        ctx.fill();

        // Lets use the velocity now
        p.x += p.vx;
        p.y += p.vy;

        // If there is only 1 particle
        // show X, Y, and velocity
        if (num === 1) {
            ctx.fillText('Y:' + p.y, 20, 20);
            ctx.fillText('X:' + p.x, 20, 40);
            ctx.fillText('YV:' + p.vy, 20, 60);
            ctx.fillText('XV:' + p.vx, 20, 80);
        }

        // To prevent the balls from moving out of the canvas
        if (p.x < size) p.vx *= (p.vx / -p.vx);
        if (p.y < size) p.vy *= (p.vy / -p.vy);
        if (p.x > canvas.width - size) p.vx *= (-p.vx / p.vx);
        if (p.y > canvas.height - size) p.vy *= (-p.vy / p.vy);

    }

}

// Return a particle object
function create_particle(xPos, yPos) {

    // Position
    if (xPos == false && yPos == false) {
        this.x = Math.random() * canvas.width;
        this.y = Math.random() * canvas.height;
    } else {
        this.x = xPos;
        this.y = yPos;
    }

    // Velocity
    this.vx = random_int_between(min_speed, max_speed);
    this.vy = random_int_between(min_speed, max_speed);

    // Size
    this.radius = size;

    console.log('particle created at: ' + this.x + ', ' + this.y);

}

// Returns an random integer, positive or negative
// between the given value
function random_int_between(min, max) {

    var num = Math.floor(Math.random() * max) - min;
    num *= Math.floor(Math.random() * 2) == 1 ? 1 : -1;
    return num;

}

// Draw a line between 2 particles
// given the particles x and y position
function draw_line(p_x, p_y, p2_x, p2_y) {

    ctx.beginPath();
    ctx.lineWidth = line_width;
    ctx.strokeStyle = line_color;
    ctx.moveTo(p_x, p_y);
    ctx.lineTo(p2_x, p2_y);
    ctx.stroke();

}

// When the canvas is clicked
// add new particle
function clicked(e) {

    var mouseXpos, mouseYpos;

    if (e.offsetX) {
        mouseXpos = e.offsetX;
        mouseYpos = e.offsetY;
    } else if (e.layerX) {
        mouseXpos = e.layerX;
        mouseYpos = e.layerY;
    }

    particles.push(
        new create_particle(mouseXpos, mouseYpos)
    );

}

canvas.addEventListener('click', function(e) {
    clicked(e);
}, false);

draw();
<!DOCTYPE html>

<html>

	<head>
		<style>
		* {margin:0;padding:0;overflow:hidden;}
		</style>
	</head>

    <body>

        <canvas id="canvas">{{-- The background --}}</canvas>

    </body>

</html>

最佳答案

好吧,除了在评论中没有其他人回答这个问题,我想我会回答这个问题,这样其他人可能不会对同样的事情感到疑惑。

问题是您使用变量“num”来保存粒子数。如果您改为使用“particles.length”,则可以

// Request animation frame
var requestAnimationFrame = window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame;

// Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Set full-screen
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Options
var num = 100;              // Number of particles to draw
var size = 2;               // Particle size
var color = '#dd64e6';      // Particle color
var min_speed = .3;         // Particle min speed
var max_speed = 2;          // Particle max speed
var dist = 100; 		    // Max distance before line gets cut
var dist_sq = dist * dist;  // Dist squared
var line_width = 2;         // Line width
var background = '#181b23'; // Background color
var line_color = '#1d2631'; // Line color
var fps = 60;
var now, delta;
var then = Date.now();
var interval = 1000 / fps;

if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
    num = 10;
    fps = 29;
}

// Particles array
var particles = [];
for (var i = 0; i < num; i++) {
    particles.push(
        new create_particle(false, false)
    );
}

// Lets animate the particle
function draw() {

    // Loop
    requestAnimationFrame(draw);

    now = Date.now();
    delta = now - then;

    if (delta > interval) {

        then = now - (delta % interval);

        // Background
        ctx.fillStyle = background;
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Lets draw particles from the array now
        draw_particles();

    }

}

// Draw particles
function draw_particles() {

    for (var t = 0; t < particles.length; t++) {

        // This particle
        var p = particles[t];

        for (var q = t + 1; q < particles.length; q++) {

            // Check X first, maybe we don't need to
            // calculate Y
            var x = particles[q].x - p.x;
            if ((x *= x) < dist_sq) {

                // Check passed, calculate Y
                var y = particles[q].y - p.y;
                if (x + (y * y) < dist_sq) {

                    // Check passed, draw line
                    draw_line(p.x, p.y, particles[q].x, particles[q].y);

                }

            }

        }

        // Color
        ctx.fillStyle = color;

        // Circle path
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.radius, Math.PI * 2, false);
        ctx.fill();

        // Lets use the velocity now
        p.x += p.vx;
        p.y += p.vy;

        // If there is only 1 particle
        // show X, Y, and velocity
        if (num === 1) {
            ctx.fillText('Y:' + p.y, 20, 20);
            ctx.fillText('X:' + p.x, 20, 40);
            ctx.fillText('YV:' + p.vy, 20, 60);
            ctx.fillText('XV:' + p.vx, 20, 80);
        }

        // To prevent the balls from moving out of the canvas
        if (p.x < size) p.vx *= (p.vx / -p.vx);
        if (p.y < size) p.vy *= (p.vy / -p.vy);
        if (p.x > canvas.width - size) p.vx *= (-p.vx / p.vx);
        if (p.y > canvas.height - size) p.vy *= (-p.vy / p.vy);

    }

}

// Return a particle object
function create_particle(xPos, yPos) {

    // Position
    if (xPos == false && yPos == false) {
        this.x = Math.random() * canvas.width;
        this.y = Math.random() * canvas.height;
    } else {
        this.x = xPos;
        this.y = yPos;
    }

    // Velocity
    this.vx = random_int_between(min_speed, max_speed);
    this.vy = random_int_between(min_speed, max_speed);

    // Size
    this.radius = size;

    console.log('particle created at: ' + this.x + ', ' + this.y);

}

// Returns an random integer, positive or negative
// between the given value
function random_int_between(min, max) {

    var num = Math.floor(Math.random() * max) - min;
    num *= Math.floor(Math.random() * 2) == 1 ? 1 : -1;
    return num;

}

// Draw a line between 2 particles
// given the particles x and y position
function draw_line(p_x, p_y, p2_x, p2_y) {

    ctx.beginPath();
    ctx.lineWidth = line_width;
    ctx.strokeStyle = line_color;
    ctx.moveTo(p_x, p_y);
    ctx.lineTo(p2_x, p2_y);
    ctx.stroke();

}

// When the canvas is clicked
// add new particle
function clicked(e) {

    var mouseXpos, mouseYpos;

    if (e.offsetX) {
        mouseXpos = e.offsetX;
        mouseYpos = e.offsetY;
    } else if (e.layerX) {
        mouseXpos = e.layerX;
        mouseYpos = e.layerY;
    }

    particles.push(
        new create_particle(mouseXpos, mouseYpos)
    );

}

canvas.addEventListener('click', function(e) {
    clicked(e);
}, false);

draw();
<!DOCTYPE html>

<html>

	<head>
		<style>
		* {margin:0;padding:0;overflow:hidden;}
		</style>
	</head>

    <body>

        <canvas id="canvas">{{-- The background --}}</canvas>

    </body>

</html>

我敢于走出我们的问题范围,因为您可以通过使用 Array.prototype.forEach 来防止将来出现此类问题,并移动点的绘制并将它们约束到新函数。具有简化代码的额外好处。

// Draw particles
function draw_particles() {
    particles.forEach(function(p,pi){
        particles.forEach(function(p2,p2i){
            if(pi === p2i){
                return;
            }
            // Check X first, maybe we don't need to
            // calculate Y
            var x = p2.x - p.x;
            if ((x *= x) < dist_sq) {
                // Check passed, calculate Y
                var y = p2.y - p.y;
                if (x + (y * y) < dist_sq) {
                    // Check passed, draw line
                    draw_line(p.x, p.y, p2.x, p2.y);
                    draw_dot(p);
                    constrain(p);
                }
            }
        });

    });
}

// Draw particle
function draw_dot(p){
    // Color
    ctx.fillStyle = color;

    // Circle path
    ctx.beginPath();
    ctx.arc(p.x, p.y, p.radius, Math.PI * 2, false);
    ctx.fill();
    ctx.closePath();

    // Lets use the velocity now
    p.x += p.vx;
    p.y += p.vy;

    // If there is only 1 particle
    // show X, Y, and velocity
    if (particles.length === 1) {
        ctx.fillText('Y:' + p.y, 20, 20);
        ctx.fillText('X:' + p.x, 20, 40);
        ctx.fillText('YV:' + p.vy, 20, 60);
        ctx.fillText('XV:' + p.vx, 20, 80);
    }
}

// Constrain particle movement
function constrain(p){
    // To prevent the balls from moving out of the canvas
    if (p.x < size) p.vx *= (p.vx / -p.vx);
    if (p.y < size) p.vy *= (p.vy / -p.vy);
    if (p.x > canvas.width - size) p.vx *= (-p.vx / p.vx);
    if (p.y > canvas.height - size) p.vy *= (-p.vy / p.vy);
}

使用 Array.prototype.length 和 Array.prototype.forEach 可以降低出现数组索引问题的风险。

关于javascript - Canvas onClick 添加到数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43413068/

相关文章:

c - C 中存储 char 的动态数组

arrays - 为什么在动态数组末尾插入是 O(1),而在中间插入是 O(n)?

html - 如何在不移动标题的情况下将此 Logo 移动到我的页眉上?

javascript - 如何在 Bootstrap Jumbotron 中将按钮居中?

javascript - 将内容发送到 WordPress 的纯文本编辑器

javascript - 检查父窗口是否为 iframe

javascript - 一个简单的 ReactJS 示例来显示警报

javascript - Gulp - 替换文本

javascript - 使用 for 循环、数组和事件监听器更改输入元素的 "name"属性 - 无 jQuery

javascript 获取当前文件脚本路径