// SPDX-FileCopyrightText: Chris Pressey, the original author of this work, has dedicated it to the public domain.
// For more information, please refer to <https://unlicense.org/>
// SPDX-License-Identifier: Unlicense
Rectangle = function() {
this.init = function(cfg) {
this.x = cfg.x;
this.y = cfg.y;
this.width = cfg.width;
this.height = cfg.height;
this.dx = cfg.dx || 0;
this.dy = cfg.dy || 0;
this.fillStyle = cfg.fillStyle || "green";
this.visible = (cfg.visible === undefined ? true : (!!cfg.visible));
this._isBeingDragged = false;
this.relativeTo = cfg.relativeTo;
return this;
};
this.getX = function() {
if (this.relativeTo !== null) {
return this.x + this.relativeTo.getX();
} else {
return this.x;
}
};
this.getCenterX = function() {
return this.getX() + this.getWidth() / 2;
};
this.getLeftX = function() {
return this.x - this.width / 2;
};
this.getRightX = function() {
return this.x + this.width / 2;
};
this.getY = function() {
if (this.relativeTo !== null) {
return this.y + this.relativeTo.getY();
} else {
return this.y;
}
};
this.getCenterY = function() {
return this.getY() + this.getHeight() / 2;
};
this.getTopY = function() {
return this.y - this.height / 2;
};
this.getBottomY = function() {
return this.y + this.height / 2;
};
this.getWidth = function() {
return this.width;
};
this.getHeight = function() {
return this.height;
};
this.move = function(x, y) {
this.x += this.dx;
this.y += this.dy;
this.onmove();
};
this.onmove = function() {
var x = this.x;
var y = this.y;
if (this.scrawlOn !== undefined) {
if (this.lastX !== undefined) {
var ctx = this.scrawlOn;
ctx.beginPath();
ctx.strokeStyle = "rgba(0, 0, 0, 0.5)";
ctx.lineWidth = 2;
ctx.moveTo(this.lastX, this.lastY);
ctx.lineTo(this.getCenterX(), this.getCenterY());
ctx.stroke();
}
this.lastX = this.getCenterX();
this.lastY = this.getCenterY();
}
if (x < 0 || x + this.getWidth() > this.relativeTo.getWidth()) {
this.dx *= -1;
}
if (y < 0 || y + this.getHeight() > this.relativeTo.getHeight()) {
this.dy *= -1;
}
};
this.draw = function(ctx) {
if (this.visible) {
ctx.fillStyle = this.fillStyle;
ctx.fillRect(
this.getX(), this.getY(), this.getWidth(), this.getHeight()
);
}
};
};
Hypongtrochoid = function() {
var canvas;
var overlayCanvas;
var ctx;
var overlayCtx;
var turbo = false;
var rectangles;
var blueRectangle;
var redRectangle;
var yellowRectangle;
this.setShowBlue = function(b) {
blueRectangle.visible = b;
};
this.setShowRed = function(b) {
redRectangle.visible = b;
};
this.setShowYellow = function(b) {
yellowRectangle.visible = b;
};
this.setTurbo = function(b) {
turbo = b;
};
this.draw = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var j = 0; j < rectangles.length; j++) {
rectangles[j].draw(ctx);
}
};
this.update = function() {
var n = turbo ? 10 : 1;
for (var i = 0; i < n; i++) {
for (var j = 0; j < rectangles.length; j++) {
rectangles[j].move();
}
}
};
this.init = function(config) {
canvas = config.mainCanvas;
overlayCanvas = config.overlayCanvas;
ctx = canvas.getContext('2d');
overlayCtx = overlayCanvas.getContext('2d');
var outside = new Rectangle();
outside.init({
x: 0,
y: 0,
dx: 0,
dy: 0,
width: canvas.width,
height: canvas.height,
fillStyle: '',
relativeTo: null
});
blueRectangle = new Rectangle();
blueRectangle.init({
x: 50,
y: 50,
dx: -1,
dy: 1,
width: 200,
height: 200,
fillStyle: 'blue',
relativeTo: outside
});
redRectangle = new Rectangle();
redRectangle.init({
x: 50,
y: 50,
dx: -0.75,
dy: 0.75,
width: 50,
height: 50,
fillStyle: 'red',
relativeTo: blueRectangle
});
yellowRectangle = new Rectangle();
yellowRectangle.init({
x: 10,
y: 10,
dx: 0.5,
dy: -0.5,
width: 10,
height: 10,
fillStyle: 'yellow',
relativeTo: redRectangle
});
yellowRectangle.scrawlOn = overlayCtx;
rectangles = [
blueRectangle,
redRectangle,
yellowRectangle
];
var handleFrame;
var $this = this;
handleFrame = function() {
$this.update();
$this.draw();
requestAnimationFrame(handleFrame);
}
// start the animation.
requestAnimationFrame(handleFrame);
};
}