@infinite-canvas-tutorial/webcomponents
Version:
WebComponents UI implementation
130 lines • 5.17 kB
JavaScript
"use strict";
/**
* Borrow from https://github.com/excalidraw/excalidraw/blob/d87620b23907cef9a119c758124569b5f44991a4/packages/excalidraw/animated-trail.ts
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnimatedTrail = void 0;
const laser_pointer_1 = require("@excalidraw/laser-pointer");
const ecs_1 = require("@infinite-canvas-tutorial/ecs");
class AnimatedTrail {
constructor(animationFrameHandler, api, options) {
this.animationFrameHandler = animationFrameHandler;
this.api = api;
this.options = options;
this.pastTrails = [];
this.animationFrameHandler.register(this, this.onFrame.bind(this));
this.trailElement = (0, ecs_1.createSVGElement)('path');
if (this.options.animateTrail) {
const { strokeDasharray = '7 7', strokeDashoffset = '10' } = this.options;
this.trailAnimation = (0, ecs_1.createSVGElement)('animate');
// TODO: make this configurable
this.trailAnimation.setAttribute('attributeName', 'stroke-dashoffset');
this.trailElement.setAttribute('stroke-dasharray', strokeDasharray);
this.trailElement.setAttribute('stroke-dashoffset', strokeDashoffset);
this.trailAnimation.setAttribute('from', '0');
this.trailAnimation.setAttribute('to', `-14`);
this.trailAnimation.setAttribute('dur', '0.3s');
this.trailElement.appendChild(this.trailAnimation);
}
}
get hasCurrentTrail() {
return !!this.currentTrail;
}
hasLastPoint(x, y) {
if (this.currentTrail) {
const len = this.currentTrail.originalPoints.length;
return (this.currentTrail.originalPoints[len - 1][0] === x &&
this.currentTrail.originalPoints[len - 1][1] === y);
}
return false;
}
start(container) {
if (container) {
this.container = container;
}
if (this.trailElement.parentNode !== this.container && this.container) {
this.container.appendChild(this.trailElement);
}
this.animationFrameHandler.start(this);
}
stop() {
var _a;
this.animationFrameHandler.stop(this);
if (this.trailElement.parentNode === this.container) {
(_a = this.container) === null || _a === void 0 ? void 0 : _a.removeChild(this.trailElement);
}
}
startPath(x, y) {
this.currentTrail = new laser_pointer_1.LaserPointer(this.options);
this.currentTrail.addPoint([x, y, performance.now()]);
this.update();
}
addPointToPath(x, y) {
if (this.currentTrail) {
this.currentTrail.addPoint([x, y, performance.now()]);
this.update();
}
}
endPath() {
if (this.currentTrail) {
this.currentTrail.close();
this.currentTrail.options.keepHead = false;
this.pastTrails.push(this.currentTrail);
this.currentTrail = undefined;
this.update();
}
}
getCurrentTrail() {
return this.currentTrail;
}
clearTrails() {
this.pastTrails = [];
this.currentTrail = undefined;
this.update();
}
update() {
this.start();
if (this.trailAnimation) {
this.trailAnimation.setAttribute('begin', 'indefinite');
this.trailAnimation.setAttribute('repeatCount', 'indefinite');
}
}
onFrame() {
var _a, _b, _c, _d;
const paths = [];
for (const trail of this.pastTrails) {
paths.push(this.drawTrail(trail));
}
if (this.currentTrail) {
const currentPath = this.drawTrail(this.currentTrail);
paths.push(currentPath);
}
this.pastTrails = this.pastTrails.filter((trail) => {
return trail.getStrokeOutline().length !== 0;
});
if (paths.length === 0) {
this.stop();
}
const svgPaths = paths.join(' ').trim();
this.trailElement.setAttribute('d', svgPaths);
if (this.trailAnimation) {
this.trailElement.setAttribute('fill', ((_a = this.options.fill) !== null && _a !== void 0 ? _a : (() => 'black'))(this));
this.trailElement.setAttribute('stroke', ((_b = this.options.stroke) !== null && _b !== void 0 ? _b : (() => 'black'))(this));
this.trailElement.setAttribute('fill-opacity', ((_c = this.options.fillOpacity) !== null && _c !== void 0 ? _c : (() => 0.5))(this).toString());
}
else {
this.trailElement.setAttribute('fill', ((_d = this.options.fill) !== null && _d !== void 0 ? _d : (() => 'black'))(this));
}
}
drawTrail(trail) {
const _stroke = trail.getStrokeOutline(trail.options.size).map(([x, y]) => {
return [x, y];
});
const stroke = this.trailAnimation
? _stroke.slice(0, _stroke.length / 2)
: _stroke;
return (0, ecs_1.getSvgPathFromStroke)(stroke, true);
}
}
exports.AnimatedTrail = AnimatedTrail;
//# sourceMappingURL=animated-trail.js.map