Сделайте ваши очки trace
в данном контексте (может быть даже Path2D) и сохраните фактический чертеж для средства визуализации.
Все, что вам нужно сделать, это создать контекст moveTo
их собственные координаты до трассировки rect
.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2 )
);
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
ctx.beginPath();
for (let p of particles) {
p.trace(ctx);
}
ctx.fillStyle = "gray";
ctx.stroke(); // OP has it reversed, but then the fill-color is almost not visible
// (1.5 width - 2*0.5 stroke leaves only 0.5 for the fill => antialiased...
ctx.fill();
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
Но это работает только потому, что все ваши частицы имеют одинаковый цвет. Если этого не произойдет, вам понадобится немного больше логики c:
const colors = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow'];
class Point {
constructor(x, y, color=0) {
this.x = x;
this.y = y;
this.color = color;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2, (Math.random()*colors.length-1)|0 )
);
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
let last_color = -1;
for (let p of particles) {
let p_color = p.color;
if( p_color !== last_color ) {
paint();
last_color = p_color;
}
p.trace(ctx);
}
paint(); // the last
function paint() {
ctx.fillStyle = colors[ last_color ];
ctx.strokeStyle = colors[ (last_color + 1) % colors .length ];
ctx.stroke();
ctx.fill();
ctx.beginPath();
}
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
Хотя, делая это, вы вполне можете получить множество рисунков, поэтому последний трюк, который может не сработать везде, - отсортировать частицы по их цвет. Это приводит к другому графику c, так как этот один цвет всегда будет наверху, но он может работать в некоторых случаях, и выигрыш в производительности может соответствовать недостаткам.
const colors = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow'];
class Point {
constructor(x, y, color=0) {
this.x = x;
this.y = y;
this.color = color;
}
rmove() {
this.x += Math.round(Math.random() < 0.5 ? -1 : 1);
this.y += Math.round(Math.random() < 0.5 ? -1 : 1);
}
trace (ctx) {
ctx.moveTo( this.x, this.y );
ctx.rect(this.x, this.y, 1.5, 1.5);
}
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cwidth = canvas.width = 300;
const cheight = canvas.height = 300;
const particles = Array.from(
{ length: 5000 },
()=> new Point( cwidth/2, cheight/2, (Math.random()*colors.length-1)|0 )
);
particles.sort( (a, b) => a.color - b.color );
function animate () {
update();
draw();
window.requestAnimationFrame(animate);
}
function update() {
for (let p of particles) {
p.rmove();
}
}
function draw() {
// clear screen
ctx.clearRect(0, 0, cwidth, cheight);
// define our single path
let last_color = -1;
for (let p of particles) {
let p_color = p.color;
if( p_color !== last_color ) {
paint();
last_color = p_color;
}
p.trace(ctx);
}
paint(); // the last
function paint() {
ctx.fillStyle = colors[ last_color ];
ctx.strokeStyle = colors[ (last_color + 1) % colors .length ];
ctx.stroke();
ctx.fill();
ctx.beginPath();
}
}
window.requestAnimationFrame( animate );
<canvas id="canvas"></canvas>
И ничто не мешает вам генерировать куски из этих отсортированных частиц, поэтому это выглядит более случайным.