@avolutions/canvas-painter
Version:
CanvasPainter.js is a simple yet powerful JavaScript library for drawing basic shapes (rectangles, circles, etc.) on HTML5 Canvas with ease. Perfect for creating 2D graphics in your web projects.
216 lines (215 loc) • 8.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Rectangle = void 0;
const Angle_js_1 = require("../types/Angle.js");
const Point_js_1 = require("../types/Point.js");
const RectangleDefinition_js_1 = require("../definitions/RectangleDefinition.js");
const Shape_js_1 = require("./Shape.js");
const RectangleStyle_js_1 = require("../styles/RectangleStyle.js");
const RectangleOptions_js_1 = require("../options/RectangleOptions.js");
/**
* Class representing a Rectangle, extending the Shape class with a RectangleDefinition.
* Provides functionality for rendering, resizing, moving, and rotating the rectangle.
*/
class Rectangle extends Shape_js_1.Shape {
/**
* Constructs a new Rectangle instance.
*
* @param x - The x-coordinate of the rectangle's position.
* @param y - The y-coordinate of the rectangle's position.
* @param width - The width of the rectangle.
* @param height - The height of the rectangle.
* @param rotation - The initial rotation of the rectangle in degrees clockwise.
* @param style - The style options for the rectangle.
* @param options - The configuration options for the rectangle.
*/
constructor(x, y, width, height, rotation = 0, style, options) {
// Create a RectangleDefinition using the provided parameters
const rectangleDefinition = new RectangleDefinition_js_1.RectangleDefinition(new Point_js_1.Point(x, y), width, height, new Angle_js_1.Angle(rotation));
super(rectangleDefinition, new RectangleStyle_js_1.RectangleStyle(style), new RectangleOptions_js_1.RectangleOptions(options));
}
// Getters
/**
* Gets the width of the rectangle.
* @returns The width of the rectangle.
*/
get width() {
return this._definition.width;
}
/**
* Gets the height of the rectangle.
* @returns The height of the rectangle.
*/
get height() {
return this._definition.height;
}
/**
* Gets the position (Point) of the rectangle.
* @returns The position of the rectangle.
*/
get position() {
return this._definition.position;
}
/**
* Gets the angle of the rectangle.
* @returns The angle (rotation) of the rectangle.
*/
get angle() {
return this._definition.angle;
}
/**
* Gets the rotation of the rectangle in degrees.
* @returns The rotation of the rectangle.
*/
get rotation() {
return this._definition.angle.degrees;
}
// Setters
/**
* Sets the width of the rectangle.
* @param width - The new width of the rectangle.
*/
set width(width) {
this._definition.width = width;
}
/**
* Sets the height of the rectangle.
* @param height - The new height of the rectangle.
*/
set height(height) {
this._definition.height = height;
}
/**
* Sets the position (Point) of the rectangle.
* @param position - The new position of the rectangle.
*/
set position(position) {
this._definition.position = position;
}
/**
* Sets the rotation of the rectangle.
* @param rotation - The new rotation of the rectangle.
*/
set rotation(rotation) {
this._definition.angle.degrees = rotation;
}
/**
* Updates the size of the rectangle by setting new width and height values.
*
* @param width - The new width of the rectangle.
* @param height - The new height of the rectangle.
*/
setSize(width, height) {
this.width = width;
this.height = height;
}
/**
* Resizes the rectangle by adjusting the current width and height by delta values.
*
* @param deltaWidth - The change in width.
* @param deltaHeight - The change in height.
*/
resize(deltaWidth = 0, deltaHeight = 0) {
this.width += deltaWidth;
this.height += deltaHeight;
}
/**
* Moves the rectangle by adjusting the current position by delta values.
*
* @param deltaX - The change in the x-coordinate.
* @param deltaY - The change in the y-coordinate.
*/
move(deltaX = 0, deltaY = 0) {
this.position.move(deltaX, deltaY);
}
/**
* Rotates the rectangle by adjusting its current angle.
*
* @param deltaRotation - The amount to adjust the rectangle's rotation, in degrees.
*/
rotate(deltaRotation) {
this.angle.adjustBy(deltaRotation);
}
/**
* Gets the top-left position of the rectangle.
* If the rectangle is centered, it adjusts based on the width and height.
* @returns The top-left position of the rectangle.
*/
getTopLeftPosition() {
if (this.options.centered) {
return new Point_js_1.Point(this._definition.position.x - this._definition.width / 2, this._definition.position.y - this._definition.height / 2);
}
return new Point_js_1.Point(this._definition.position.x, this._definition.position.y);
}
/**
* Renders the rectangle on the canvas using the provided 2D rendering context.
*
* The rectangle will be rendered with its current position, size, and rotation.
*
* @param context - The 2D rendering context of the canvas where the rectangle will be drawn.
*/
render(context) {
context.save(); // Save the current canvas state
// Set rectangle specific styles
context.fillStyle = this.stateStyle.color;
const topLeft = this.getTopLeftPosition();
// Rotate
if (this.angle.degrees !== 0) {
// Translate to the rectangle's position and apply rotation
context.translate(this._definition.position.x, this._definition.position.y);
context.rotate(this._definition.angle.radians);
// Translate back if centered
if (this.options.centered) {
context.translate(-this._definition.width / 2, -this._definition.height / 2);
}
// Because we are in translated context
topLeft.x = 0;
topLeft.y = 0;
}
context.fillRect(topLeft.x, topLeft.y, this._definition.width, this._definition.height);
// Draw border for rectangle
if (this.hasBorder()) {
context.strokeStyle = this.stateStyle.borderColor;
context.lineWidth = this.stateStyle.borderWidth;
context.strokeRect(topLeft.x, topLeft.y, this._definition.width, this._definition.height);
}
context.restore(); // Restore the canvas state to before the transformations
}
/**
* Determines if the mouse is currently over the shape.
*
* @param mousePosition - The current mouse position.
* @returns True if the mouse is over the shape, false otherwise.
*/
isMouseOver(mousePosition) {
// Translate the mouse position based on the rectangle's position
const x = mousePosition.x - this._definition.position.x;
const y = mousePosition.y - this._definition.position.y;
// If the rectangle is rotated, apply the reverse rotation
const angle = -this._definition.angle.radians;
const sin = Math.sin(angle);
const cos = Math.cos(angle);
const rotatedX = x * cos - y * sin;
const rotatedY = x * sin + y * cos;
// If the rectangle is centered, adjust coordinates accordingly
const offsetX = this.options.centered ? -this._definition.width / 2 : 0;
const offsetY = this.options.centered ? -this._definition.height / 2 : 0;
// Calculate half of the border width for both inward and outward bounds expansion
const borderWidth = this.hasBorder() ? this.stateStyle.borderWidth / 2 : 0;
// Check if the rotated mouse coordinates are within the rectangle's bounds,
// taking into account half the border width on each side
return (rotatedX >= offsetX - borderWidth &&
rotatedX <= offsetX + this._definition.width + borderWidth &&
rotatedY >= offsetY - borderWidth &&
rotatedY <= offsetY + this._definition.height + borderWidth);
}
/**
* Handles the drag operation by applying the given delta to the current position.
*
* @param delta - The change in position represented as a `Point`.
*/
onDrag(delta) {
this.move(delta.x, delta.y);
}
}
exports.Rectangle = Rectangle;