@g20/graphics
Version:
361 lines (352 loc) • 10.9 kB
JavaScript
/**
* @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