Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions demo/index.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/index.js

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions dist/types/base.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ButtonEventNames, ClipboardEventNames, InputEventNames, KeyboardEventNames, PointerEventNames, VideoEventNames, WindowEventNames } from "./ui/events";
export declare class AnnotationToolBase<T> {
destructors: (() => void)[];
isDestroyed: boolean;
activeTimeFrame: number;
referenceVideoElement: HTMLVideoElement | null;
videoElement: HTMLVideoElement | HTMLImageElement;
globalShapes: T[];
timeStack: Map<number, T[]>;
undoTimeStack: Map<number, T[][]>;
cleanFrameStacks(): void;
destroy(): void;
raf(cb: () => void): number;
addEvent(node: HTMLInputElement, event: InputEventNames, callback: (e: Event) => void): void;
addEvent(node: typeof document, event: ClipboardEventNames, callback: (e: ClipboardEvent) => void): void;
addEvent(node: typeof document, event: ButtonEventNames, callback: (e: PointerEvent) => void): void;
addEvent(node: HTMLVideoElement, event: VideoEventNames, callback: (e: Event) => void): void;
addEvent(node: HTMLVideoElement, event: KeyboardEventNames, callback: (e: KeyboardEvent) => void): void;
addEvent(node: HTMLButtonElement, event: ButtonEventNames, callback: (e: Event) => void): void;
addEvent(node: HTMLCanvasElement, event: PointerEventNames, callback: (e: PointerEvent) => void): void;
addEvent(node: typeof document, event: KeyboardEventNames, callback: (e: KeyboardEvent) => void): void;
addEvent(node: typeof window, event: WindowEventNames, callback: (e: Event) => void): void;
addProgressBarOverlay(): void;
initUI(): void;
initCanvas(): void;
addFrameSquareOverlay(_?: number): void;
addVideoOverlay(): void;
withRefVideo(cb: (video: HTMLVideoElement) => void): void;
withVideo(cb: (video: HTMLVideoElement) => void): void;
}
81 changes: 40 additions & 41 deletions dist/types/core.d.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import { AnnotationToolBase } from "./base";
import { IShape, ShapeMap, Tool, PluginInstances } from "./plugins";
import { ToolPlugin } from "./plugins/base";
import { ButtonEventNames, ClipboardEventNames, InputEventNames, KeyboardEventNames, PointerEventNames, VideoEventNames, WindowEventNames } from "./ui/events";
declare class FrameSyncBucket {
promise: Promise<any>;
resolve: (value: any) => void;
reject: (reason?: any) => void;
timeout: number;
constructor();
release(time?: number | undefined): void;
init(): void;
}
export type FrameAnnotationV1 = {
frame: number;
fps: number;
version: 1;
shapes: IShape[];
};
export declare class AnnotationTool {
videoElement: HTMLVideoElement | HTMLImageElement;
referenceVideoElement: HTMLVideoElement | null;
export declare class AnnotationTool extends AnnotationToolBase<IShape> {
uiContainer: HTMLDivElement;
playerControlsContainer: HTMLDivElement;
canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D;
isMouseDown: boolean;
_currentTool: Tool | null;
activeTimeFrame: number;
buttons: HTMLButtonElement[];
colorPicker: HTMLInputElement;
strokeSizePicker: HTMLInputElement;
destructors: (() => void)[];
plugins: PluginInstances[];
isDestroyed: boolean;
globalShapes: IShape[];
timeStack: Map<number, IShape[]>;
undoTimeStack: Map<number, IShape[][]>;
frameSyncBucket: FrameSyncBucket;
playTimeout: number & ReturnType<typeof window.setTimeout>;
annotatedFrameCoordinates: {
x: number;
Expand Down Expand Up @@ -53,7 +55,6 @@ export declare class AnnotationTool {
width: number;
height: number;
};
get videoClientRect(): DOMRect;
get shapes(): IShape[];
set shapes(shapes: IShape[]);
get undoStack(): IShape[][];
Expand All @@ -65,34 +66,33 @@ export declare class AnnotationTool {
hideControls(): void;
showCanvas(): void;
hideCanvas(): void;
show(): void;
updateActiveTimeFrame(): void;
show(): Promise<void>;
setCanvasSettings(): void;
pluginForTool<T extends Tool>(tool: T): ToolPlugin<ShapeMap[T]>;
getButtonForTool(tool: Tool): HTMLButtonElement;
bindContext(): void;
initProperties(): void;
setVideoStyles(): void;
get frameCallbackSupported(): boolean;
ct: number;
initFrameCounter(): Promise<unknown> | undefined;
waitForFrameSync(): Promise<any>;
init(videoElement: HTMLVideoElement | HTMLImageElement): void;
addEvent(node: HTMLInputElement, event: InputEventNames, callback: (e: Event) => void): void;
addEvent(node: typeof document, event: ClipboardEventNames, callback: (e: ClipboardEvent) => void): void;
addEvent(node: typeof document, event: ButtonEventNames, callback: (e: PointerEvent) => void): void;
addEvent(node: HTMLVideoElement, event: VideoEventNames, callback: (e: Event) => void): void;
addEvent(node: HTMLVideoElement, event: KeyboardEventNames, callback: (e: KeyboardEvent) => void): void;
addEvent(node: HTMLButtonElement, event: ButtonEventNames, callback: (e: Event) => void): void;
addEvent(node: HTMLCanvasElement, event: PointerEventNames, callback: (e: PointerEvent) => void): void;
addEvent(node: typeof document, event: KeyboardEventNames, callback: (e: KeyboardEvent) => void): void;
addEvent(node: typeof window, event: WindowEventNames, callback: (e: Event) => void): void;
initCanvas(): void;
onKeyDown(event: KeyboardEvent): void;
removeLastShape(): void;
handleUndo(): void;
removeLastShape(): Promise<void>;
handleUndo(): Promise<void>;
destroy(): void;
setCanvasSize(): void;
isMultiTouch(event: PointerEvent): boolean;
setCanvasSize(): Promise<void>;
addShape(shape: IShape): void;
syncTime(force?: boolean): void;
syncTime(force?: boolean, newTime?: null | number): void;
get msPerFrame(): number;
syncVideoSizes(): void;
addReferenceVideoByURL(url: string): Promise<void>;
addReferenceVideoByURL(url: string | URL): Promise<void>;
isPlaybackRestarting: boolean;
restartPlayback(): Promise<void>;
hideButton(tool: Tool): void;
showButton(tool: Tool): void;
addSingletonShape(shape: IShape): void;
serialize(shapes?: IShape[]): IShape[];
deserialize(shapes: IShape[]): IShape[];
Expand All @@ -105,34 +105,33 @@ export declare class AnnotationTool {
lastNavigatedFrame: number;
isProgressBarNavigation: boolean;
get isVideoPaused(): boolean;
handleMouseMove(event: PointerEvent): void;
get hasGlobalOverlays(): boolean;
handleMouseMove(event: PointerEvent): Promise<void>;
getEventX(event: PointerEvent): number;
getEventY(event: PointerEvent): number;
handleMouseUp(event: PointerEvent): void;
handleMouseUp(event: PointerEvent): Promise<void>;
focusOnMediaNode(): void;
drawShapesOverlay(): void;
drawShapesOverlay(): Promise<void>;
clearCanvas(): void;
frameToDataUrl(): string | null;
redrawFullCanvas(): void;
frameToDataUrl(): Promise<string | null>;
redrawFullCanvas(): Promise<void>;
replaceFrame(frame: number, shapes: IShape[]): void;
addShapesToFrame(frame: number, shapes: IShape[]): void;
setFrameRate(fps: number): void;
stringifyShapes(shapes: IShape[]): string;
parseShapes(shapes: string): any;
filterNonSerializableShapes(shapes: IShape[]): IShape[];
saveCurrentFrame(): FrameAnnotationV1;
addFrameSquareOverlay(_?: number): void;
addVideoOverlay(): void;
cleanFrameStacks(): void;
loadAllFrames(frames: FrameAnnotationV1[]): void;
appendFrames(frames: FrameAnnotationV1[]): void;
saveAllFrames(): FrameAnnotationV1[];
getAnnotationFrame(event: PointerEvent): number | null;
get totalFrames(): number;
frameFromProgressBar(event: PointerEvent, countY?: boolean): number | null;
addProgressBarOverlay(): void;
initUI(): void;
stopAnnotationsAsVideo(): void;
hasAnnotationsForFrame(frame: number): boolean | undefined;
playAnnotationsAsVideo(): void;
fillCanvas(): void;
isAnnotationsAsVideoActive: boolean;
stopAnnotationsAsVideo(): void;
startAnnotationsAsVideo(): void;
playAnnotationsAsVideo(): Promise<void>;
}
export {};
2 changes: 2 additions & 0 deletions dist/types/events/document-click.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { SmAnnotate } from "..";
export declare function onDocumentClick(event: PointerEvent, tool: SmAnnotate): void;
2 changes: 2 additions & 0 deletions dist/types/events/document-copy.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { SmAnnotate } from "..";
export declare function onDocumentCopy(event: ClipboardEvent, tool: SmAnnotate): void;
2 changes: 2 additions & 0 deletions dist/types/events/document-cut.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { SmAnnotate } from "..";
export declare function onDocumentCut(event: ClipboardEvent, tool: SmAnnotate): void;
2 changes: 2 additions & 0 deletions dist/types/events/document-keydown.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { SmAnnotate } from "..";
export declare function onDocumentKeydown(event: KeyboardEvent, tool: SmAnnotate): void;
2 changes: 2 additions & 0 deletions dist/types/events/document-paste.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { SmAnnotate } from "..";
export declare function onDocumentPaste(event: ClipboardEvent, tool: SmAnnotate): void;
3 changes: 3 additions & 0 deletions dist/types/events/utils/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { SmAnnotate } from "../..";
export declare const isTargetBelongsToVideo: (event: PointerEvent | KeyboardEvent | ClipboardEvent, tool: SmAnnotate) => boolean;
export declare function isMultiTouch(event: PointerEvent): boolean;
2 changes: 1 addition & 1 deletion dist/types/overlays/frame-number.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { AnnotationTool } from "../core";
import type { AnnotationTool } from "../core";
export declare function addFrameSquareOverlay(this: AnnotationTool, frame?: number): void;
2 changes: 1 addition & 1 deletion dist/types/overlays/progress-bar.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { AnnotationTool } from "../core";
import type { AnnotationTool } from "../core";
export declare function addProgressBarOverlay(this: AnnotationTool): void;
2 changes: 1 addition & 1 deletion dist/types/overlays/video.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { AnnotationTool } from "../core";
import type { AnnotationTool } from "../core";
export declare function addVideoOverlay(this: AnnotationTool): void;
2 changes: 1 addition & 1 deletion dist/types/plugins/base.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface ToolPlugin<T extends IShapeBase> {
onActivate: () => void;
onDeactivate: () => void;
reset: () => void;
draw: (shape: T) => void;
draw: (shape: T) => void | Promise<void>;
save: (shape: T) => void;
move: (shape: T, deltaX: number, deltaY: number) => T;
normalize: (shape: T, canvasWidth: number, canvasHeight: number) => T;
Expand Down
3 changes: 2 additions & 1 deletion dist/types/plugins/compare.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ export declare class CompareToolPlugin extends BasePlugin<ICompare> implements T
onPointerUp(): void;
save(shape: ICompare): void;
drawDelimiter(shape: ICompare): void;
draw(shape: ICompare): void;
drawShape(shape: ICompare): void;
draw(shape: ICompare): Promise<void>;
}
2 changes: 1 addition & 1 deletion dist/types/ui/events.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export type KeyboardEventNames = "keydown";
export type ButtonEventNames = "click";
export type InputEventNames = "input" | "change";
export type ClipboardEventNames = "copy" | "paste" | "cut";
export type VideoEventNames = "timeupdate" | "volumechange" | "seeking" | "play" | "pause" | "ended" | "seek" | "stalled" | "waiting" | "error";
export type VideoEventNames = "timeupdate" | "volumechange" | "seeking" | "play" | "pause" | "seek" | "stalled" | "error" | "requestVideoFrameCallback";
export type WindowEventNames = "resize";
export type EventNames = VideoEventNames | InputEventNames | PointerEventNames | KeyboardEventNames | WindowEventNames | ButtonEventNames | ClipboardEventNames;
23 changes: 23 additions & 0 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export class AnnotationToolBase<T> {
isDestroyed = false;
activeTimeFrame = 1;

referenceVideoElement!: HTMLVideoElement | null;
videoElement!: HTMLVideoElement | HTMLImageElement;

globalShapes: T[] = [];
timeStack = new Map<number, T[]>(); // timeFrame -> shapes
undoTimeStack = new Map<number, T[][]>(); // timeFrame -> shapes
Expand Down Expand Up @@ -125,4 +128,24 @@ export class AnnotationToolBase<T> {
addVideoOverlay() {
throw new Error("Method not implemented.");
}

withRefVideo(cb: (video: HTMLVideoElement) => void) {
if (this.isDestroyed) {
return;
}
if (this.referenceVideoElement) {
cb(this.referenceVideoElement);
}
}

withVideo(cb: (video: HTMLVideoElement) => void) {
if (this.isDestroyed) {
return;
}
const video = this.videoElement as HTMLVideoElement;
if (!video || video.tagName !== "VIDEO") {
return;
}
cb(video);
}
}
Loading