UNPKG

@g20/graphics

Version:
361 lines (352 loc) 10.9 kB
/** * @g20/graphics 1.0.0-alpha.46 * (c) David Geo Holmes david.geo.holmes@gmail.com * Released under the MIT License. */ 'use strict'; var core = require('@g20/core'); var reactive = require('@g20/reactive'); function default_color(attributeValue, defaultValue) { if (core.is_color(attributeValue)) { return attributeValue; } else { return defaultValue; } } function default_number(value, defaultValue) { if (typeof value === "number") { return value; } else { return defaultValue; } } const STROKE_WIDTH_CLOSED_PATH_PIXELS = 3; function default_closed_path_stroke_width(strokeWidth, owner) { if (typeof strokeWidth === "number") { return strokeWidth; } else { return STROKE_WIDTH_CLOSED_PATH_PIXELS / owner.sx; } } const cos$1 = Math.cos; const sin$1 = Math.sin; class RegularPolygon extends core.Path { #trash = []; #radius = reactive.signal(1); #twist = reactive.signal(0); #sides = reactive.signal(6); constructor(owner, options = {}) { super(owner, [], true, false, true, path_attribs_from_regular_polygon_attribs(options, owner)); if (typeof options.radius === "number") { this.radius = options.radius; } if (typeof options.sides === "number") { const MIN = 3; const MAX = 24; this.sides = Math.min(Math.max(options.sides, MIN), MAX); } if (typeof options.twist === "number") { this.twist = options.twist; } this.#trash.push(reactive.effect(() => { this.update(); })); this.flagReset(true); } dispose() { core.dispose(this.#trash); super.dispose(); } update() { update_vertices$2(this.radius, this.sides, this.twist, this.vertices); super.update(); return this; } flagReset(dirtyFlag = false) { super.flagReset(dirtyFlag); return this; } get radius() { return this.#radius.get(); } set radius(radius) { this.#radius.set(radius); } get sides() { return this.#sides.get(); } set sides(sides) { this.#sides.set(sides); } get twist() { return this.#twist.get(); } set twist(twist) { this.#twist.set(twist); } } function path_attribs_from_regular_polygon_attribs(options, owner) { const retval = { id: options.id, attitude: options.attitude, opacity: options.opacity, position: options.position, visibility: options.visibility, fillColor: default_color(options.fillColor, owner.defaults.polygon.fillColor), fillOpacity: default_number(options.fillOpacity, owner.defaults.polygon.fillOpacity), strokeColor: default_color(options.strokeColor, owner.defaults.polygon.strokeColor), strokeOpacity: default_number(options.strokeOpacity, owner.defaults.polygon.strokeOpacity), strokeWidth: default_closed_path_stroke_width(options.strokeWidth, owner) // plumb: attributes.plumb }; return retval; } function update_vertices$2(radius, sides, twist, vertices) { const N = sides + 1; if (vertices.length > N) { vertices.splice(N, vertices.length - N); } while (vertices.length < N) { vertices.push(new core.Anchor(core.G20.vector(0, 0))); } for (let i = 0; i < N; i++) { const theta = (2 * Math.PI * i) / sides + twist; const x = radius * cos$1(theta); const y = radius * sin$1(theta); const vertex = vertices.getAt(i); vertex.origin.set(x, y); vertex.command = i === 0 ? "M" : "L"; } } class RoundedRectangle extends core.Path { #trash = []; #width = reactive.signal(Math.SQRT2); #height = reactive.signal(Math.SQRT2); #radius = reactive.signal(0.2); constructor(owner, options = {}) { if (typeof options.radius === "undefined" && typeof options.width === "number" && typeof options.height === "number") { options.radius = Math.floor(Math.min(options.width, options.height) / 12); } const points = []; for (let i = 0; i < 10; i++) { const origin = core.G20.vector(0, 0); const command = i === 0 ? "M" : "C"; points.push(new core.Anchor(origin, command)); } super(owner, points, true, false, true, path_options_from_rounded_rectangle_options(options, owner)); if (typeof options.width === "number") { this.width = options.width; } if (typeof options.height === "number") { this.height = options.height; } if (typeof options.radius === "number") { this.radius = options.radius; } this.#trash.push(reactive.effect(() => { this.update(); })); } dispose() { core.dispose(this.#trash); super.dispose(); } update() { update_vertices$1(this.width, this.height, this.radius, this.vertices); super.update(); return this; } get width() { return this.#width.get(); } set width(width) { this.#width.set(width); } get height() { return this.#height.get(); } set height(height) { this.#height.set(height); } get radius() { return this.#radius.get(); } set radius(radius) { this.#radius.set(radius); } } function path_options_from_rounded_rectangle_options(options, owner) { const retval = { id: options.id, attitude: options.attitude, opacity: options.opacity, position: options.position, visibility: options.visibility, fillColor: default_color(options.fillColor, owner.defaults.polygon.fillColor), fillOpacity: default_number(options.fillOpacity, owner.defaults.polygon.fillOpacity), strokeColor: default_color(options.strokeColor, owner.defaults.polygon.strokeColor), strokeOpacity: default_number(options.strokeOpacity, owner.defaults.polygon.strokeOpacity), strokeWidth: default_closed_path_stroke_width(options.strokeWidth, owner) }; return retval; } function update_vertices$1(width, height, radius, vertices) { const rx = radius; const ry = radius; let v; const w = width / 2; const h = height / 2; v = vertices.getAt(0); v.x = -(w - rx); v.y = -h; // Upper Right Corner v = vertices.getAt(1); v.x = w - rx; v.y = -h; v.controls.a.clear(); v.controls.b.x = rx; v.controls.b.y = 0; v = vertices.getAt(2); v.x = w; v.y = -(h - ry); v.controls.b.clear(); v.controls.a.clear(); // Bottom Right Corner v = vertices.getAt(3); v.x = w; v.y = h - ry; v.controls.a.clear(); v.controls.b.x = 0; v.controls.b.y = ry; v = vertices.getAt(4); v.x = w - rx; v.y = h; v.controls.b.clear(); v.controls.a.clear(); // Bottom Left Corner v = vertices.getAt(5); v.x = -(w - rx); v.y = h; v.controls.a.clear(); v.controls.b.x = -rx; v.controls.b.y = 0; v = vertices.getAt(6); v.x = -w; v.y = h - ry; v.controls.a.clear(); v.controls.b.clear(); // Upper Left Corner v = vertices.getAt(7); v.x = -w; v.y = -(h - ry); v.controls.a.clear(); v.controls.b.x = 0; v.controls.b.y = -ry; v = vertices.getAt(8); v.x = -(w - rx); v.y = -h; v.controls.a.clear(); v.controls.b.clear(); v = vertices.getAt(9); v.copy(vertices.getAt(8)); } const cos = Math.cos, sin = Math.sin; class Star extends core.Path { #trash = []; #innerRadius = reactive.signal(0.5); #outerRadius = reactive.signal(1); #points = reactive.signal(8); #twist = reactive.signal(0); constructor(owner, options = {}) { super(owner, [], true, false, true, path_options_from_star_options(options, owner)); if (typeof options.innerRadius === "number") { this.innerRadius = options.innerRadius; } if (typeof options.outerRadius === "number") { this.outerRadius = options.outerRadius; } if (typeof options.points === "number") { this.points = options.points; } if (typeof options.twist === "number") { this.twist = options.twist; } this.#trash.push(reactive.effect(() => { this.update(); })); } dispose() { core.dispose(this.#trash); super.dispose(); } update() { update_vertices(this.points, this.innerRadius, this.outerRadius, this.twist, this.vertices); super.update(); return this; } get innerRadius() { return this.#innerRadius.get(); } set innerRadius(innerRadius) { this.#innerRadius.set(innerRadius); } get outerRadius() { return this.#outerRadius.get(); } set outerRadius(outerRadius) { this.#outerRadius.set(outerRadius); } get points() { return this.#points.get(); } set points(points) { this.#points.set(points); } get twist() { return this.#twist.get(); } set twist(twist) { this.#twist.set(twist); } } function update_vertices(points, innerRadius, outerRadius, twist, vertices) { const sides = 2 * points; const N = sides + 1; if (vertices.length > N) { vertices.splice(N, vertices.length - N); } while (vertices.length < N) { vertices.push(new core.Anchor(core.G20.vector(0, 0))); } for (let i = 0; i < N; i++) { const theta = (2 * Math.PI * i) / sides + twist; const r = i % 2 === 0 ? outerRadius : innerRadius; const x = r * cos(theta); const y = r * sin(theta); const vertex = vertices.getAt(i); vertex.origin.set(x, y); vertex.command = i === 0 ? "M" : "L"; } } function path_options_from_star_options(options, owner) { const retval = { id: options.id, attitude: options.attitude, opacity: options.opacity, position: options.position, visibility: options.visibility, fillColor: default_color(options.fillColor, owner.defaults.polygon.fillColor), fillOpacity: default_number(options.fillOpacity, owner.defaults.polygon.fillOpacity), strokeColor: default_color(options.strokeColor, owner.defaults.polygon.strokeColor), strokeOpacity: default_number(options.strokeOpacity, owner.defaults.polygon.strokeOpacity), strokeWidth: default_closed_path_stroke_width(options.strokeWidth, owner) }; return retval; } exports.RegularPolygon = RegularPolygon; exports.RoundedRectangle = RoundedRectangle; exports.Star = Star; //# sourceMappingURL=index.js.map