UNPKG

@linkurious/ogma-annotations

Version:
639 lines (560 loc) 19.1 kB
import { BBox } from 'geojson'; import { default as default_2 } from 'eventemitter3'; import { default as default_3 } from '@linkurious/ogma'; import { Feature } from 'geojson'; import { FeatureCollection } from 'geojson'; import { Geometry } from 'geojson'; import { GeometryObject } from 'geojson'; import { LineString } from 'geojson'; import { Options } from '@linkurious/ogma'; import { Overlay } from '@linkurious/ogma'; import { Point as Point_2 } from '@linkurious/ogma'; import { Polygon } from 'geojson'; import { Position } from 'geojson'; import { SVGLayer } from '@linkurious/ogma'; export declare type Annotation = Arrow | Text_2; export declare interface AnnotationCollection extends FeatureCollection { features: (Arrow | Text_2)[]; } export declare interface AnnotationFeature<G extends GeometryObject = GeometryObject, P = AnnotationProps> extends Feature<G, P> { id: string | number; } export declare type AnnotationOptions = { handleSize: number; placeholder: string; }; export declare interface AnnotationProps { type: AnnotationType; style?: unknown; } declare type AnnotationType = "arrow" | "text"; export declare type Arrow = AnnotationFeature<LineString, ArrowProperties>; export declare interface ArrowProperties extends AnnotationProps { type: "arrow"; style?: ArrowStyles; link?: Partial<Record<Side, ExportedLink>>; } /** * @class Arrows * Draw and edit arrows */ export declare class Arrows extends Editor<Arrow> { private draggedHandle; private start; private end; private arrow; private startX; private startY; private minArrowHeight; private maxArrowHeight; private handles; constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "arrowHandleSize" | "maxArrowHeight" | "minArrowHeight">); private onHandleMouseDown; /** * Start drawing a new arrow, it will also be added as a new annotation * @param x * @param y * @param arrow */ startDrawing(x: number, y: number, arrow?: Arrow): void; cancelDrawing(): void; private startDragging; private onMouseUp; private onMouseMove; detect(point: Point_2, margin?: number): Arrow | undefined; refreshEditor(): void; getDefaultOptions(): Arrow; draw(svg: SVGSVGElement): void; refreshDrawing(): void; destroy(): void; } export declare interface ArrowStyles extends StrokeOptions { tail?: Extremity; head?: Extremity; } /** * Bounding box object, with the following properties: * - [0]: min x * - [1]: min y * - [2]: max x * - [3]: max y */ export declare type Bounds = [number, number, number, number]; export declare function clientToContainerPosition(evt: { clientX: number; clientY: number; }, container?: HTMLElement | null): { x: number; y: number; }; export declare function colorToRgba(color: string, alpha: number): string; export declare class Control extends default_2<FeatureEvents> { private arrows; private texts; private links; private layer; private annotations; private ogma; private options; private selected; private updateTimeout; private hoveredNode; private dragged; private textToMagnet; private activeLinks; constructor(ogma: default_3, options?: Partial<ControllerOptions>); private _render; private _onFeatureDrag; private _onFeatureDragEnd; private _onFeatureDragStart; private _onNodesDragStart; private _onNodesDrag; private _onLayoutEnd; private _moveNodes; private _snapToText; private _findAndSnapToNode; private _snapToNode; private _onAdded; private _onRemoved; private _onUnselect; private _onSelect; private refreshTextLinks; /** * @returns the currently selected annotation */ getSelected(): Annotation | null; private findMagnetPoint; /** * Set the options for the controller * @param options new Options * @returns the updated options */ setOptions(options?: Partial<ControllerOptions>): ControllerOptions; /** * Selects the annotation with the given id * @param id the id of the annotation to select */ select(id: Id): this; /** * Unselects the currently selected annotation */ unselect(): this; /** * Add an annotation to the controller * @param annotation The annotation to add */ add(annotation: Arrow | Text_2 | AnnotationCollection): this; /** * Remove an annotation or an array of annotations from the controller * @param annotation The annotation(s) to remove */ remove(annotation: Arrow | Text_2 | AnnotationCollection): this; private loadLink; /** * Start adding an arrow (add it, and give control to the user) * @param x coord of the first point * @param y coord of the first point * @param arrow The arrow to add */ startArrow(x: number, y: number, arrow?: Arrow): void; /** * Start adding a text (add it, and give control to the user) * @param x coord of the top left point * @param y coord of the top left point * @param text The text to add */ startText(x: number, y: number, text?: Text_2): void; /** * Cancel drawing on the current frame */ cancelDrawing(): void; /** * Triggers the update event on the annotation * @param annotation The annotation updated */ onUpdate: (annotation: Annotation) => void; private _onUpdate; /** * Update the style of the annotation with the given id * @param id The id of the annotation to update * @param style The new style */ updateStyle<A extends Annotation>(id: Id, style: A["properties"]["style"]): this; setScale(id: Id, scale: number, ox: number, oy: number): this; /** * @returns the annotations in the controller */ getAnnotations(): AnnotationCollection; /** * Retrieve the annotation with the given id * @param id the id of the annotation to get * @returns The annotation with the given id */ getAnnotation(id: Id): Arrow | Text_2 | undefined; /** * Destroy the controller and its elements */ destroy(): void; } export declare type ControllerOptions = { /** * The color of the magnet points */ magnetColor: string; /** * The radius in which arrows are attracted */ magnetRadius: number; /** * The margin in which the Texts are detected when looking for magnet points */ detectMargin: number; /** * Display size of the magnet point */ magnetHandleRadius: number; /** * Placeholder for the text input */ textPlaceholder: string; /** * Size of the text handle */ textHandleSize: number; /** * Size of the arrow handle */ arrowHandleSize: number; /** * Minimum height of the arrow in units */ minArrowHeight: number; /** * Maximum height of the arrow in units */ maxArrowHeight: number; }; export declare const createArrow: (x0?: number, y0?: number, x1?: number, y1?: number, styles?: { tail?: Extremity | undefined; head?: Extremity | undefined; strokeType?: "none" | "plain" | "dashed" | undefined; strokeColor?: string | undefined; strokeWidth?: number | undefined; }) => Arrow; export declare function createSVGElement<T extends SVGElement>(tag: string): T; export declare const createText: (x?: number, y?: number, width?: number, height?: number, content?: string, styles?: Partial<TextStyle>) => Text_2; export declare const defaultArrowOptions: Arrow; export declare const defaultArrowStyle: ArrowStyles; export declare const defaultControllerOptions: AnnotationOptions; export declare const defaultTextOptions: Text_2; export declare const defaultTextStyle: TextStyle; /** * @class Annotations * Abstract class to display Texts and Arrows, provide add/remove/update and mouse events * Modifying annotation is handled by the child classes, it is too specific */ declare abstract class Editor<T extends Annotation> extends default_2<Events<T>> { protected ogma: default_3; protected elements: T[]; protected layer: SVGLayer; protected editor: Overlay; protected selectedId: Id; protected hoveredId: Id; protected ogmaOptions: Options; protected shouldDetect: boolean; protected isDragging: boolean; protected showeditorOnHover: boolean; constructor(ogma: default_3, editorHtml: string); private _onKeyUp; protected _canRemove(): boolean; private _onClickMouseMove; /** * @method add * @param options Params for the annotation (merged with default) * @returns the added annotation */ add(options: T): T; updateStyle(annotation: T, style: Partial<T["properties"]["style"]>): void; updateGeometry(annotation: T, geometry: Partial<T["geometry"]>): void; scale(annotation: T, scale: number, ox: number, oy: number): void; /** * @method update * Updates an annotation (position, color etc) * @param id Id of the annotation to update * @param element params of the annotation */ update(id: Id, element: Partial<T>): void; updateAnnotation(target: T, element: Partial<T>): void; getById(id: Id): T; /** * @method select * @param id id of the element to select * Select element, show editor, disable Ogma dragging and fire event */ select(id: Id): void; hover(id: Id): void; getSelectedFeature(): T | null; unselect(): this; unhover(): this; /** * @method remove * @param id Id of the annotation to remove * Removes annotation with the given id */ remove(id: Id): void; /** * @method disableDragging * Prevents Ogma from dragging elements or moving the view while dragging an annotation */ disableDragging(): void; /** * @method restoreDragging * restore ogma options as they were before we start dragging an annotation */ restoreDragging(): void; enableDetection(): void; /** * @method disableDetection * Disables the hover behaviour, used by controller to avoid hovering * arrows while dragging texts and vice versa */ disableDetection(): void; refreshLayer(): void; refreshDrawing(): void; getElements(): T[]; abstract refreshEditor(): void; abstract draw(svg: SVGSVGElement): void; abstract cancelDrawing(): void; abstract getDefaultOptions(): T; abstract detect(point: Point_2, margin: number): T | undefined; destroy(): void; } export declare type Events<T> = { [EVT_HOVER]: (evt: T) => void; [EVT_UNHOVER]: (evt: T) => void; [EVT_SELECT]: (evt: T) => void; [EVT_UNSELECT]: (evt: T) => void; [EVT_DRAG_START]: (evt: T) => void; [EVT_DRAG]: (evt: T, key: "line" | "start" | "end" | "text") => void; [EVT_DRAG_END]: (evt: T) => void; [EVT_REMOVE]: (evt: T) => void; [EVT_ADD]: (evt: T) => void; [EVT_UPDATE]: (evt: T) => void; }; export declare const EVT_ADD = "add"; export declare const EVT_CANCEL_DRAWING = "cancelDrawing"; export declare const EVT_DRAG = "dragging"; export declare const EVT_DRAG_END = "dragend"; export declare const EVT_DRAG_START = "dragstart"; export declare const EVT_HOVER = "hover"; export declare const EVT_LINK = "link"; export declare const EVT_REMOVE = "remove"; export declare const EVT_SELECT = "select"; export declare const EVT_UNHOVER = "unhover"; export declare const EVT_UNSELECT = "unselect"; export declare const EVT_UPDATE = "update"; declare type ExportedLink = { id: Id; side: "start" | "end"; type: "node" | "text"; magnet?: Point; }; export declare type Extremity = "none" | "arrow" | "arrow-plain" | "dot" | "halo-dot"; export declare type FeatureEvents = { /** * Event trigerred when selecting an annotation * @param evt The annotation selected */ [EVT_SELECT]: (evt: Annotation) => void; /** * Event trigerred when unselecting an annotation * @param evt The annotation unselected */ [EVT_UNSELECT]: (evt: Annotation) => void; /** * Event trigerred when removing an annotation * @param evt The annotation removed */ [EVT_REMOVE]: (evt: Annotation) => void; /** * Event trigerred when adding an annotation * @param evt The annotation added */ [EVT_ADD]: (evt: Annotation) => void; [EVT_CANCEL_DRAWING]: () => void; /** * Event trigerred when updating an annotation * @returns The annotation updated */ [EVT_UPDATE]: (evt: Annotation) => void; /** * Event trigerred when linking an arrow to a text or node */ [EVT_LINK]: (evt: { arrow: Arrow; link: Link; }) => void; /** * Event trigerred when starting to drag an arrow or a text */ [EVT_DRAG_START]: (evt: Arrow | Text_2) => void; /** * Event trigerred when dragging an arrow or a text */ [EVT_DRAG]: (evt: Arrow | Text_2, key: "line" | "start" | "end" | "text") => void; /** * Event trigerred when stopped dragging an arrow or a text */ [EVT_DRAG_END]: (evt: Arrow | Text_2) => void; }; /** * Calculate the bounds of a collection of annotations * @param annotations */ export declare function getAnnotationsBounds(annotations: AnnotationCollection): Bounds; export declare function getArrowEnd(a: Arrow): { x: number; y: number; }; export declare function getArrowEndPoints(a: Arrow): { start: { x: number; y: number; }; end: { x: number; y: number; }; }; export declare function getArrowSide(a: Arrow, side: "start" | "end"): { x: number; y: number; }; export declare function getArrowStart(a: Arrow): { x: number; y: number; }; export declare function getAttachmentPointOnNode(start: Point_2, nodeCenter: Point_2, nodeRadius: number): { x: number; y: number; }; export declare function getCoordinates(gj: Feature | FeatureCollection | Geometry): Position[]; export declare const getHandleId: (handle: HTMLDivElement) => number; export declare function getTextBbox(t: Text_2): BBox; export declare function getTextPosition(t: Text_2): { x: number; y: number; }; export declare function getTextSize(t: Text_2): { width: number; height: number; }; export declare function hexShortToLong(color: string): string; export declare function hexToRgba(color: string, alpha: number): string; export declare type Id = string | number; export declare const isAnnotationCollection: (a: AnnotationFeature<Geometry, AnnotationProps> | FeatureCollection) => a is AnnotationCollection; export declare const isArrow: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Arrow; export declare const isText: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Text_2; export declare type Link = { /** arrow attached to the text or node */ arrow: Id; /** id of the text the arrow is attached to */ id: Id; /** On which end the arrow is tighten to the text */ side: Side; /** id of the text or node the arrow is attached to */ target: Id; /** Text or node */ targetType: TargetType; /** * On which point relative to topleft corner the arrow is tighten, in case of * node, it can be deduced from the arrow itself */ connectionPoint: Point; }; export declare const NONE = -1; export declare type Point = { x: number; y: number; }; export declare function rgbToRgba(color: string, alpha: number): string; export declare function scaleGeometry(geometry: LineString | Polygon, scale: number, ox: number, oy: number): LineString | Polygon; export declare function setArrowEnd(a: Arrow, x: number, y: number): void; export declare function setArrowEndPoint(a: Arrow, side: "start" | "end", x: number, y: number): void; export declare function setArrowStart(a: Arrow, x: number, y: number): void; export declare function setTextBbox(t: Text_2, x: number, y: number, width: number, height: number): void; export declare type Side = "start" | "end"; export declare type Stroke = { type: "plain" | "dashed" | "none"; color: string; width: number; }; export declare type StrokeOptions = { strokeType?: "plain" | "dashed" | "none"; strokeColor?: string; strokeWidth?: number; }; export declare type StrokeStyle = Stroke; export declare type TargetType = "text" | "node"; declare type Text_2 = AnnotationFeature<Polygon, TextProperties>; export { Text_2 as Text } export declare interface TextProperties extends AnnotationProps { type: "text"; /**text to display*/ content: string; style?: TextStyle; } /** * @class Texts * Draw, update, edit texts */ export declare class Texts extends Editor<Text_2> { private textArea; private handleSize; private rect; private annotation; private startX; private startY; private handles; private draggedHandle; private isFocused; private placeholder; constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "textHandleSize" | "textPlaceholder">); private _onFocus; private _onBlur; protected _canRemove(): boolean; startDrawing: (x: number, y: number, text?: Text_2) => void; cancelDrawing: () => void; private startDragging; private onHandleMouseDown; private onMouseMove; private _onMouseMove; private onMouseUp; private _onMousedown; private onViewChanged; private _onInput; detect({ x, y }: Point_2, margin?: number): Text_2 | undefined; draw(svg: SVGSVGElement): void; refreshDrawing(): void; getDefaultOptions(): Text_2; refreshEditor(): void; select(id: Id): void; destroy(): void; } export declare interface TextStyle extends StrokeOptions { /** Helvetica, sans-serif... */ font?: string; /** Font size, in pixels */ fontSize?: number | string; /** text color: #f00, yellow...*/ color?: string; /** background color: empty for transparent #f00, yellow...*/ background?: string; /** padding around the text */ padding?: number; /** Text box border radius */ borderRadius?: number; } export declare function updateTextBbox(t: Text_2): void; export declare type Vector = Point; export { }