js-draw
Version:
Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.
65 lines (64 loc) • 2.41 kB
JavaScript
import { Mat33, Rect2, Path } from '@js-draw/math';
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
import Stroke from '../Stroke.mjs';
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
/**
* Creates filled rectangles with sharp corners.
*
* Example:
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
*/
export const makeFilledRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
return new RectangleBuilder(initialPoint, true, viewport);
});
/**
* Creates outlined rectangles with sharp corners.
*
* Example:
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
*/
export const makeOutlinedRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
return new RectangleBuilder(initialPoint, false, viewport);
});
export default class RectangleBuilder {
constructor(startPoint, filled, viewport) {
this.startPoint = startPoint;
this.filled = filled;
this.viewport = viewport;
// Initially, the start and end points are the same.
this.endPoint = startPoint;
}
getBBox() {
const preview = this.buildPreview();
return preview.getBBox();
}
buildPreview() {
const canvasAngle = this.viewport.getRotationAngle();
const rotationMat = Mat33.zRotation(-canvasAngle);
// Adjust startPoint and endPoint such that applying [rotationMat] to them
// brings them to this.startPoint and this.endPoint.
const startPoint = rotationMat.inverse().transformVec2(this.startPoint.pos);
const endPoint = rotationMat.inverse().transformVec2(this.endPoint.pos);
const rect = Rect2.fromCorners(startPoint, endPoint);
const path = Path.fromRect(rect, this.filled ? null : this.endPoint.width)
.transformedBy(
// Rotate the canvas rectangle so that its rotation matches the screen
rotationMat)
.mapPoints((point) => this.viewport.roundPoint(point));
const preview = new Stroke([
pathToRenderable(path, {
fill: this.endPoint.color,
}),
]);
return preview;
}
build() {
return this.buildPreview();
}
preview(renderer) {
this.buildPreview().render(renderer);
}
addPoint(point) {
this.endPoint = point;
}
}