mskalign-canvas
Version:
一个用于图片标注的javascript库,基于canvas,简单轻量,支持矩形、多边形、点、折线、圆形。
606 lines (605 loc) • 19.1 kB
TypeScript
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 {};