UNPKG

mskalign-canvas

Version:

一个用于图片标注的javascript库,基于canvas,简单轻量,支持矩形、多边形、点、折线、圆形。

606 lines (605 loc) 19.1 kB
import Rect from './shape/Rect'; import Polygon from './shape/Polygon'; import Dot from './shape/Dot'; import Line from './shape/Line'; import Circle from './shape/Circle'; import Angle from './shape/Angle'; import Arrow from './shape/Arrow'; import Ellipse from './shape/Ellipse'; import Checkerboard from './shape/Checkerboard'; import Curve from './shape/Curve'; import CompositeGraph from './shape/CompositeGraph'; import EventBus from './EventBus'; import type { Point, HitType, RememberPointsType } from './types'; export type FixedPoint = { coor: Point; uuid: string; }; export type AllShape = Rect | Polygon | Dot | Line | Circle | Angle | Arrow | Ellipse | Checkerboard | Curve | CompositeGraph; type HitShapeResult = { hitIndex: number; hitShape: AllShape; hitType: HitType; shape: AllShape | null; hitComponentIndex?: number; hitComponentShape?: AllShape; hitComponentType?: HitType; }; type EditDataType = { uuid: string; key: string; value: any; }; type EditDataType2 = { dataType: string; newData: any; }; type ContainerSize = { width: number; height: number; }; type LineRoughType = 'thin' | 'normal' | 'bold'; export default class MskalignCanvas extends EventBus { /** 当前版本 */ version: string; /** 只读模式,画布不允许任何交互 */ lock: boolean; /** 只读模式,仅支持查看, 支持放大缩小和平移 */ readonly: boolean; /** 操作类型 目前支持 move zoom 为空则两种操作都支持 * readonly actionType 组合则可以做到只允许move or zoom 而不运行其他任何操作 */ actionType: string; mouseAction: string; disableWheel: boolean; enableKeyMove: boolean; isMouseInImage: boolean; transformConfig: { horizontalScale: number; rotate: number; }; debugMode: boolean; disableSort: boolean; /** 最小矩形宽度 */ MIN_WIDTH: number; /** 最小矩形高度 */ MIN_HEIGHT: number; /** 最小圆形半径 */ MIN_RADIUS: number; /** 插值点数 */ INTERPOLATION_POINTS: number; pixelSpacing: number; /** 边线颜色 */ strokeStyle: string; /** 填充颜色 */ fillStyle: string; /** 当前选中的标注边线颜色 */ activeSecondaryStrokeStyle: string; activeStrokeStyle: string; /** 当前选中的标注填充颜色 */ activeFillStyle: string; /** 控制点填充颜色 */ ctrlFillStyle: string; /** 是否隐藏标签 */ hideLabel: boolean; isUsePrimitiveMathRound: boolean; /** 标签背景填充颜色 */ labelFillStyle: string; /** 标签字体 */ labelFont: string; /** 标签文字颜色 */ labelTextFillStyle: string; /** 标签字符最大长度,超出使用省略号 */ labelMaxLen: number; /** 画布宽度 */ WIDTH: number; /** 画布高度 */ HEIGHT: number; canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; /** 所有标注数据 */ dataset: AllShape[]; activeShapeList: AllShape[]; offScreen: HTMLCanvasElement; offScreenCtx: CanvasRenderingContext2D; bufferCtx: CanvasRenderingContext2D; buffer: any; /** 亮度 */ luminance: number; luminanceStep: number; private oldLuminanceType; private hitIndex; /** 记录锚点距离 */ remember: RememberPointsType; /** 记录鼠标位置 */ mouse: Point; mousePoint: Point; /** 记录背景图鼠标位移 */ rememberOrigin: number[]; fixedPointList: FixedPoint[]; dataType: string; ctrlHoverRadius: number; drawCtrlOuterDash: boolean; /** 虚线配置 */ dashLineConfig: number[]; /** 控制点半径 */ ctrlRadius: number; /** 边线宽度 */ lineWidth: number; /** 线粗细模式 */ lineRoughnessMode: LineRoughType; modeConfigs: { thin: { ctrlRadius: number; lineWidth: number; dashLineConfig: number[]; }; normal: { ctrlRadius: number; lineWidth: number; dashLineConfig: number[]; }; bold: { ctrlRadius: number; lineWidth: number; dashLineConfig: number[]; }; }; /** 0 不创建,1 矩形,2 多边形,3 点,4 折线,5 */ private createType; createOptions: any; /** 控制点索引 */ ctrlIndex: number; /** 控制组件索引 */ ctrlComponentIndex: number; /** 背景图片 */ image: HTMLImageElement; /** 图片原始宽度 */ IMAGE_ORIGIN_WIDTH: number; /** 图片缩放后的宽度 */ IMAGE_WIDTH: number; /** 图片原始高度 */ IMAGE_ORIGIN_HEIGHT: number; /** 图片缩放后的高度 */ IMAGE_HEIGHT: number; /** 原点x */ originX: number; /** 原点y */ originY: number; private isRightMouseDown; private rightMouseDownTimer; private readonly RIGHT_MOUSE_HOLD_THRESHOLD; private isRightMouseHold; private rightMouseDownTime; /** 缩放步长 */ private scaleStep; private limitMaxScaleStep; private limitMinScaleStep; private stepRate; maxScaleRate: number; minScaleRate: number; scaleRate: number; /** 滚动缩放 */ scrollZoom: boolean; private allShapeTypes; private ctrlShapeTypes; private lineLikeTypes; private timer; private timer2; private mouseTimer; /** 最小touch双击时间 */ dblTouch: number; /** 记录touch双击开始时间 */ dblTouchStore: number; /** 这个选项可以帮助浏览器进行内部优化 */ alpha: boolean; /** 专注模式 */ /** 记录当前事件 */ private evt; private curveCtrlHoverIndex; private curveCtrlActiveIndex; /** 触控缩放时记录上一次两点距离 */ scaleTouchStore: number; /** 当前是否为双指触控 */ isTouch2: boolean; isMobile: boolean; /** 向上展示label */ labelUp: boolean; labelValueVisible: boolean; labelCoor: Point | []; labelRadius: number; auxiliaryLineList: any[]; auxiliaryPointList: any[]; auxiliaryCurveList: any[]; offscreenCanvas: any; offscreenCtx: any; magnifierCanvas: HTMLCanvasElement; magnifierCtx: CanvasRenderingContext2D; isMagnifierVisible: boolean; magnifierConfig: { scale: number; offsetX: number; offsetY: number; width: number; height: number; }; oldData: any; /** * @param el Valid CSS selector string, or DOM * @param src image src */ constructor(el: HTMLCanvasElement | string, options?: ContainerSize); get canMoveImage(): boolean; get canZoomImage(): boolean; /** 当前选中的标注 */ get activeShape(): AllShape; /** 当前选中的子组件 */ get activeComponentShape(): any; /** 当前缩放比例 */ get scale(): number; /** 图片最小边尺寸 */ get imageMin(): number; /** 图片原始最大边尺寸 */ get imageOriginMax(): number; private mathRound; changeDataByUid(data: EditDataType): void; changeDataByDataType(data: EditDataType2): void; /** * 设置模式 * @param mode 模式名称, 不传则默认为正常模式 * @param value * 1. 锁定模式 * 2. 只读模式 * 3. 移动模式 * 4. 缩放模式 * 以上模式均不可以操作参数 */ setMode(mode: string, value: Boolean): void; getMode(): "" | "lock" | "readonly" | "moveOnly" | "zoomOnly"; update(): void; /** * 设置线条粗细模式 * @param {LineRoughType} mode - 线条模式: 'thin' | 'normal' | 'bold' * @returns {void} */ setLineRoughness(mode: LineRoughType): void; /** * 设置固定数据 * @param data Array */ setFixedPoint(list: Point[]): void; /** 设置像素间距 */ setPixelSpacing(pixelSpacing: number, isUpdate?: boolean): void; pureUpdateImage(ctx?: CanvasRenderingContext2D): void; createMagnifier(): void; updateMagnifier(x: number, y: number): void; destroyMagnifier(): void; getImageDataFromCanvas(canvas: HTMLCanvasElement, [x, y, width, height]: [number, number, number, number]): ImageData; cancelActive(): void; viewAllShape(): void; /** 获取画布快照 rate 越高越高清*/ getSnapshot(rate?: number): Promise<unknown>; /** 合成事件 */ mergeEvent(e: TouchEvent | MouseEvent): { mouseX: number; mouseY: number; mouseCX: number; mouseCY: number; altKey: boolean; button: number; buttons: number; clientX: number; clientY: number; ctrlKey: boolean; metaKey: boolean; movementX: number; movementY: number; offsetX: number; offsetY: number; pageX: number; pageY: number; relatedTarget: EventTarget; screenX: number; screenY: number; shiftKey: boolean; x: number; y: number; getModifierState(keyArg: string): boolean; initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget): void; detail: number; view: Window; which: number; initUIEvent(typeArg: string, bubblesArg?: boolean, cancelableArg?: boolean, viewArg?: Window, detailArg?: number): void; bubbles: boolean; cancelBubble: boolean; cancelable: boolean; composed: boolean; currentTarget: EventTarget; defaultPrevented: boolean; eventPhase: number; isTrusted: boolean; returnValue: boolean; srcElement: EventTarget; target: EventTarget; timeStamp: number; type: string; composedPath(): EventTarget[]; initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void; preventDefault(): void; stopImmediatePropagation(): void; stopPropagation(): void; AT_TARGET: number; BUBBLING_PHASE: number; CAPTURING_PHASE: number; NONE: number; } | { mouseX: number; mouseY: number; mouseCX: number; mouseCY: number; altKey: boolean; changedTouches: TouchList; ctrlKey: boolean; metaKey: boolean; shiftKey: boolean; targetTouches: TouchList; touches: TouchList; detail: number; view: Window; which: number; initUIEvent(typeArg: string, bubblesArg?: boolean, cancelableArg?: boolean, viewArg?: Window, detailArg?: number): void; bubbles: boolean; cancelBubble: boolean; cancelable: boolean; composed: boolean; currentTarget: EventTarget; defaultPrevented: boolean; eventPhase: number; isTrusted: boolean; returnValue: boolean; srcElement: EventTarget; target: EventTarget; timeStamp: number; type: string; composedPath(): EventTarget[]; initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void; preventDefault(): void; stopImmediatePropagation(): void; stopPropagation(): void; AT_TARGET: number; BUBBLING_PHASE: number; CAPTURING_PHASE: number; NONE: number; }; handleContextmenu(e: MouseEvent): void; handleMousewheel(e: WheelEvent): void; handleMouseDown(e: MouseEvent | TouchEvent): void; handleClickOnShapeOrNot(offsetX: number, offsetY: number): void; getRememberPoint(hitShape: AllShape, offsetX: number, offsetY: number): RememberPointsType; watchMouseStatus(mouse: Point): void; handleMouseMove(e: MouseEvent | TouchEvent): void; handelMouseUp(e: MouseEvent | TouchEvent): void; handelDblclick(e: MouseEvent | TouchEvent): void; handelKeyup(e: KeyboardEvent): void; /** 初始化配置 */ initSetting(options?: ContainerSize): void; /** 拖拽矩形 */ dragRect([x, y]: Point, [offsetX, offsetY]: Point): void; /** 初始化事件 */ private initEvents; /** * 添加/切换图片 * @param url 图片链接 */ setImage(url: string): void; /** 开始的时候实例化图形 */ initialShapes(AllShapes: AllShape[]): AllShape[]; /** * 设置数据 * @param data Array */ initData(data: AllShape[]): void; /** * 追加数据 * @param data Array */ appendData(data: AllShape): void; /** 创建图形 */ create(type: number, options: any): void; createSingleGraph(createType: number, createOptions: any, curPoint: Point | Point[], // index: number, isCreating: boolean): Rect | Polygon | Dot | Line | Circle | Angle | Arrow | Ellipse | Checkerboard | Curve; createShapes(offsetX: number, offsetY: number): void; isHitOnBaseShape(mousePoint: Point, shape: AllShape): boolean; /** * 判断是否在标注实例上 * @param mousePoint 点击位置 * @returns */ onHitShape(mousePoint: Point, allShapes: AllShape[]): HitShapeResult; /** * 判断鼠标是否在背景图内部 * @param e MouseEvent * @returns 布尔值 */ isInBackground(e: MouseEvent | TouchEvent): boolean; isInImage(e: MouseEvent | TouchEvent): boolean; /** * 判断是否在矩形内 * @param point 坐标 * @param coor 区域坐标 * @returns 布尔值 */ isPointInRect(point: Point, coor: Point[]): boolean; /** * 判断是否在多边形内 * @param point 坐标 * @param coor 区域坐标 * @returns 布尔值 */ isPointInPolygon(point: Point, coor: Point[]): boolean; /** * 判断是否在折线内 * @param point 坐标 * @param coor 区域坐标 * @returns 布尔值 */ isPointInLine(point: Point, coor: Point[]): boolean; /** * 判断是图形是否属于嵌套关系 (目前只支持矩形和多边形) * @param shape1 标注实例 * @param shape2 标注实例 * @returns 布尔值 */ isNested(shape1: Rect | Polygon, shape2: Rect | Polygon): boolean; getActiveShapeLastPointInScreen(): { x: number; y: number; }; /** * 绘制矩形 * @param shape 标注实例 * @returns */ drawRect(shape: Rect, ctx: CanvasRenderingContext2D): void; /** * 绘制拟合曲线 * @param shape 标注实例 * @returns */ drawCurve(shape: Curve, ctx: CanvasRenderingContext2D): void; /** * 绘制多边形 * @param shape 标注实例 */ drawPolygon(shape: Polygon, ctx: CanvasRenderingContext2D): void; /** * 绘制点 * @param shape 标注实例 */ drawDot(shape: Dot, ctx: CanvasRenderingContext2D): void; /** * 绘制圆 * @param shape 标注实例 */ drawCircle(shape: Circle, ctx: CanvasRenderingContext2D): void; /** * 绘制椭圆 * @param shape 标注实例 */ drawEllipse(shape: Ellipse, ctx: CanvasRenderingContext2D): void; /** * 绘制棋盘 * @param shape 标注实例 */ drawCheckerboard(shape: Checkerboard, ctx: CanvasRenderingContext2D): void; /** * 绘制折线 * @param shape 标注实例 */ drawLine(shape: Line, ctx: CanvasRenderingContext2D): void; /** * 绘制角度 * @param shape 标注实例 */ drawAngle(shape: Angle, ctx: CanvasRenderingContext2D): void; /** * 绘制箭头 * @param shape 标注实例 */ drawArrow(shape: Arrow, ctx: CanvasRenderingContext2D): void; /** * 绘制辅助线 * @param shape * @returns */ drawAuxiliaryLine(shape: Line, ctx: CanvasRenderingContext2D): void; /** * 绘制辅助曲线 * @param shape * @returns */ drawAuxiliaryCurve(shape: Curve, ctx: CanvasRenderingContext2D): void; getFillColor(shape: AllShape): string; /** * 绘制hover控制点, 在点周围显示一个蓝色轮廓 * @param coor 坐标 */ drawCtrlByCoor(coor: any, fillColor?: string): void; /** * 绘制控制点 * @param point 坐标 */ drawCtrl(point: Point, ctrlFillStyle?: string): void; /** * 绘制控制点列表 * @param shape 标注实例 */ drawCtrlList(shape: Rect | Polygon | Line | Curve): void; /** * 绘制label * @param point 位置 * @param label 文本 */ drawLabel(ctx: CanvasRenderingContext2D, shape: AllShape, point: Point, padding?: number): void; drawAuxiliaryLines(ctx: CanvasRenderingContext2D): void; drawAuxiliaryCurves(ctx: CanvasRenderingContext2D): void; drawAuxiliaryPoints(ctx: CanvasRenderingContext2D): void; /** * 绘制图形 */ drawShape(list: AllShape[], ctx?: CanvasRenderingContext2D): void; pureDraw(shape: AllShape, ctx: CanvasRenderingContext2D): void; /** * 根据dataType选中指定图形 */ selectByDataType(type: string): void; /** * 根据id选中指定图形 */ selectById(id: string): void; /** * 删除指定图形 * @param index number */ deleteById(id: string): void; deleteByIndex(index: number): void; /** * 计算缩放步长 */ calcStep(): void; setLuminance(type: boolean): void; /** * 缩放 * @param type true放大5%,false缩小5% * @param center 缩放中心 center|mouse * @param pure 不绘制 */ setScale(type: boolean, byMouse?: boolean, pure?: boolean): void; /** * 取消上一个图形 */ cancelCreate(): void; /** * 适配背景图 */ fitZoom(): void; /** * 设置专注模式 未生效 * @param type {boolean} */ setFocusMode(type: boolean): void; /** * 销毁 */ destroy(): void; /** * 重新设置画布大小 */ resize(): void; private isMiddleMouseDown; private lastMouseX; private lastMouseY; private readonly ARROW_MOVE_STEP; private handleArrowMove; } export {};