js-draw
Version:
Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.
101 lines (100 loc) • 3.75 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeArrowBuilder = void 0;
const math_1 = require("@js-draw/math");
const Stroke_1 = __importDefault(require("../Stroke"));
const makeSnapToGridAutocorrect_1 = __importDefault(require("./autocorrect/makeSnapToGridAutocorrect"));
/**
* Creates a stroke builder that generates arrows.
*
* Example:
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
*/
exports.makeArrowBuilder = (0, makeSnapToGridAutocorrect_1.default)((initialPoint, viewport) => {
return new ArrowBuilder(initialPoint, viewport);
});
class ArrowBuilder {
constructor(startPoint, viewport) {
this.startPoint = startPoint;
this.viewport = viewport;
this.endPoint = startPoint;
}
getLineWidth() {
return Math.max(this.endPoint.width, this.startPoint.width);
}
getBBox() {
const preview = this.buildPreview();
return preview.getBBox();
}
buildPreview() {
const lineStartPoint = this.startPoint.pos;
const endPoint = this.endPoint.pos;
const toEnd = endPoint.minus(lineStartPoint).normalized();
const arrowLength = endPoint.distanceTo(lineStartPoint);
// Ensure that the arrow tip is smaller than the arrow.
const arrowTipSize = Math.min(this.getLineWidth(), arrowLength / 2);
const startSize = this.startPoint.width / 2;
const endSize = this.endPoint.width / 2;
const arrowTipBase = endPoint.minus(toEnd.times(arrowTipSize));
// Scaled normal vectors.
const lineNormal = toEnd.orthog();
const scaledStartNormal = lineNormal.times(startSize);
const scaledBaseNormal = lineNormal.times(endSize);
const path = new math_1.Path(arrowTipBase.minus(scaledBaseNormal), [
// Stem
{
kind: math_1.PathCommandType.LineTo,
point: lineStartPoint.minus(scaledStartNormal),
},
{
kind: math_1.PathCommandType.LineTo,
point: lineStartPoint.plus(scaledStartNormal),
},
{
kind: math_1.PathCommandType.LineTo,
point: arrowTipBase.plus(scaledBaseNormal),
},
// Head
{
kind: math_1.PathCommandType.LineTo,
point: arrowTipBase.plus(lineNormal.times(arrowTipSize).plus(scaledBaseNormal)),
},
{
kind: math_1.PathCommandType.LineTo,
point: endPoint.plus(toEnd.times(endSize)),
},
{
kind: math_1.PathCommandType.LineTo,
point: arrowTipBase.plus(lineNormal.times(-arrowTipSize).minus(scaledBaseNormal)),
},
{
kind: math_1.PathCommandType.LineTo,
point: arrowTipBase.minus(scaledBaseNormal),
},
// Round all points in the arrow (to remove unnecessary decimal places)
]).mapPoints((point) => this.viewport.roundPoint(point));
const preview = new Stroke_1.default([
{
startPoint: path.startPoint,
commands: path.parts,
style: {
fill: this.startPoint.color,
},
},
]);
return preview;
}
build() {
return this.buildPreview();
}
preview(renderer) {
this.buildPreview().render(renderer);
}
addPoint(point) {
this.endPoint = point;
}
}
exports.default = ArrowBuilder;
;