You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
5.1 KiB
171 lines
5.1 KiB
import Rx, { Observable } from 'rxjs';
|
|
// import DOM from './dom';
|
|
import { RAD } from './enums';
|
|
import Store from './store';
|
|
|
|
const random = {
|
|
bool: () => Math.random() < 0.5,
|
|
num: (min, max) => min + Math.round(Math.random() * max)
|
|
}
|
|
|
|
function moveArc(arc, newRadius) {
|
|
const r0 = arc.r;
|
|
const r1 = newRadius;
|
|
|
|
// Moves arc center to new radius while keeping theta constant.
|
|
arc.x -= (r1 - r0) * Math.cos(arc.t);
|
|
arc.y += (r1 - r0) * Math.sin(arc.t);
|
|
arc.r = r1;
|
|
|
|
return arc;
|
|
}
|
|
|
|
function changeDirection(arc) {
|
|
arc.t = (arc.t + Math.PI) % RAD.t360;
|
|
arc.x -= (2 * arc.r) * Math.cos(arc.t);
|
|
arc.y += (2 * arc.r) * Math.sin(arc.t);
|
|
|
|
return arc;
|
|
}
|
|
|
|
// function transformVisionGrid(store) {
|
|
// const {
|
|
// arc,
|
|
// clockwise,
|
|
// particle.x,
|
|
// particle.y,
|
|
// radius,
|
|
// } = store.get();
|
|
//
|
|
// const r0 = Math.min(arc.t, arc.t - Math.PI);
|
|
// const r1 = Math.max(arc.t, arc.t + Math.PI);
|
|
//
|
|
// const gridX = particle.x - particle.x % 5;
|
|
// const gridY = particle.y - particle.y % 5;
|
|
//
|
|
// visionGridPoints.forEach(({ x, y, alpha, div }, i) => {
|
|
// if (alpha >= 0 && alpha <= r0) {
|
|
// div.style.display = (clockwise ? 'none' : 'block');
|
|
// // div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
|
|
// } else if (alpha >= arc.t && alpha <= r1) {
|
|
// div.style.display = (clockwise ? 'none' : 'block');
|
|
// // div.className = (clockwise ? 'anim3-dot removed' : 'anim3-dot');
|
|
// } else {
|
|
// div.style.display = (clockwise ? 'block' : 'none');
|
|
// // div.className = (clockwise ? 'anim3-dot' : 'anim3-dot removed');
|
|
// }
|
|
//
|
|
// div.style.left = `${x + gridX}px`;
|
|
// div.style.top = `${-y + gridY}px`;
|
|
// });
|
|
// }
|
|
//
|
|
|
|
function Particle(container, bounds, options = {}) {
|
|
this.container = container;
|
|
this.bounds = bounds;
|
|
|
|
this.node = document.createElement('div');
|
|
this.node.className = 'particle has-vision';
|
|
|
|
this.circle = document.createElement('div');
|
|
this.circle.className = 'particle-movement-circle';
|
|
|
|
this.container.appendChild(this.node);
|
|
this.container.appendChild(this.circle);
|
|
|
|
this.arc = {
|
|
r: random.num(100, 200),
|
|
t: random.num(0, RAD.t360),
|
|
x: random.num(0, bounds.width),
|
|
y: random.num(0, bounds.height)
|
|
}
|
|
|
|
this.particle = {
|
|
clockwise: random.bool(),
|
|
speed: 4,
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
|
|
this.interval = 0;
|
|
|
|
this.updateOptions(options);
|
|
this.nextFrame();
|
|
|
|
};
|
|
|
|
Particle.prototype.nextFrame = function() {
|
|
this.move();
|
|
this.repaintParticle();
|
|
this.repaintCircle();
|
|
}
|
|
|
|
Particle.prototype.updateOptions = function(options) {
|
|
this.particleImage = 'seahorse';
|
|
this.randomlyChangeRadius = (new Boolean(options.randomlyChangeRadius)) || true;
|
|
this.randomlyChangeRotation = (new Boolean(options.randomlyChangeRotation)) || true;
|
|
this.showCircle = (new Boolean(options.showCircle)) || false;
|
|
this.showVision = (new Boolean(options.showVision)) || false;
|
|
}
|
|
|
|
Particle.prototype.repaintParticle = function() {
|
|
const rad = this.particle.clockwise
|
|
? RAD.t180 - this.arc.t
|
|
: RAD.t360 - this.arc.t;
|
|
|
|
this.node.style.left = `${this.particle.x}px`;
|
|
this.node.style.top = `${this.particle.y}px`;
|
|
this.node.style.transform = `rotate(${rad}rad)`;
|
|
}
|
|
|
|
Particle.prototype.repaintCircle = function() {
|
|
this.circle.style.width = `${2 * this.arc.r}px`;
|
|
this.circle.style.height = `${2 * this.arc.r}px`;
|
|
this.circle.style.left = `${this.arc.x - this.arc.r}px`;
|
|
this.circle.style.top = `${this.arc.y - this.arc.r}px`;
|
|
|
|
this.circle.style.borderRadius = `${this.arc.r}px`;
|
|
}
|
|
|
|
Particle.prototype.move = function(store) {
|
|
// Randomly change radius and rotation direction.
|
|
this.interval -= 1;
|
|
if (this.interval <= 0) {
|
|
this.interval = random.num(50, 100);
|
|
this.arc = moveArc(this.arc, random.num(100, 200));
|
|
|
|
if (random.bool()) {
|
|
this.particle.clockwise = !this.particle.clockwise;
|
|
this.arc = changeDirection(this.arc);
|
|
}
|
|
}
|
|
|
|
// Ensure constant velocity and theta between 0 and 2π.
|
|
const delta = this.particle.speed / this.arc.r;
|
|
this.arc.t += (this.particle.clockwise ? -delta : +delta);
|
|
this.arc.t = (this.arc.t > 0 ? this.arc.t % RAD.t360 : RAD.t360 - this.arc.t);
|
|
|
|
this.particle.x = this.arc.x + this.arc.r * Math.cos(this.arc.t);
|
|
this.particle.y = this.arc.y - this.arc.r * Math.sin(this.arc.t);
|
|
|
|
// Overflow.
|
|
if (this.particle.x < 0) {
|
|
this.particle.x += this.bounds.width;
|
|
this.arc.x += this.bounds.width
|
|
} else if (this.particle.x > this.bounds.width) {
|
|
this.particle.x -= this.bounds.width;
|
|
this.arc.x -= this.bounds.width
|
|
}
|
|
|
|
if (this.particle.y < 0) {
|
|
this.particle.y += this.bounds.height; // TODO size of area
|
|
this.arc.y += this.bounds.height
|
|
} else if (this.particle.y > this.bounds.height) {
|
|
this.particle.y -= this.bounds.height;
|
|
this.arc.y -= this.bounds.height
|
|
}
|
|
}
|
|
|
|
|
|
export default Particle;
|
|
|