61 lines
1.8 KiB
JavaScript
61 lines
1.8 KiB
JavaScript
import {Polygon as SVGPolygon} from '@svgdotjs/svg.js';
|
|
import {Geo} from './Geo.js';
|
|
import {TAU} from '../shapes/helpers.js';
|
|
|
|
/**
|
|
* Creates an SVG oval shape from Tldraw v2 JSON data.
|
|
*
|
|
* @class Oval
|
|
* @extends {Geo}
|
|
*/
|
|
export class Oval extends Geo {
|
|
/**
|
|
* Draws an oval shape on the SVG canvas.
|
|
* @return {G} Returns the SVG group element containing the oval.
|
|
* @see {@link https://github.com/tldraw/tldraw/blob/main/packages/editor/src/lib/primitives/geometry/Stadium2d.ts} Adapted from Tldraw.
|
|
*/
|
|
draw() {
|
|
const w = Math.max(1, this.w);
|
|
const h = Math.max(1, this.h + this.growY);
|
|
const cx = w / 2;
|
|
const cy = h / 2;
|
|
|
|
const len = 25; // Number of vertices to use for the oval
|
|
const points = Array(len * 2 - 2).fill(null).map(() => []);
|
|
|
|
if (h > w) {
|
|
for (let i = 0; i < len - 1; i++) {
|
|
const t1 = -(TAU / 2) + ((TAU / 2) * i) / (len - 2);
|
|
const t2 = ((TAU / 2) * i) / (len - 2);
|
|
points[i] = [cx + cx * Math.cos(t1), cx + cx * Math.sin(t1)];
|
|
points[i + (len - 1)] = [cx + cx * Math.cos(t2),
|
|
h - cx + cx * Math.sin(t2)];
|
|
}
|
|
} else {
|
|
for (let i = 0; i < len - 1; i++) {
|
|
const t1 = -(TAU / 4) + (TAU / 2 * i) / (len - 2);
|
|
const t2 = (TAU / 4) + (TAU / 2 * -i) / (len - 2);
|
|
points[i] = [w - cy + cy * Math.cos(t1), h - cy + cy * Math.sin(t1)];
|
|
points[i + (len - 1)] = [cy - cy * Math.cos(t2),
|
|
h - cy + cy * Math.sin(t2)];
|
|
}
|
|
}
|
|
|
|
const formattedPoints = points.map((p) => p.join(',')).join(' ');
|
|
|
|
const ovalGroup = this.shapeGroup;
|
|
const oval = new SVGPolygon({
|
|
'points': formattedPoints,
|
|
'stroke': this.shapeColor,
|
|
'stroke-width': this.thickness,
|
|
'style': this.dasharray,
|
|
});
|
|
|
|
this.setFill(oval);
|
|
ovalGroup.add(oval);
|
|
this.drawLabel(ovalGroup);
|
|
|
|
return ovalGroup;
|
|
}
|
|
}
|