diff --git a/lib/colors.ts b/lib/colors.ts index bd469b2..76881c9 100644 --- a/lib/colors.ts +++ b/lib/colors.ts @@ -1,10 +1,16 @@ +import type { AttachmentPointType } from "./specs"; + export const STROKE_REPLACEMENT_COLOR = "#000000"; export const FILL_REPLACEMENT_COLOR = "#ffffff"; -export const TAIL_ATTACHMENT_COLOR = "#ff0000"; -export const LEG_ATTACHMENT_COLOR = "#ffff00"; -export const ARM_ATTACHMENT_COLOR = "#00ff00"; -export const HORN_ATTACHMENT_COLOR = "#00ffff"; -export const CROWN_ATTACHMENT_COLOR = "#0000ff"; +export const ATTACHMENT_POINT_COLORS: { + [key in AttachmentPointType]: string; +} = { + tail: "#ff0000", + leg: "#ffff00", + arm: "#00ff00", + horn: "#00ffff", + crown: "#0000ff", +}; export const NESTING_BOUNDING_BOX_COLOR = "#ff00ff"; diff --git a/lib/pages/vocabulary-page.tsx b/lib/pages/vocabulary-page.tsx index 2db64fe..da42b3f 100644 --- a/lib/pages/vocabulary-page.tsx +++ b/lib/pages/vocabulary-page.tsx @@ -3,7 +3,7 @@ import { BBox } from "../../vendor/bezier-js"; import { dilateBoundingBox, getBoundingBoxSize } from "../bounding-box"; import { FILL_REPLACEMENT_COLOR, STROKE_REPLACEMENT_COLOR } from "../colors"; import * as colors from "../colors"; -import { PointWithNormal, Specs } from "../specs"; +import { iterAttachmentPoints, AttachmentPoint, Specs } from "../specs"; import type { SvgSymbolData, SvgSymbolElement } from "../vocabulary"; import { SvgVocabulary } from "../svg-vocabulary"; @@ -61,36 +61,28 @@ const ATTACHMENT_POINT_NORMAL_LENGTH = 50; const ATTACHMENT_POINT_NORMAL_STROKE = 4; -const AttachmentPoints: React.FC<{ - color: string; - points: PointWithNormal[]; -}> = (props) => ( - <> - {props.points.map((pwn, i) => { - const { x, y } = pwn.point; - const x2 = x + pwn.normal.x * ATTACHMENT_POINT_NORMAL_LENGTH; - const y2 = y + pwn.normal.y * ATTACHMENT_POINT_NORMAL_LENGTH; - return ( - - - - - ); - })} - -); +const VisibleAttachmentPoint: React.FC<{ + point: AttachmentPoint; +}> = ({ point: ap }) => { + const { x, y } = ap.point; + const x2 = x + ap.normal.x * ATTACHMENT_POINT_NORMAL_LENGTH; + const y2 = y + ap.normal.y * ATTACHMENT_POINT_NORMAL_LENGTH; + const color = colors.ATTACHMENT_POINT_COLORS[ap.type]; + + return ( + <> + + + + ); +}; const BoundingBoxes: React.FC<{ fill: string; bboxes: BBox[] }> = (props) => ( <> @@ -113,36 +105,9 @@ const BoundingBoxes: React.FC<{ fill: string; bboxes: BBox[] }> = (props) => ( const SvgSymbolSpecs: React.FC<{ specs: Specs }> = ({ specs }) => { return ( <> - {specs.tail && ( - - )} - {specs.leg && ( - - )} - {specs.arm && ( - - )} - {specs.horn && ( - - )} - {specs.crown && ( - - )} + {Array.from(iterAttachmentPoints(specs)).map((point, i) => ( + + ))} {specs.nesting && ( ; + +export type AttachmentPointType = keyof AttachmentPointSpecs; + +export type AttachmentPoint = PointWithNormal & { + type: AttachmentPointType; +}; + +export const ATTACHMENT_POINT_TYPES: AttachmentPointType[] = [ + "tail", + "leg", + "arm", + "horn", + "crown", +]; + +export function* iterAttachmentPoints(specs: Specs): Iterable { + for (let type of ATTACHMENT_POINT_TYPES) { + const points = specs[type]; + if (points) { + for (let point of points) { + yield { ...point, type }; + } + } + } +} + const NUM_ARROW_POINTS = 4; const ARROW_TOP_POINT_IDX = 0; const ARROW_BOTTOM_POINT_IDX = 2; @@ -76,38 +107,28 @@ function concat(first: T[] | undefined, second: T[]): T[] { return first ? [...first, ...second] : second; } +const ATTACHMENT_COLOR_MAP = new Map( + ATTACHMENT_POINT_TYPES.map((type) => [ + colors.ATTACHMENT_POINT_COLORS[type], + type, + ]) +); + function updateSpecs(fill: string, path: string, specs: Specs): Specs { - switch (fill) { - case colors.TAIL_ATTACHMENT_COLOR: - return { - ...specs, - tail: concat(specs.tail, getArrowPoints(path)), - }; - case colors.LEG_ATTACHMENT_COLOR: - return { - ...specs, - leg: concat(specs.leg, getArrowPoints(path)), - }; - case colors.ARM_ATTACHMENT_COLOR: - return { - ...specs, - arm: concat(specs.arm, getArrowPoints(path)), - }; - case colors.HORN_ATTACHMENT_COLOR: - return { - ...specs, - horn: concat(specs.horn, getArrowPoints(path)), - }; - case colors.CROWN_ATTACHMENT_COLOR: - return { - ...specs, - crown: concat(specs.crown, getArrowPoints(path)), - }; - case colors.NESTING_BOUNDING_BOX_COLOR: - return { - ...specs, - nesting: concat(specs.nesting, getBoundingBoxes(path)), - }; + const attachmentType = ATTACHMENT_COLOR_MAP.get(fill); + + if (attachmentType) { + return { + ...specs, + [attachmentType]: concat(specs[attachmentType], getArrowPoints(path)), + }; + } + + if (fill === colors.NESTING_BOUNDING_BOX_COLOR) { + return { + ...specs, + nesting: concat(specs.nesting, getBoundingBoxes(path)), + }; } throw new Error(`Not sure what to do with specs path with fill "${fill}"!`); diff --git a/package.json b/package.json index 2d81519..0b4d6aa 100644 --- a/package.json +++ b/package.json @@ -27,5 +27,8 @@ "react": "^17.0.1", "react-dom": "^17.0.1", "typescript": "^4.1.3" - } + }, + "browserslist": [ + "since 2017-06" + ] }