mirror of
https://github.com/idrawjs/idraw
synced 2026-05-23 17:48:23 +00:00
refactor: rename ts type name
This commit is contained in:
parent
59f1280f3c
commit
7b2f00f047
63 changed files with 1326 additions and 1249 deletions
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
TypeScreenPosition,
|
||||
TypeScreenSize,
|
||||
TypeScreenContext,
|
||||
TypePoint,
|
||||
TypePointCursor,
|
||||
TypeBoardOptions,
|
||||
TypeBoardSizeOptions,
|
||||
TypeContext
|
||||
ScreenPosition,
|
||||
ScreenSize,
|
||||
ScreenContext,
|
||||
Point,
|
||||
PointCursor,
|
||||
BoardOptions,
|
||||
BoardSizeOptions,
|
||||
IDrawContext
|
||||
} from '@idraw/types';
|
||||
import util from '@idraw/util';
|
||||
import { ScreenWatcher } from './lib/screen-watcher';
|
||||
|
|
@ -39,7 +39,7 @@ import {
|
|||
_screen
|
||||
} from './names';
|
||||
|
||||
type PrivateOptions = TypeBoardOptions & {
|
||||
type PrivateOptions = BoardOptions & {
|
||||
devicePixelRatio: number;
|
||||
};
|
||||
|
||||
|
|
@ -51,15 +51,15 @@ export default class Board {
|
|||
private [_displayCanvas]: HTMLCanvasElement;
|
||||
private [_mount]: HTMLDivElement;
|
||||
private [_opts]: PrivateOptions;
|
||||
private [_ctx]: TypeContext;
|
||||
private [_helperCtx]: TypeContext;
|
||||
private [_ctx]: IDrawContext;
|
||||
private [_helperCtx]: IDrawContext;
|
||||
// private [_watcher]: Watcher;
|
||||
private [_watcher]: ScreenWatcher;
|
||||
private [_scroller]: Scroller;
|
||||
private [_screen]: Screen;
|
||||
// private [_tempData]: TempData;
|
||||
|
||||
constructor(mount: HTMLDivElement, opts: TypeBoardOptions) {
|
||||
constructor(mount: HTMLDivElement, opts: BoardOptions) {
|
||||
// this[_tempData] = new TempData(opts);
|
||||
|
||||
this[_mount] = mount;
|
||||
|
|
@ -104,15 +104,15 @@ export default class Board {
|
|||
return this[_helperCtx].getContext();
|
||||
}
|
||||
|
||||
getContext(): TypeContext {
|
||||
getContext(): IDrawContext {
|
||||
return this[_ctx];
|
||||
}
|
||||
|
||||
getHelperContext(): TypeContext {
|
||||
getHelperContext(): IDrawContext {
|
||||
return this[_helperCtx];
|
||||
}
|
||||
|
||||
scale(scaleRatio: number): TypeScreenContext {
|
||||
scale(scaleRatio: number): ScreenContext {
|
||||
if (scaleRatio > 0) {
|
||||
this[_ctx].setTransform({ scale: scaleRatio });
|
||||
this[_helperCtx].setTransform({ scale: scaleRatio });
|
||||
|
|
@ -149,7 +149,7 @@ export default class Board {
|
|||
return { position, size };
|
||||
}
|
||||
|
||||
scrollY(y: number): TypeScreenContext {
|
||||
scrollY(y: number): ScreenContext {
|
||||
this[_watcher].setStatusMap({
|
||||
canScrollYPrev: true,
|
||||
canScrollYNext: true,
|
||||
|
|
@ -181,7 +181,7 @@ export default class Board {
|
|||
return this[_ctx].getTransform();
|
||||
}
|
||||
|
||||
draw(): TypeScreenContext {
|
||||
draw(): ScreenContext {
|
||||
this.clear();
|
||||
const { position, deviceSize, size } = this[_screen].calcScreen();
|
||||
const displayCtx = this[_displayCanvas].getContext('2d');
|
||||
|
|
@ -230,9 +230,9 @@ export default class Board {
|
|||
}
|
||||
|
||||
getScreenInfo(): {
|
||||
size: TypeScreenSize;
|
||||
position: TypeScreenPosition;
|
||||
deviceSize: TypeScreenSize;
|
||||
size: ScreenSize;
|
||||
position: ScreenPosition;
|
||||
deviceSize: ScreenSize;
|
||||
width: number;
|
||||
height: number;
|
||||
devicePixelRatio: number;
|
||||
|
|
@ -241,7 +241,7 @@ export default class Board {
|
|||
return this[_screen].calcScreen();
|
||||
}
|
||||
|
||||
setCursor(cursor: TypePointCursor) {
|
||||
setCursor(cursor: PointCursor) {
|
||||
this[_displayCanvas].style.cursor = cursor;
|
||||
}
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ export default class Board {
|
|||
this[_displayCanvas].style.cursor = 'auto';
|
||||
}
|
||||
|
||||
resetSize(opts: TypeBoardSizeOptions) {
|
||||
resetSize(opts: BoardSizeOptions) {
|
||||
this[_opts] = { ...this[_opts], ...opts };
|
||||
this[_resetContext]();
|
||||
this[_ctx].resetSize(opts);
|
||||
|
|
@ -271,7 +271,7 @@ export default class Board {
|
|||
return lineWidth;
|
||||
}
|
||||
|
||||
pointScreenToContext(screenPoint: TypePoint): TypePoint {
|
||||
pointScreenToContext(screenPoint: Point): Point {
|
||||
const { scrollX, scrollY, scale } = this.getTransform();
|
||||
const ctxPoint = {
|
||||
x: (screenPoint.x - scrollX) / scale,
|
||||
|
|
@ -280,7 +280,7 @@ export default class Board {
|
|||
return ctxPoint;
|
||||
}
|
||||
|
||||
pointContextToScreen(ctxPoint: TypePoint): TypePoint {
|
||||
pointContextToScreen(ctxPoint: Point): Point {
|
||||
const { scrollX, scrollY, scale } = this.getTransform();
|
||||
const screenPoint = {
|
||||
x: ctxPoint.x * scale + scrollX,
|
||||
|
|
@ -316,7 +316,7 @@ export default class Board {
|
|||
});
|
||||
}
|
||||
|
||||
private [_parsePrivateOptions](opts: TypeBoardOptions): PrivateOptions {
|
||||
private [_parsePrivateOptions](opts: BoardOptions): PrivateOptions {
|
||||
const defaultOpts = {
|
||||
devicePixelRatio: 1
|
||||
};
|
||||
|
|
@ -344,7 +344,7 @@ export default class Board {
|
|||
let scrollType: 'x' | 'y' | null = null;
|
||||
this.on(
|
||||
'moveStart',
|
||||
throttle((p: TypePoint) => {
|
||||
throttle((p: Point) => {
|
||||
if (this[_scroller].isPointAtScrollX(p)) {
|
||||
scrollType = 'x';
|
||||
} else if (this[_scroller].isPointAtScrollY(p)) {
|
||||
|
|
@ -355,7 +355,7 @@ export default class Board {
|
|||
|
||||
this.on(
|
||||
'move',
|
||||
throttle((p: TypePoint) => {
|
||||
throttle((p: Point) => {
|
||||
if (scrollType) {
|
||||
this[_doMoveScroll](scrollType, p);
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@ export default class Board {
|
|||
|
||||
this.on(
|
||||
'moveEnd',
|
||||
throttle((p: TypePoint) => {
|
||||
throttle((p: Point) => {
|
||||
if (scrollType) {
|
||||
this[_doMoveScroll](scrollType, p);
|
||||
}
|
||||
|
|
@ -372,7 +372,7 @@ export default class Board {
|
|||
}, 16)
|
||||
);
|
||||
|
||||
// this.on('doubleClick', (p: TypePoint) => {})
|
||||
// this.on('doubleClick', (p: Point) => {})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ export default class Board {
|
|||
this.draw();
|
||||
}
|
||||
|
||||
private [_doMoveScroll](scrollType: 'x' | 'y', point: TypePoint) {
|
||||
private [_doMoveScroll](scrollType: 'x' | 'y', point: Point) {
|
||||
if (!scrollType) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,43 @@
|
|||
import { TypePoint } from '@idraw/types';
|
||||
import { Point } from '@idraw/types';
|
||||
|
||||
export interface TypeBoardEventArgMap {
|
||||
'doubleClick': TypePoint;
|
||||
'hover': TypePoint;
|
||||
'leave': void;
|
||||
'point': TypePoint;
|
||||
'move': TypePoint;
|
||||
'moveStart': TypePoint;
|
||||
'moveEnd': TypePoint;
|
||||
'wheelX': number;
|
||||
'wheelY': number;
|
||||
doubleClick: Point;
|
||||
hover: Point;
|
||||
leave: void;
|
||||
point: Point;
|
||||
move: Point;
|
||||
moveStart: Point;
|
||||
moveEnd: Point;
|
||||
wheelX: number;
|
||||
wheelY: number;
|
||||
}
|
||||
|
||||
export interface TypeBoardEvent {
|
||||
on<T extends keyof TypeBoardEventArgMap >(key: T, callback: (p: TypeBoardEventArgMap[T]) => void): void
|
||||
off<T extends keyof TypeBoardEventArgMap >(key: T, callback: (p: TypeBoardEventArgMap[T]) => void): void
|
||||
trigger<T extends keyof TypeBoardEventArgMap >(key: T, p: TypeBoardEventArgMap[T]): void
|
||||
on<T extends keyof TypeBoardEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeBoardEventArgMap[T]) => void
|
||||
): void;
|
||||
off<T extends keyof TypeBoardEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeBoardEventArgMap[T]) => void
|
||||
): void;
|
||||
trigger<T extends keyof TypeBoardEventArgMap>(
|
||||
key: T,
|
||||
p: TypeBoardEventArgMap[T]
|
||||
): void;
|
||||
}
|
||||
|
||||
|
||||
export class BoardEvent implements TypeBoardEvent {
|
||||
|
||||
private _listeners: Map<string, ((p: any) => void)[]>;
|
||||
|
||||
constructor() {
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
||||
on<T extends keyof TypeBoardEventArgMap >(eventKey: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
|
||||
on<T extends keyof TypeBoardEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeBoardEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
callbacks?.push(callback);
|
||||
|
|
@ -36,8 +46,11 @@ export class BoardEvent implements TypeBoardEvent {
|
|||
this._listeners.set(eventKey, [callback]);
|
||||
}
|
||||
}
|
||||
|
||||
off<T extends keyof TypeBoardEventArgMap >(eventKey: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
|
||||
|
||||
off<T extends keyof TypeBoardEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeBoardEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
|
|
@ -52,7 +65,10 @@ export class BoardEvent implements TypeBoardEvent {
|
|||
}
|
||||
}
|
||||
|
||||
trigger<T extends keyof TypeBoardEventArgMap >(eventKey: T, arg: TypeBoardEventArgMap[T]) {
|
||||
trigger<T extends keyof TypeBoardEventArgMap>(
|
||||
eventKey: T,
|
||||
arg: TypeBoardEventArgMap[T]
|
||||
) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.forEach((cb) => {
|
||||
|
|
@ -64,14 +80,14 @@ export class BoardEvent implements TypeBoardEvent {
|
|||
}
|
||||
}
|
||||
|
||||
has<T extends keyof TypeBoardEventArgMap> (name: string) {
|
||||
has<T extends keyof TypeBoardEventArgMap>(name: string) {
|
||||
if (this._listeners.has(name)) {
|
||||
const list: ((p: TypeBoardEventArgMap[T]) => void)[] | undefined = this._listeners.get(name);
|
||||
const list: ((p: TypeBoardEventArgMap[T]) => void)[] | undefined =
|
||||
this._listeners.get(name);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { TypePoint, TypeContext } from '@idraw/types';
|
||||
import { Point, IDrawContext } from '@idraw/types';
|
||||
import { BoardEvent, TypeBoardEventArgMap } from './event';
|
||||
import { TempData } from './watcher-temp';
|
||||
|
||||
|
|
@ -16,9 +16,9 @@ export class ScreenWatcher {
|
|||
private _event: BoardEvent;
|
||||
private _temp: TempData = new TempData();
|
||||
private _container: HTMLElement | Window = window;
|
||||
// private _ctx: TypeContext;
|
||||
// private _ctx: IDrawContext;
|
||||
|
||||
constructor(canvas: HTMLCanvasElement, ctx: TypeContext) {
|
||||
constructor(canvas: HTMLCanvasElement, ctx: IDrawContext) {
|
||||
this._canvas = canvas;
|
||||
this._isMoving = false;
|
||||
this._initEvent();
|
||||
|
|
@ -328,7 +328,7 @@ export class ScreenWatcher {
|
|||
}
|
||||
}
|
||||
|
||||
_getPosition(e: MouseEvent | TouchEvent): TypePoint {
|
||||
_getPosition(e: MouseEvent | TouchEvent): Point {
|
||||
const canvas = this._canvas;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
|
@ -356,7 +356,7 @@ export class ScreenWatcher {
|
|||
return p;
|
||||
}
|
||||
|
||||
private _isVaildPoint(p: TypePoint): boolean {
|
||||
private _isVaildPoint(p: Point): boolean {
|
||||
return isAvailableNum(p.x) && isAvailableNum(p.y);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import {
|
||||
TypeBoardSizeOptions, TypeScreenPosition,
|
||||
TypeContext, TypeScreenSize,
|
||||
BoardSizeOptions,
|
||||
ScreenPosition,
|
||||
IDrawContext,
|
||||
ScreenSize
|
||||
} from '@idraw/types';
|
||||
|
||||
type Options = {
|
||||
|
|
@ -9,37 +11,43 @@ type Options = {
|
|||
contextWidth: number;
|
||||
contextHeight: number;
|
||||
devicePixelRatio: number;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const _opts = Symbol('_opts');
|
||||
const _ctx = Symbol('_ctx');
|
||||
|
||||
export class Screen {
|
||||
private [_opts]: Options;
|
||||
private [_ctx]: TypeContext;
|
||||
|
||||
constructor(ctx: TypeContext, opts: Options) {
|
||||
private [_ctx]: IDrawContext;
|
||||
|
||||
constructor(ctx: IDrawContext, opts: Options) {
|
||||
this[_opts] = opts;
|
||||
this[_ctx] = ctx;
|
||||
}
|
||||
|
||||
resetSize(opts: TypeBoardSizeOptions) {
|
||||
this[_opts] = {...this[_opts], ...opts};
|
||||
resetSize(opts: BoardSizeOptions) {
|
||||
this[_opts] = { ...this[_opts], ...opts };
|
||||
}
|
||||
|
||||
calcScreen(): {
|
||||
size: TypeScreenSize, position: TypeScreenPosition, deviceSize: TypeScreenSize,
|
||||
width: number, height: number, devicePixelRatio: number,
|
||||
canScrollXPrev: boolean,
|
||||
canScrollXNext: boolean,
|
||||
canScrollYPrev: boolean,
|
||||
canScrollYNext: boolean,
|
||||
size: ScreenSize;
|
||||
position: ScreenPosition;
|
||||
deviceSize: ScreenSize;
|
||||
width: number;
|
||||
height: number;
|
||||
devicePixelRatio: number;
|
||||
canScrollXPrev: boolean;
|
||||
canScrollXNext: boolean;
|
||||
canScrollYPrev: boolean;
|
||||
canScrollYNext: boolean;
|
||||
} {
|
||||
const scaleRatio = this[_ctx].getTransform().scale;
|
||||
const {
|
||||
width, height, contextWidth, contextHeight,
|
||||
devicePixelRatio: pxRatio,
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
contextWidth,
|
||||
contextHeight,
|
||||
devicePixelRatio: pxRatio
|
||||
} = this[_opts];
|
||||
|
||||
let canScrollXPrev: boolean = true;
|
||||
|
|
@ -51,7 +59,7 @@ export class Screen {
|
|||
if (contextWidth * scaleRatio <= width) {
|
||||
// make context center
|
||||
this[_ctx].setTransform({
|
||||
scrollX: (width - contextWidth * scaleRatio) / 2,
|
||||
scrollX: (width - contextWidth * scaleRatio) / 2
|
||||
});
|
||||
canScrollXPrev = false;
|
||||
canScrollXNext = false;
|
||||
|
|
@ -60,21 +68,27 @@ export class Screen {
|
|||
if (contextHeight * scaleRatio <= height) {
|
||||
// make context center
|
||||
this[_ctx].setTransform({
|
||||
scrollY: (height - contextHeight * scaleRatio) / 2,
|
||||
scrollY: (height - contextHeight * scaleRatio) / 2
|
||||
});
|
||||
canScrollYPrev = false;
|
||||
canScrollYNext = false;
|
||||
}
|
||||
|
||||
if (contextWidth * scaleRatio >= width && this[_ctx].getTransform().scrollX > 0) {
|
||||
if (
|
||||
contextWidth * scaleRatio >= width &&
|
||||
this[_ctx].getTransform().scrollX > 0
|
||||
) {
|
||||
this[_ctx].setTransform({
|
||||
scrollX: 0,
|
||||
scrollX: 0
|
||||
});
|
||||
canScrollXPrev = false;
|
||||
}
|
||||
if (contextHeight * scaleRatio >= height && this[_ctx].getTransform().scrollY > 0) {
|
||||
if (
|
||||
contextHeight * scaleRatio >= height &&
|
||||
this[_ctx].getTransform().scrollY > 0
|
||||
) {
|
||||
this[_ctx].setTransform({
|
||||
scrollY: 0,
|
||||
scrollY: 0
|
||||
});
|
||||
canScrollYPrev = false;
|
||||
}
|
||||
|
|
@ -82,13 +96,19 @@ export class Screen {
|
|||
const { scrollX: _scrollX, scrollY: _scrollY } = this[_ctx].getTransform();
|
||||
|
||||
// reset scroll
|
||||
if (_scrollX < 0 && Math.abs(_scrollX) > Math.abs(contextWidth * scaleRatio - width)) {
|
||||
if (
|
||||
_scrollX < 0 &&
|
||||
Math.abs(_scrollX) > Math.abs(contextWidth * scaleRatio - width)
|
||||
) {
|
||||
this[_ctx].setTransform({
|
||||
scrollX: 0 - Math.abs(contextWidth * scaleRatio - width)
|
||||
});
|
||||
canScrollXNext = false;
|
||||
}
|
||||
if (_scrollY < 0 && Math.abs(_scrollY) > Math.abs(contextHeight * scaleRatio - height)) {
|
||||
if (
|
||||
_scrollY < 0 &&
|
||||
Math.abs(_scrollY) > Math.abs(contextHeight * scaleRatio - height)
|
||||
) {
|
||||
this[_ctx].setTransform({
|
||||
scrollY: 0 - Math.abs(contextHeight * scaleRatio - height)
|
||||
});
|
||||
|
|
@ -101,19 +121,19 @@ export class Screen {
|
|||
x: scrollX * scaleRatio,
|
||||
y: scrollY * scaleRatio,
|
||||
w: contextWidth * scaleRatio,
|
||||
h: contextHeight * scaleRatio,
|
||||
h: contextHeight * scaleRatio
|
||||
};
|
||||
const deviceSize = {
|
||||
x: scrollX * pxRatio,
|
||||
y: scrollY * pxRatio,
|
||||
w: contextWidth * pxRatio * scaleRatio,
|
||||
h: contextHeight * pxRatio * scaleRatio,
|
||||
h: contextHeight * pxRatio * scaleRatio
|
||||
};
|
||||
const position = {
|
||||
top: scrollY,
|
||||
bottom: height - (contextHeight * scaleRatio + scrollY),
|
||||
left: scrollX,
|
||||
right: width - (contextWidth * scaleRatio + scrollX),
|
||||
right: width - (contextWidth * scaleRatio + scrollX)
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
@ -126,11 +146,16 @@ export class Screen {
|
|||
canScrollYPrev,
|
||||
canScrollYNext,
|
||||
canScrollXPrev,
|
||||
canScrollXNext,
|
||||
canScrollXNext
|
||||
};
|
||||
}
|
||||
|
||||
calcScreenScroll( start: number, end: number, sliderSize: number, limitLen: number, moveDistance: number
|
||||
calcScreenScroll(
|
||||
start: number,
|
||||
end: number,
|
||||
sliderSize: number,
|
||||
limitLen: number,
|
||||
moveDistance: number
|
||||
): number {
|
||||
let scrollDistance = start;
|
||||
let scrollLen = limitLen - sliderSize;
|
||||
|
|
@ -141,8 +166,7 @@ export class Screen {
|
|||
if (scrollLen > 0) {
|
||||
unit = scrollLen / (limitLen - sliderSize);
|
||||
}
|
||||
scrollDistance = 0 - unit * moveDistance;
|
||||
scrollDistance = 0 - unit * moveDistance;
|
||||
return scrollDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
import {
|
||||
TypePoint,
|
||||
TypeScreenPosition,
|
||||
TypeBoardScrollConfig
|
||||
} from '@idraw/types';
|
||||
import { Point, ScreenPosition, BoardScrollConfig } from '@idraw/types';
|
||||
import { isColorStr } from '@idraw/util';
|
||||
|
||||
type TypeOptions = {
|
||||
width: number;
|
||||
height: number;
|
||||
devicePixelRatio: number;
|
||||
scrollConfig?: TypeBoardScrollConfig;
|
||||
scrollConfig?: BoardScrollConfig;
|
||||
};
|
||||
|
||||
type TypePrivateOptions = Required<
|
||||
TypeOptions & { scrollConfig: Required<TypeBoardScrollConfig> }
|
||||
TypeOptions & { scrollConfig: Required<BoardScrollConfig> }
|
||||
>;
|
||||
|
||||
const minScrollerWidth = 12;
|
||||
const scrollerAlpha = 0.12;
|
||||
const scrollerThumbAlpha = 0.36;
|
||||
|
||||
const defaultScrollConfig: Partial<TypeBoardScrollConfig> & {
|
||||
const defaultScrollConfig: Partial<BoardScrollConfig> & {
|
||||
width: number;
|
||||
color: string;
|
||||
} = {
|
||||
|
|
@ -38,7 +34,7 @@ export class Scroller {
|
|||
this._opts = this._getOpts(opts);
|
||||
}
|
||||
|
||||
draw(position: TypeScreenPosition) {
|
||||
draw(position: ScreenPosition) {
|
||||
const { width, height, scrollConfig } = this._opts;
|
||||
const wrapper = this.calc(position);
|
||||
const ctx = this._displayCtx;
|
||||
|
|
@ -102,7 +98,7 @@ export class Scroller {
|
|||
this._opts = { ...this._opts, ...opts };
|
||||
}
|
||||
|
||||
isPointAtScrollY(p: TypePoint): boolean {
|
||||
isPointAtScrollY(p: Point): boolean {
|
||||
const { width, height, scrollConfig } = this._opts;
|
||||
const ctx = this._displayCtx;
|
||||
ctx.beginPath();
|
||||
|
|
@ -119,7 +115,7 @@ export class Scroller {
|
|||
return false;
|
||||
}
|
||||
|
||||
isPointAtScrollX(p: TypePoint): boolean {
|
||||
isPointAtScrollX(p: Point): boolean {
|
||||
const { width, height, scrollConfig } = this._opts;
|
||||
const ctx = this._displayCtx;
|
||||
ctx.beginPath();
|
||||
|
|
@ -141,7 +137,7 @@ export class Scroller {
|
|||
return lineWidth;
|
||||
}
|
||||
|
||||
calc(position: TypeScreenPosition) {
|
||||
calc(position: ScreenPosition) {
|
||||
const { width, height, scrollConfig } = this._opts;
|
||||
const sliderMinSize = scrollConfig.width * 2.5;
|
||||
const lineSize = scrollConfig.width;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { TypeBoardOptions, TypeContext } from '@idraw/types';
|
||||
import { BoardOptions, IDrawContext } from '@idraw/types';
|
||||
import { Context } from '@idraw/util';
|
||||
|
||||
type TempDataDesc = {
|
||||
ctx: TypeContext,
|
||||
}
|
||||
ctx: IDrawContext;
|
||||
};
|
||||
|
||||
function createDefaultData(opts: TypeBoardOptions) {
|
||||
function createDefaultData(opts: BoardOptions) {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx2d = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
const ctx = new Context(ctx2d, {
|
||||
|
|
@ -13,34 +13,31 @@ function createDefaultData(opts: TypeBoardOptions) {
|
|||
height: opts.height,
|
||||
contextWidth: opts.contextWidth,
|
||||
contextHeight: opts.contextHeight,
|
||||
devicePixelRatio: opts.devicePixelRatio || window.devicePixelRatio || 1,
|
||||
devicePixelRatio: opts.devicePixelRatio || window.devicePixelRatio || 1
|
||||
});
|
||||
|
||||
return {
|
||||
plugins: [],
|
||||
ctx: ctx
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class TempData {
|
||||
private _temp: TempDataDesc;
|
||||
|
||||
private _temp: TempDataDesc
|
||||
|
||||
constructor(opts: TypeBoardOptions) {
|
||||
this._temp = createDefaultData(opts)
|
||||
constructor(opts: BoardOptions) {
|
||||
this._temp = createDefaultData(opts);
|
||||
}
|
||||
|
||||
set<T extends keyof TempDataDesc >(name: T, value: TempDataDesc[T]) {
|
||||
set<T extends keyof TempDataDesc>(name: T, value: TempDataDesc[T]) {
|
||||
this._temp[name] = value;
|
||||
}
|
||||
|
||||
get<T extends keyof TempDataDesc >(name: T): TempDataDesc[T] {
|
||||
get<T extends keyof TempDataDesc>(name: T): TempDataDesc[T] {
|
||||
return this._temp[name];
|
||||
}
|
||||
|
||||
clear(opts: TypeBoardOptions) {
|
||||
this._temp = createDefaultData(opts)
|
||||
clear(opts: BoardOptions) {
|
||||
this._temp = createDefaultData(opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { TypePoint } from '@idraw/types'
|
||||
import { Point } from '@idraw/types';
|
||||
|
||||
type TempDataDesc = {
|
||||
prevClickPoint: TypePoint & { t: number } | null,
|
||||
prevClickPoint: (Point & { t: number }) | null;
|
||||
isHoverCanvas: boolean;
|
||||
isDragCanvas: boolean;
|
||||
statusMap: {
|
||||
canScrollYPrev: boolean,
|
||||
canScrollYNext: boolean,
|
||||
canScrollXPrev: boolean,
|
||||
canScrollXNext: boolean,
|
||||
}
|
||||
}
|
||||
canScrollYPrev: boolean;
|
||||
canScrollYNext: boolean;
|
||||
canScrollXPrev: boolean;
|
||||
canScrollXNext: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
function createTempData() {
|
||||
return {
|
||||
|
|
@ -21,28 +21,27 @@ function createTempData() {
|
|||
canScrollYPrev: true,
|
||||
canScrollYNext: true,
|
||||
canScrollXPrev: true,
|
||||
canScrollXNext: true,
|
||||
canScrollXNext: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class TempData {
|
||||
|
||||
private _temp: TempDataDesc
|
||||
private _temp: TempDataDesc;
|
||||
|
||||
constructor() {
|
||||
this._temp = createTempData();
|
||||
}
|
||||
|
||||
set<T extends keyof TempDataDesc >(name: T, value: TempDataDesc[T]) {
|
||||
set<T extends keyof TempDataDesc>(name: T, value: TempDataDesc[T]) {
|
||||
this._temp[name] = value;
|
||||
}
|
||||
|
||||
get<T extends keyof TempDataDesc >(name: T): TempDataDesc[T] {
|
||||
get<T extends keyof TempDataDesc>(name: T): TempDataDesc[T] {
|
||||
return this._temp[name];
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._temp = createTempData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { TypePoint } from '@idraw/types';
|
||||
import { Point } from '@idraw/types';
|
||||
import { BoardEvent, TypeBoardEventArgMap } from './event';
|
||||
import { TempData } from './watcher-temp';
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ export class Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
_getPosition(e: MouseEvent | TouchEvent): TypePoint {
|
||||
_getPosition(e: MouseEvent | TouchEvent): Point {
|
||||
const canvas = this._canvas;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
|
@ -171,7 +171,7 @@ export class Watcher {
|
|||
return p;
|
||||
}
|
||||
|
||||
private _isVaildPoint(p: TypePoint): boolean {
|
||||
private _isVaildPoint(p: Point): boolean {
|
||||
return p.x > 0 && p.y > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import {
|
||||
TypeData,
|
||||
TypePoint,
|
||||
TypeBoardSizeOptions,
|
||||
TypeConfig,
|
||||
TypeConfigStrict,
|
||||
TypeElementBase,
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
TypeContext,
|
||||
TypeCoreOptions,
|
||||
TypeScreenContext,
|
||||
TypeScreenData
|
||||
IDrawData,
|
||||
Point,
|
||||
BoardSizeOptions,
|
||||
IDrawConfig,
|
||||
IDrawConfigStrict,
|
||||
DataElementBase,
|
||||
DataElement,
|
||||
DataElemDesc,
|
||||
IDrawContext,
|
||||
CoreOptions,
|
||||
ScreenContext,
|
||||
ScreenData
|
||||
} from '@idraw/types';
|
||||
import Board from '@idraw/board';
|
||||
import { deepClone } from '@idraw/util';
|
||||
import Renderer from '@idraw/renderer';
|
||||
import is, { TypeIs } from './lib/is';
|
||||
import check, { TypeCheck } from './lib/check';
|
||||
import is, { IsTypeUtil } from './lib/is';
|
||||
import check, { CheckTypeUtil } from './lib/check';
|
||||
import {
|
||||
Element,
|
||||
mergeConfig,
|
||||
|
|
@ -69,23 +69,19 @@ import {
|
|||
|
||||
export default class Core {
|
||||
private [_board]: Board;
|
||||
private [_data]: TypeData;
|
||||
private [_opts]: TypeCoreOptions;
|
||||
private [_config]: TypeConfigStrict;
|
||||
private [_data]: IDrawData;
|
||||
private [_opts]: CoreOptions;
|
||||
private [_config]: IDrawConfigStrict;
|
||||
private [_renderer]: Renderer;
|
||||
private [_element]: Element;
|
||||
private [_coreEvent]: CoreEvent = new CoreEvent();
|
||||
private [_tempData]: TempData = new TempData();
|
||||
private [_engine]: Engine;
|
||||
|
||||
static is: TypeIs = is;
|
||||
static check: TypeCheck = check;
|
||||
static is: IsTypeUtil = is;
|
||||
static check: CheckTypeUtil = check;
|
||||
|
||||
constructor(
|
||||
mount: HTMLDivElement,
|
||||
opts: TypeCoreOptions,
|
||||
config?: TypeConfig
|
||||
) {
|
||||
constructor(mount: HTMLDivElement, opts: CoreOptions, config?: IDrawConfig) {
|
||||
this[_data] = { elements: [] };
|
||||
this[_opts] = opts;
|
||||
this[_config] = mergeConfig(config || {});
|
||||
|
|
@ -190,11 +186,11 @@ export default class Core {
|
|||
return moveDownElement(this, uuid);
|
||||
}
|
||||
|
||||
updateElement(elem: TypeElement<keyof TypeElemDesc>) {
|
||||
updateElement(elem: DataElement<keyof DataElemDesc>) {
|
||||
return updateElement(this, elem);
|
||||
}
|
||||
|
||||
addElement(elem: TypeElementBase<keyof TypeElemDesc>): string | null {
|
||||
addElement(elem: DataElementBase<keyof DataElemDesc>): string | null {
|
||||
return addElement(this, elem);
|
||||
}
|
||||
|
||||
|
|
@ -203,14 +199,14 @@ export default class Core {
|
|||
}
|
||||
|
||||
insertElementBefore(
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
beforeUUID: string
|
||||
) {
|
||||
return insertElementBefore(this, elem, beforeUUID);
|
||||
}
|
||||
|
||||
insertElementBeforeIndex(
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
index: number
|
||||
) {
|
||||
return insertElementBeforeIndex(this, elem, index);
|
||||
|
|
@ -221,47 +217,47 @@ export default class Core {
|
|||
}
|
||||
|
||||
insertElementAfter(
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
beforeUUID: string
|
||||
) {
|
||||
return insertElementAfter(this, elem, beforeUUID);
|
||||
}
|
||||
|
||||
insertElementAfterIndex(
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
index: number
|
||||
) {
|
||||
return insertElementAfterIndex(this, elem, index);
|
||||
}
|
||||
|
||||
resetSize(opts: TypeBoardSizeOptions) {
|
||||
resetSize(opts: BoardSizeOptions) {
|
||||
this[_opts] = { ...this[_opts], ...opts };
|
||||
this[_board].resetSize(opts);
|
||||
this[_draw]();
|
||||
}
|
||||
|
||||
scale(ratio: number): TypeScreenContext {
|
||||
scale(ratio: number): ScreenContext {
|
||||
const screen = this[_board].scale(ratio);
|
||||
this[_draw]();
|
||||
this[_emitChangeScreen]();
|
||||
return screen;
|
||||
}
|
||||
|
||||
scrollLeft(left: number): TypeScreenContext {
|
||||
scrollLeft(left: number): ScreenContext {
|
||||
const screen = this[_board].scrollX(0 - left);
|
||||
this[_draw]();
|
||||
this[_emitChangeScreen]();
|
||||
return screen;
|
||||
}
|
||||
|
||||
scrollTop(top: number): TypeScreenContext {
|
||||
scrollTop(top: number): ScreenContext {
|
||||
const screen = this[_board].scrollY(0 - top);
|
||||
this[_draw]();
|
||||
this[_emitChangeScreen]();
|
||||
return screen;
|
||||
}
|
||||
|
||||
getScreenTransform(): TypeScreenData {
|
||||
getScreenTransform(): ScreenData {
|
||||
const transform = this[_board].getTransform();
|
||||
return {
|
||||
scale: transform.scale,
|
||||
|
|
@ -270,11 +266,11 @@ export default class Core {
|
|||
};
|
||||
}
|
||||
|
||||
getData(): TypeData {
|
||||
getData(): IDrawData {
|
||||
return deepClone(this[_data]);
|
||||
}
|
||||
|
||||
setData(data: any | TypeData, opts?: { triggerChangeEvent: boolean }): void {
|
||||
setData(data: any | IDrawData, opts?: { triggerChangeEvent: boolean }): void {
|
||||
const resourceChangeUUIDs = diffElementResourceChangeList(
|
||||
this[_data],
|
||||
data
|
||||
|
|
@ -305,15 +301,15 @@ export default class Core {
|
|||
this[_coreEvent].off(key, callback);
|
||||
}
|
||||
|
||||
pointScreenToContext(p: TypePoint) {
|
||||
pointScreenToContext(p: Point) {
|
||||
return this[_board].pointScreenToContext(p);
|
||||
}
|
||||
|
||||
pointContextToScreen(p: TypePoint) {
|
||||
pointContextToScreen(p: Point) {
|
||||
return this[_board].pointContextToScreen(p);
|
||||
}
|
||||
|
||||
__getBoardContext(): TypeContext {
|
||||
__getBoardContext(): IDrawContext {
|
||||
return this[_board].getContext();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,30 @@
|
|||
import {
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
TypePoint,
|
||||
} from '@idraw/types';
|
||||
|
||||
import { DataElement, DataElemDesc, Point } from '@idraw/types';
|
||||
|
||||
export function parseRadianToAngle(radian: number): number {
|
||||
return radian / Math.PI * 180;
|
||||
return (radian / Math.PI) * 180;
|
||||
}
|
||||
|
||||
export function parseAngleToRadian(angle: number): number {
|
||||
return angle / 180 * Math.PI;
|
||||
return (angle / 180) * Math.PI;
|
||||
}
|
||||
|
||||
export function calcElementCenter(elem: TypeElement<keyof TypeElemDesc>): TypePoint {
|
||||
export function calcElementCenter(
|
||||
elem: DataElement<keyof DataElemDesc>
|
||||
): Point {
|
||||
const p = {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y + elem.h / 2,
|
||||
y: elem.y + elem.h / 2
|
||||
};
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
export function calcRadian(center: TypePoint, start: TypePoint, end: TypePoint): number {
|
||||
export function calcRadian(center: Point, start: Point, end: Point): number {
|
||||
const startAngle = calcLineAngle(center, start);
|
||||
const endAngle = calcLineAngle(center, end);
|
||||
if (endAngle !== null && startAngle !== null ) {
|
||||
if (startAngle > Math.PI * 3 / 2 && endAngle < Math.PI / 2) {
|
||||
if (endAngle !== null && startAngle !== null) {
|
||||
if (startAngle > (Math.PI * 3) / 2 && endAngle < Math.PI / 2) {
|
||||
return endAngle + (Math.PI * 2 - startAngle);
|
||||
} else if (endAngle > Math.PI * 3 / 2 && startAngle < Math.PI / 2) {
|
||||
} else if (endAngle > (Math.PI * 3) / 2 && startAngle < Math.PI / 2) {
|
||||
return startAngle + (Math.PI * 2 - endAngle);
|
||||
} else {
|
||||
return endAngle - startAngle;
|
||||
|
|
@ -38,14 +34,14 @@ export function calcRadian(center: TypePoint, start: TypePoint, end: TypePoint):
|
|||
}
|
||||
}
|
||||
|
||||
function calcLineAngle(center: TypePoint, p: TypePoint): number | null {
|
||||
function calcLineAngle(center: Point, p: Point): number | null {
|
||||
const x = p.x - center.x;
|
||||
const y = center.y - p.y;
|
||||
if (x === 0) {
|
||||
if (y < 0) {
|
||||
return Math.PI / 2;
|
||||
} else if (y > 0) {
|
||||
return Math.PI * ( 3 / 2 );
|
||||
return Math.PI * (3 / 2);
|
||||
}
|
||||
} else if (y === 0) {
|
||||
if (x < 0) {
|
||||
|
|
@ -64,4 +60,4 @@ function calcLineAngle(center: TypePoint, p: TypePoint): number | null {
|
|||
return Math.PI * 2 - Math.atan(Math.abs(y) / Math.abs(x));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,18 @@
|
|||
|
||||
import { TypeElementAttrs } from '@idraw/types';
|
||||
import { DataElementAttrs } from '@idraw/types';
|
||||
import is from './is';
|
||||
|
||||
|
||||
function attrs(
|
||||
attrs: TypeElementAttrs
|
||||
): boolean {
|
||||
function attrs(attrs: DataElementAttrs): boolean {
|
||||
const { x, y, w, h, angle } = attrs;
|
||||
if (!(is.x(x) && is.y(y) && is.w(w) && is.h(h) && is.angle(angle))) {
|
||||
return false;
|
||||
}
|
||||
if (!(angle >= -360 && angle <= 360 )) {
|
||||
if (!(angle >= -360 && angle <= 360)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function box(
|
||||
desc: any = {},
|
||||
): boolean {
|
||||
function box(desc: any = {}): boolean {
|
||||
const { borderColor, borderRadius, borderWidth } = desc;
|
||||
if (desc.hasOwnProperty('borderColor') && !is.color(borderColor)) {
|
||||
return false;
|
||||
|
|
@ -32,9 +26,7 @@ function box(
|
|||
return true;
|
||||
}
|
||||
|
||||
function rectDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function rectDesc(desc: any): boolean {
|
||||
const { bgColor } = desc;
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
|
|
@ -45,9 +37,7 @@ function rectDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function circleDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function circleDesc(desc: any): boolean {
|
||||
const { bgColor, borderColor, borderWidth } = desc;
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
|
|
@ -61,10 +51,7 @@ function circleDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
function imageDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function imageDesc(desc: any): boolean {
|
||||
const { src } = desc;
|
||||
if (!is.imageSrc(src)) {
|
||||
return false;
|
||||
|
|
@ -72,9 +59,7 @@ function imageDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function svgDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function svgDesc(desc: any): boolean {
|
||||
const { svg } = desc;
|
||||
if (!is.svg(svg)) {
|
||||
return false;
|
||||
|
|
@ -82,9 +67,7 @@ function svgDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function htmlDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function htmlDesc(desc: any): boolean {
|
||||
const { html } = desc;
|
||||
if (!is.html(html)) {
|
||||
return false;
|
||||
|
|
@ -92,44 +75,50 @@ function htmlDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function textDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function textDesc(desc: any): boolean {
|
||||
const {
|
||||
text, color, fontSize, lineHeight, fontFamily, textAlign,
|
||||
fontWeight, bgColor, strokeWidth, strokeColor
|
||||
text,
|
||||
color,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
fontFamily,
|
||||
textAlign,
|
||||
fontWeight,
|
||||
bgColor,
|
||||
strokeWidth,
|
||||
strokeColor
|
||||
} = desc;
|
||||
if (!is.text(text)){
|
||||
if (!is.text(text)) {
|
||||
return false;
|
||||
}
|
||||
if (!is.color(color)){
|
||||
if (!is.color(color)) {
|
||||
return false;
|
||||
}
|
||||
if (!is.fontSize(fontSize)){
|
||||
if (!is.fontSize(fontSize)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)){
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('fontWeight') && !is.fontWeight(fontWeight)){
|
||||
if (desc.hasOwnProperty('fontWeight') && !is.fontWeight(fontWeight)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('lineHeight') && !is.lineHeight(lineHeight)){
|
||||
if (desc.hasOwnProperty('lineHeight') && !is.lineHeight(lineHeight)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('fontFamily') && !is.fontFamily(fontFamily)){
|
||||
if (desc.hasOwnProperty('fontFamily') && !is.fontFamily(fontFamily)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('textAlign') && !is.textAlign(textAlign)){
|
||||
if (desc.hasOwnProperty('textAlign') && !is.textAlign(textAlign)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('strokeWidth') && !is.strokeWidth(strokeWidth)){
|
||||
if (desc.hasOwnProperty('strokeWidth') && !is.strokeWidth(strokeWidth)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('strokeColor') && !is.color(strokeColor)){
|
||||
if (desc.hasOwnProperty('strokeColor') && !is.color(strokeColor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!box(desc)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -143,21 +132,19 @@ const check = {
|
|||
circleDesc,
|
||||
imageDesc,
|
||||
svgDesc,
|
||||
htmlDesc,
|
||||
htmlDesc
|
||||
};
|
||||
|
||||
type TypeCheck = {
|
||||
attrs: (value: any) => boolean,
|
||||
rectDesc: (value: any) => boolean,
|
||||
circleDesc: (value: any) => boolean,
|
||||
imageDesc: (value: any) => boolean,
|
||||
svgDesc: (value: any) => boolean,
|
||||
htmlDesc: (value: any) => boolean,
|
||||
textDesc: (value: any) => boolean,
|
||||
}
|
||||
|
||||
export {
|
||||
TypeCheck
|
||||
type CheckTypeUtil = {
|
||||
attrs: (value: any) => boolean;
|
||||
rectDesc: (value: any) => boolean;
|
||||
circleDesc: (value: any) => boolean;
|
||||
imageDesc: (value: any) => boolean;
|
||||
svgDesc: (value: any) => boolean;
|
||||
htmlDesc: (value: any) => boolean;
|
||||
textDesc: (value: any) => boolean;
|
||||
};
|
||||
|
||||
export default check;
|
||||
export { CheckTypeUtil };
|
||||
|
||||
export default check;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { TypeConfig, TypeConfigStrict } from '@idraw/types';
|
||||
import { IDrawConfig, IDrawConfigStrict } from '@idraw/types';
|
||||
import { deepClone } from '@idraw/util';
|
||||
|
||||
const defaultConfig: TypeConfigStrict = {
|
||||
const defaultConfig: IDrawConfigStrict = {
|
||||
elementWrapper: {
|
||||
color: '#0d85da',
|
||||
lockColor: '#aaaaaa',
|
||||
|
|
@ -11,7 +11,7 @@ const defaultConfig: TypeConfigStrict = {
|
|||
}
|
||||
};
|
||||
|
||||
function mergeConfig(config?: TypeConfig): TypeConfigStrict {
|
||||
function mergeConfig(config?: IDrawConfig): IDrawConfigStrict {
|
||||
const result = deepClone(defaultConfig);
|
||||
if (config) {
|
||||
if (config.elementWrapper) {
|
||||
|
|
|
|||
|
|
@ -1,50 +1,74 @@
|
|||
import {
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
TypePoint,
|
||||
TypeData,
|
||||
TypeScreenData,
|
||||
DataElement,
|
||||
DataElemDesc,
|
||||
Point,
|
||||
IDrawData,
|
||||
ScreenData
|
||||
} from '@idraw/types';
|
||||
|
||||
export type TypeCoreEventSelectBaseArg = {
|
||||
index: number | null;
|
||||
uuid: string | null;
|
||||
}
|
||||
};
|
||||
|
||||
export type TypeCoreEventArgMap = {
|
||||
error: any;
|
||||
mouseOverScreen: Point;
|
||||
mouseLeaveScreen: void;
|
||||
mouseOverElement: TypeCoreEventSelectBaseArg & {
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
mouseLeaveElement: TypeCoreEventSelectBaseArg & {
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
screenClickElement: TypeCoreEventSelectBaseArg & {
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
screenDoubleClickElement: TypeCoreEventSelectBaseArg & {
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
screenSelectElement: TypeCoreEventSelectBaseArg & {
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
screenMoveElementStart: TypeCoreEventSelectBaseArg & Point;
|
||||
screenMoveElementEnd: TypeCoreEventSelectBaseArg & Point;
|
||||
screenChangeElement: TypeCoreEventSelectBaseArg & {
|
||||
width: number;
|
||||
height: number;
|
||||
angle: number;
|
||||
};
|
||||
changeData: IDrawData;
|
||||
changeScreen: ScreenData;
|
||||
drawFrameComplete: void;
|
||||
drawFrame: void;
|
||||
};
|
||||
|
||||
export type TypeCoreEventArgMap = {
|
||||
'error': any;
|
||||
'mouseOverScreen': TypePoint,
|
||||
'mouseLeaveScreen': void,
|
||||
'mouseOverElement': TypeCoreEventSelectBaseArg & { element: TypeElement<keyof TypeElemDesc> }
|
||||
'mouseLeaveElement': TypeCoreEventSelectBaseArg & { element: TypeElement<keyof TypeElemDesc> }
|
||||
'screenClickElement': TypeCoreEventSelectBaseArg & { element: TypeElement<keyof TypeElemDesc> }
|
||||
'screenDoubleClickElement': TypeCoreEventSelectBaseArg & { element: TypeElement<keyof TypeElemDesc> }
|
||||
'screenSelectElement': TypeCoreEventSelectBaseArg & { element: TypeElement<keyof TypeElemDesc> }
|
||||
'screenMoveElementStart': TypeCoreEventSelectBaseArg & TypePoint,
|
||||
'screenMoveElementEnd': TypeCoreEventSelectBaseArg & TypePoint,
|
||||
'screenChangeElement': TypeCoreEventSelectBaseArg & { width: number, height: number, angle: number};
|
||||
'changeData': TypeData;
|
||||
'changeScreen': TypeScreenData,
|
||||
'drawFrameComplete': void;
|
||||
'drawFrame': void;
|
||||
}
|
||||
|
||||
export interface TypeCoreEvent {
|
||||
on<T extends keyof TypeCoreEventArgMap >(key: T, callback: (p: TypeCoreEventArgMap[T]) => void): void
|
||||
off<T extends keyof TypeCoreEventArgMap >(key: T, callback: (p: TypeCoreEventArgMap[T]) => void): void
|
||||
trigger<T extends keyof TypeCoreEventArgMap >(key: T, p: TypeCoreEventArgMap[T]): void
|
||||
on<T extends keyof TypeCoreEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeCoreEventArgMap[T]) => void
|
||||
): void;
|
||||
off<T extends keyof TypeCoreEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeCoreEventArgMap[T]) => void
|
||||
): void;
|
||||
trigger<T extends keyof TypeCoreEventArgMap>(
|
||||
key: T,
|
||||
p: TypeCoreEventArgMap[T]
|
||||
): void;
|
||||
}
|
||||
|
||||
|
||||
export class CoreEvent implements TypeCoreEvent {
|
||||
|
||||
private _listeners: Map<string, ((p: any) => void)[]>;
|
||||
|
||||
constructor() {
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
||||
on<T extends keyof TypeCoreEventArgMap >(eventKey: T, callback: (p: TypeCoreEventArgMap[T]) => void) {
|
||||
on<T extends keyof TypeCoreEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeCoreEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
callbacks?.push(callback);
|
||||
|
|
@ -53,8 +77,11 @@ export class CoreEvent implements TypeCoreEvent {
|
|||
this._listeners.set(eventKey, [callback]);
|
||||
}
|
||||
}
|
||||
|
||||
off<T extends keyof TypeCoreEventArgMap >(eventKey: T, callback: (p: TypeCoreEventArgMap[T]) => void) {
|
||||
|
||||
off<T extends keyof TypeCoreEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeCoreEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
|
|
@ -69,7 +96,10 @@ export class CoreEvent implements TypeCoreEvent {
|
|||
}
|
||||
}
|
||||
|
||||
trigger<T extends keyof TypeCoreEventArgMap >(eventKey: T, arg: TypeCoreEventArgMap[T]) {
|
||||
trigger<T extends keyof TypeCoreEventArgMap>(
|
||||
eventKey: T,
|
||||
arg: TypeCoreEventArgMap[T]
|
||||
) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.forEach((cb) => {
|
||||
|
|
@ -81,14 +111,14 @@ export class CoreEvent implements TypeCoreEvent {
|
|||
}
|
||||
}
|
||||
|
||||
has<T extends keyof TypeCoreEventArgMap> (name: string) {
|
||||
has<T extends keyof TypeCoreEventArgMap>(name: string) {
|
||||
if (this._listeners.has(name)) {
|
||||
const list: ((p: TypeCoreEventArgMap[T]) => void)[] | undefined = this._listeners.get(name);
|
||||
const list: ((p: TypeCoreEventArgMap[T]) => void)[] | undefined =
|
||||
this._listeners.get(name);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +1,64 @@
|
|||
import { TypeElement, TypeData, TypeElemDesc } from '@idraw/types';
|
||||
|
||||
type TypeElementMap = {
|
||||
[uuid: string]: TypeElement<keyof TypeElemDesc>
|
||||
}
|
||||
import { DataElement, IDrawData, DataElemDesc } from '@idraw/types';
|
||||
|
||||
type DataElementMap = {
|
||||
[uuid: string]: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
|
||||
export function isChangeImageElementResource(
|
||||
before: TypeElement<'image'>,
|
||||
after: TypeElement<'image'>,
|
||||
before: DataElement<'image'>,
|
||||
after: DataElement<'image'>
|
||||
): boolean {
|
||||
return (before?.desc?.src !== after?.desc?.src);
|
||||
return before?.desc?.src !== after?.desc?.src;
|
||||
}
|
||||
|
||||
|
||||
export function isChangeSVGElementResource(
|
||||
before: TypeElement<'svg'>,
|
||||
after: TypeElement<'svg'>,
|
||||
before: DataElement<'svg'>,
|
||||
after: DataElement<'svg'>
|
||||
): boolean {
|
||||
return (before?.desc?.svg !== after?.desc?.svg);
|
||||
return before?.desc?.svg !== after?.desc?.svg;
|
||||
}
|
||||
|
||||
export function isChangeHTMLElementResource(
|
||||
before: TypeElement<'html'>,
|
||||
after: TypeElement<'html'>,
|
||||
before: DataElement<'html'>,
|
||||
after: DataElement<'html'>
|
||||
): boolean {
|
||||
return (
|
||||
before?.desc?.html !== after?.desc?.html
|
||||
|| before?.desc?.width !== after?.desc?.width
|
||||
|| before?.desc?.height !== after?.desc?.height
|
||||
before?.desc?.html !== after?.desc?.html ||
|
||||
before?.desc?.width !== after?.desc?.width ||
|
||||
before?.desc?.height !== after?.desc?.height
|
||||
);
|
||||
}
|
||||
|
||||
export function diffElementResourceChange(
|
||||
before: TypeElement<keyof TypeElemDesc>,
|
||||
after: TypeElement<keyof TypeElemDesc>,
|
||||
before: DataElement<keyof DataElemDesc>,
|
||||
after: DataElement<keyof DataElemDesc>
|
||||
): string | null {
|
||||
let result = null;
|
||||
let isChange = false;
|
||||
switch (after.type) {
|
||||
case 'image': {
|
||||
isChange = isChangeImageElementResource(
|
||||
before as TypeElement<'image'>,
|
||||
after as TypeElement<'image'>
|
||||
before as DataElement<'image'>,
|
||||
after as DataElement<'image'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'svg': {
|
||||
isChange = isChangeSVGElementResource(
|
||||
before as TypeElement<'svg'>,
|
||||
after as TypeElement<'svg'>
|
||||
before as DataElement<'svg'>,
|
||||
after as DataElement<'svg'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
isChange = isChangeHTMLElementResource(
|
||||
before as TypeElement<'html'>,
|
||||
after as TypeElement<'html'>
|
||||
before as DataElement<'html'>,
|
||||
after as DataElement<'html'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isChange === true) {
|
||||
result = after.uuid;
|
||||
|
|
@ -68,8 +67,8 @@ export function diffElementResourceChange(
|
|||
}
|
||||
|
||||
export function diffElementResourceChangeList(
|
||||
before: TypeData,
|
||||
after: TypeData,
|
||||
before: IDrawData,
|
||||
after: IDrawData
|
||||
): string[] {
|
||||
const uuids: string[] = [];
|
||||
const beforeMap = parseDataElementMap(before);
|
||||
|
|
@ -83,26 +82,27 @@ export function diffElementResourceChangeList(
|
|||
switch (beforeMap[uuid].type) {
|
||||
case 'image': {
|
||||
isChange = isChangeImageElementResource(
|
||||
beforeMap[uuid] as TypeElement<'image'>,
|
||||
afterMap[uuid] as TypeElement<'image'>
|
||||
beforeMap[uuid] as DataElement<'image'>,
|
||||
afterMap[uuid] as DataElement<'image'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'svg': {
|
||||
isChange = isChangeSVGElementResource(
|
||||
beforeMap[uuid] as TypeElement<'svg'>,
|
||||
afterMap[uuid] as TypeElement<'svg'>
|
||||
beforeMap[uuid] as DataElement<'svg'>,
|
||||
afterMap[uuid] as DataElement<'svg'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
isChange = isChangeHTMLElementResource(
|
||||
beforeMap[uuid] as TypeElement<'html'>,
|
||||
afterMap[uuid] as TypeElement<'html'>
|
||||
beforeMap[uuid] as DataElement<'html'>,
|
||||
afterMap[uuid] as DataElement<'html'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isChange === true) {
|
||||
uuids.push(uuid);
|
||||
|
|
@ -114,11 +114,10 @@ export function diffElementResourceChangeList(
|
|||
return uuids;
|
||||
}
|
||||
|
||||
|
||||
function parseDataElementMap(data: TypeData): TypeElementMap {
|
||||
const elemMap: TypeElementMap = {};
|
||||
function parseDataElementMap(data: IDrawData): DataElementMap {
|
||||
const elemMap: DataElementMap = {};
|
||||
data.elements.forEach((elem) => {
|
||||
elemMap[elem.uuid] = elem;
|
||||
})
|
||||
});
|
||||
return elemMap;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
TypeContext,
|
||||
// TypeElemDesc,
|
||||
TypeElement,
|
||||
IDrawContext,
|
||||
// DataElemDesc,
|
||||
DataElement
|
||||
} from '@idraw/types';
|
||||
import { istype, isColorStr } from '@idraw/util';
|
||||
import { rotateElement } from './../transform';
|
||||
import is from './../is';
|
||||
|
||||
export function clearContext(ctx: TypeContext) {
|
||||
export function clearContext(ctx: IDrawContext) {
|
||||
// ctx.setFillStyle('rgb(0 0 0 / 100%)');
|
||||
// ctx.setStrokeStyle('rgb(0 0 0 / 100%)');
|
||||
ctx.setFillStyle('#000000');
|
||||
|
|
@ -15,21 +15,21 @@ export function clearContext(ctx: TypeContext) {
|
|||
ctx.setLineDash([]);
|
||||
ctx.setGlobalAlpha(1);
|
||||
ctx.setShadowColor('#00000000');
|
||||
ctx.setShadowOffsetX(0)
|
||||
ctx.setShadowOffsetX(0);
|
||||
ctx.setShadowOffsetY(0);
|
||||
ctx.setShadowBlur(0);
|
||||
}
|
||||
|
||||
export function drawBgColor(ctx: TypeContext, color: string) {
|
||||
export function drawBgColor(ctx: IDrawContext, color: string) {
|
||||
const size = ctx.getSize();
|
||||
ctx.setFillStyle(color);
|
||||
ctx.fillRect(0, 0, size.contextWidth, size.contextHeight);
|
||||
}
|
||||
|
||||
export function drawBox(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'text' | 'rect'>,
|
||||
pattern: string | CanvasPattern | null,
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'text' | 'rect'>,
|
||||
pattern: string | CanvasPattern | null
|
||||
): void {
|
||||
clearContext(ctx);
|
||||
drawBoxBorder(ctx, elem);
|
||||
|
|
@ -47,20 +47,19 @@ export function drawBox(
|
|||
ctx.arcTo(x + w, y + h, x, y + h, r);
|
||||
ctx.arcTo(x, y + h, x, y, r);
|
||||
ctx.arcTo(x, y, x + w, y, r);
|
||||
ctx.closePath();
|
||||
ctx.closePath();
|
||||
if (typeof pattern === 'string') {
|
||||
ctx.setFillStyle(pattern);
|
||||
ctx.setFillStyle(pattern);
|
||||
} else if (['CanvasPattern'].includes(istype.type(pattern))) {
|
||||
ctx.setFillStyle(pattern as CanvasPattern);
|
||||
}
|
||||
ctx.fill();
|
||||
ctx.fill();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function drawBoxBorder(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'text'|'rect'>,
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'text' | 'rect'>
|
||||
): void {
|
||||
clearContext(ctx);
|
||||
rotateElement(ctx, elem, () => {
|
||||
|
|
@ -103,7 +102,7 @@ export function drawBoxBorder(
|
|||
ctx.arcTo(x + w, y + h, x, y + h, r);
|
||||
ctx.arcTo(x, y + h, x, y, r);
|
||||
ctx.arcTo(x, y, x + w, y, r);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { TypeContext, TypeHelperConfig } from '@idraw/types';
|
||||
import { IDrawContext, HelperConfig } from '@idraw/types';
|
||||
import { rotateContext } from './../transform';
|
||||
import { clearContext } from './base';
|
||||
|
||||
export function drawElementWrapper(ctx: TypeContext, config: TypeHelperConfig) {
|
||||
export function drawElementWrapper(ctx: IDrawContext, config: HelperConfig) {
|
||||
if (!config?.selectedElementWrapper) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ export function drawElementWrapper(ctx: TypeContext, config: TypeHelperConfig) {
|
|||
});
|
||||
}
|
||||
|
||||
export function drawAreaWrapper(ctx: TypeContext, config: TypeHelperConfig) {
|
||||
export function drawAreaWrapper(ctx: IDrawContext, config: HelperConfig) {
|
||||
if (!config?.selectedAreaWrapper) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -178,8 +178,8 @@ export function drawAreaWrapper(ctx: TypeContext, config: TypeHelperConfig) {
|
|||
}
|
||||
|
||||
export function drawElementListWrappers(
|
||||
ctx: TypeContext,
|
||||
config: TypeHelperConfig
|
||||
ctx: IDrawContext,
|
||||
config: HelperConfig
|
||||
) {
|
||||
if (!Array.isArray(config?.selectedElementListWrappers)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import {
|
||||
TypeContext,
|
||||
TypePoint,
|
||||
TypeData,
|
||||
TypeHelperWrapperControllerDirection,
|
||||
TypeElement,
|
||||
TypeElemDesc
|
||||
IDrawContext,
|
||||
Point,
|
||||
IDrawData,
|
||||
HelperWrapperControllerDirection,
|
||||
DataElement,
|
||||
DataElemDesc
|
||||
} from '@idraw/types';
|
||||
import { createUUID } from '@idraw/util';
|
||||
import { rotateElement } from './transform';
|
||||
|
|
@ -16,13 +16,13 @@ import { LIMIT_QBLIQUE_ANGLE } from './../constant/element';
|
|||
const limitQbliqueAngle = LIMIT_QBLIQUE_ANGLE;
|
||||
|
||||
export class Element {
|
||||
private _ctx: TypeContext;
|
||||
private _ctx: IDrawContext;
|
||||
|
||||
constructor(ctx: TypeContext) {
|
||||
constructor(ctx: IDrawContext) {
|
||||
this._ctx = ctx;
|
||||
}
|
||||
|
||||
initData(data: TypeData): TypeData {
|
||||
initData(data: IDrawData): IDrawData {
|
||||
data.elements.forEach((elem) => {
|
||||
if (!(elem.uuid && typeof elem.uuid === 'string')) {
|
||||
elem.uuid = createUUID();
|
||||
|
|
@ -31,7 +31,7 @@ export class Element {
|
|||
return data;
|
||||
}
|
||||
|
||||
isPointInElement(p: TypePoint, data: TypeData): [number, string | null] {
|
||||
isPointInElement(p: Point, data: IDrawData): [number, string | null] {
|
||||
const ctx = this._ctx;
|
||||
let idx = -1;
|
||||
let uuid = null;
|
||||
|
|
@ -67,10 +67,10 @@ export class Element {
|
|||
}
|
||||
|
||||
dragElement(
|
||||
data: TypeData,
|
||||
data: IDrawData,
|
||||
uuid: string,
|
||||
point: TypePoint,
|
||||
prevPoint: TypePoint,
|
||||
point: Point,
|
||||
prevPoint: Point,
|
||||
scale: number
|
||||
): void {
|
||||
const index = this.getElementIndex(data, uuid);
|
||||
|
|
@ -85,12 +85,12 @@ export class Element {
|
|||
}
|
||||
|
||||
transformElement(
|
||||
data: TypeData,
|
||||
data: IDrawData,
|
||||
uuid: string,
|
||||
point: TypePoint,
|
||||
prevPoint: TypePoint,
|
||||
point: Point,
|
||||
prevPoint: Point,
|
||||
scale: number,
|
||||
direction: TypeHelperWrapperControllerDirection
|
||||
direction: HelperWrapperControllerDirection
|
||||
): null | {
|
||||
width: number;
|
||||
height: number;
|
||||
|
|
@ -144,7 +144,7 @@ export class Element {
|
|||
};
|
||||
}
|
||||
|
||||
getElementIndex(data: TypeData, uuid: string): number {
|
||||
getElementIndex(data: IDrawData, uuid: string): number {
|
||||
let idx = -1;
|
||||
for (let i = 0; i < data.elements.length; i++) {
|
||||
if (data.elements[i].uuid === uuid) {
|
||||
|
|
@ -155,7 +155,7 @@ export class Element {
|
|||
return idx;
|
||||
}
|
||||
|
||||
limitElementAttrs(elem: TypeElement<keyof TypeElemDesc>) {
|
||||
limitElementAttrs(elem: DataElement<keyof DataElemDesc>) {
|
||||
elem.x = limitNum(elem.x);
|
||||
elem.y = limitNum(elem.y);
|
||||
elem.w = limitNum(elem.w);
|
||||
|
|
@ -165,12 +165,12 @@ export class Element {
|
|||
}
|
||||
|
||||
function calcuScaleElemPosition(
|
||||
elem: TypeElement<keyof TypeElemDesc>,
|
||||
elem: DataElement<keyof DataElemDesc>,
|
||||
moveX: number,
|
||||
moveY: number,
|
||||
direction: TypeHelperWrapperControllerDirection,
|
||||
direction: HelperWrapperControllerDirection,
|
||||
scale: number
|
||||
): TypePoint & { w: number; h: number } {
|
||||
): Point & { w: number; h: number } {
|
||||
const p = { x: elem.x, y: elem.y, w: elem.w, h: elem.h };
|
||||
let angle = elem.angle;
|
||||
if (angle < 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { TypeHelperWrapperControllerDirection, TypePoint } from '@idraw/types';
|
||||
import { HelperWrapperControllerDirection, Point } from '@idraw/types';
|
||||
import { Mode, CursorStatus } from '../constant/static';
|
||||
|
||||
type TempDataDesc = {
|
||||
|
|
@ -8,9 +8,9 @@ type TempDataDesc = {
|
|||
selectedUUID: string | null;
|
||||
selectedUUIDList: string[];
|
||||
hoverUUID: string | null;
|
||||
selectedControllerDirection: TypeHelperWrapperControllerDirection | null;
|
||||
hoverControllerDirection: TypeHelperWrapperControllerDirection | null;
|
||||
prevPoint: TypePoint | null;
|
||||
selectedControllerDirection: HelperWrapperControllerDirection | null;
|
||||
hoverControllerDirection: HelperWrapperControllerDirection | null;
|
||||
prevPoint: Point | null;
|
||||
hasChangedElement: boolean;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
TypePoint,
|
||||
TypeHelperWrapperControllerDirection,
|
||||
Point,
|
||||
HelperWrapperControllerDirection,
|
||||
InterfaceHelperPlugin,
|
||||
TypeConfigStrict,
|
||||
TypeData,
|
||||
TypeHelperConfig
|
||||
IDrawConfigStrict,
|
||||
IDrawData,
|
||||
HelperConfig
|
||||
} from '@idraw/types';
|
||||
import { deepClone, throttle } from '@idraw/util';
|
||||
import Board from '@idraw/board';
|
||||
|
|
@ -19,9 +19,9 @@ type Options = {
|
|||
coreEvent: CoreEvent;
|
||||
board: Board;
|
||||
element: Element;
|
||||
config: TypeConfigStrict;
|
||||
config: IDrawConfigStrict;
|
||||
drawFeekback: () => void;
|
||||
getDataFeekback: () => TypeData;
|
||||
getDataFeekback: () => IDrawData;
|
||||
selectElementByIndex: (index: number, opts?: { useMode?: boolean }) => void;
|
||||
emitChangeScreen: () => void;
|
||||
emitChangeData: () => void;
|
||||
|
|
@ -48,7 +48,7 @@ export class Engine {
|
|||
this._plugins.push(plugin);
|
||||
}
|
||||
|
||||
getHelperConfig(): TypeHelperConfig {
|
||||
getHelperConfig(): HelperConfig {
|
||||
return this.helper.getConfig();
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ export class Engine {
|
|||
board.on('moveEnd', this._handleMoveEnd.bind(this));
|
||||
}
|
||||
|
||||
private _handleDoubleClick(point: TypePoint) {
|
||||
private _handleDoubleClick(point: Point) {
|
||||
const { element, getDataFeekback, drawFeekback, coreEvent } = this._opts;
|
||||
const data = getDataFeekback();
|
||||
const [index, uuid] = element.isPointInElement(point, data);
|
||||
|
|
@ -110,7 +110,7 @@ export class Engine {
|
|||
drawFeekback();
|
||||
}
|
||||
|
||||
_handlePoint(point: TypePoint): void {
|
||||
_handlePoint(point: Point): void {
|
||||
if (!this._mapper.isEffectivePoint(point)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ export class Engine {
|
|||
drawFeekback();
|
||||
}
|
||||
|
||||
private _handleClick(point: TypePoint): void {
|
||||
private _handleClick(point: Point): void {
|
||||
const { element, getDataFeekback, coreEvent, drawFeekback } = this._opts;
|
||||
const data = getDataFeekback();
|
||||
const [index, uuid] = element.isPointInElement(point, data);
|
||||
|
|
@ -180,7 +180,7 @@ export class Engine {
|
|||
drawFeekback();
|
||||
}
|
||||
|
||||
private _handleMoveStart(point: TypePoint): void {
|
||||
private _handleMoveStart(point: Point): void {
|
||||
const { element, getDataFeekback, coreEvent } = this._opts;
|
||||
const data = getDataFeekback();
|
||||
const helper = this.helper;
|
||||
|
|
@ -204,7 +204,7 @@ export class Engine {
|
|||
}
|
||||
}
|
||||
|
||||
private _handleMove(point: TypePoint): void {
|
||||
private _handleMove(point: Point): void {
|
||||
const { drawFeekback } = this._opts;
|
||||
const helper = this.helper;
|
||||
if (this.temp.get('mode') === Mode.SELECT_ELEMENT_LIST) {
|
||||
|
|
@ -236,7 +236,7 @@ export class Engine {
|
|||
this.temp.get('prevPoint'),
|
||||
this.temp.get(
|
||||
'selectedControllerDirection'
|
||||
) as TypeHelperWrapperControllerDirection
|
||||
) as HelperWrapperControllerDirection
|
||||
);
|
||||
this.temp.set('cursorStatus', CursorStatus.DRAGGING);
|
||||
}
|
||||
|
|
@ -249,8 +249,8 @@ export class Engine {
|
|||
|
||||
private _dragElements(
|
||||
uuids: string[],
|
||||
point: TypePoint,
|
||||
prevPoint: TypePoint | null
|
||||
point: Point,
|
||||
prevPoint: Point | null
|
||||
): void {
|
||||
if (!prevPoint) {
|
||||
return;
|
||||
|
|
@ -280,9 +280,9 @@ export class Engine {
|
|||
|
||||
private _transfromElement(
|
||||
uuid: string,
|
||||
point: TypePoint,
|
||||
prevPoint: TypePoint | null,
|
||||
direction: TypeHelperWrapperControllerDirection
|
||||
point: Point,
|
||||
prevPoint: Point | null,
|
||||
direction: HelperWrapperControllerDirection
|
||||
): null | { width: number; height: number; angle: number } {
|
||||
if (!prevPoint) {
|
||||
return null;
|
||||
|
|
@ -301,7 +301,7 @@ export class Engine {
|
|||
return result;
|
||||
}
|
||||
|
||||
private _handleMoveEnd(point: TypePoint): void {
|
||||
private _handleMoveEnd(point: Point): void {
|
||||
const {
|
||||
element,
|
||||
getDataFeekback,
|
||||
|
|
@ -359,7 +359,7 @@ export class Engine {
|
|||
}
|
||||
}
|
||||
|
||||
private _handleHover(point: TypePoint): void {
|
||||
private _handleHover(point: Point): void {
|
||||
let isMouseOverElement = false;
|
||||
const { board, getDataFeekback, coreEvent } = this._opts;
|
||||
const data = getDataFeekback();
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import {
|
||||
TypeData,
|
||||
TypeHelper,
|
||||
TypeHelperConfig,
|
||||
TypeHelperUpdateOpts,
|
||||
TypeHelperWrapperControllerDirection,
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
TypeContext,
|
||||
TypePoint,
|
||||
TypeConfigStrict,
|
||||
TypeHeplerSelectedElementWrapper
|
||||
IDrawData,
|
||||
Helper,
|
||||
HelperConfig,
|
||||
HelperUpdateOpts,
|
||||
HelperWrapperControllerDirection,
|
||||
DataElement,
|
||||
DataElemDesc,
|
||||
IDrawContext,
|
||||
Point,
|
||||
IDrawConfigStrict,
|
||||
HeplerSelectedElementWrapper
|
||||
} from '@idraw/types';
|
||||
import Board from '@idraw/board';
|
||||
import { deepClone } from '@idraw/util';
|
||||
|
|
@ -20,15 +20,15 @@ import { LIMIT_QBLIQUE_ANGLE } from './../constant/element';
|
|||
|
||||
const limitQbliqueAngle = LIMIT_QBLIQUE_ANGLE;
|
||||
|
||||
export class Helper implements TypeHelper {
|
||||
private _helperConfig: TypeHelperConfig;
|
||||
private _coreConfig: TypeConfigStrict;
|
||||
private _ctx: TypeContext;
|
||||
export class Helper implements Helper {
|
||||
private _helperConfig: HelperConfig;
|
||||
private _coreConfig: IDrawConfigStrict;
|
||||
private _ctx: IDrawContext;
|
||||
private _board: Board;
|
||||
private _areaStart: TypePoint = { x: 0, y: 0 };
|
||||
private _areaEnd: TypePoint = { x: 0, y: 0 };
|
||||
private _areaStart: Point = { x: 0, y: 0 };
|
||||
private _areaEnd: Point = { x: 0, y: 0 };
|
||||
|
||||
constructor(board: Board, config: TypeConfigStrict) {
|
||||
constructor(board: Board, config: IDrawConfigStrict) {
|
||||
this._board = board;
|
||||
this._ctx = this._board.getContext();
|
||||
this._coreConfig = config;
|
||||
|
|
@ -37,13 +37,13 @@ export class Helper implements TypeHelper {
|
|||
};
|
||||
}
|
||||
|
||||
updateConfig(data: TypeData, opts: TypeHelperUpdateOpts): void {
|
||||
updateConfig(data: IDrawData, opts: HelperUpdateOpts): void {
|
||||
this._updateElementIndex(data);
|
||||
this._updateSelectedElementWrapper(data, opts);
|
||||
this._updateSelectedElementListWrapper(data, opts);
|
||||
}
|
||||
|
||||
getConfig(): TypeHelperConfig {
|
||||
getConfig(): HelperConfig {
|
||||
return deepClone(this._helperConfig);
|
||||
}
|
||||
|
||||
|
|
@ -56,20 +56,20 @@ export class Helper implements TypeHelper {
|
|||
}
|
||||
|
||||
isPointInElementWrapperController(
|
||||
p: TypePoint,
|
||||
data?: TypeData
|
||||
p: Point,
|
||||
data?: IDrawData
|
||||
): {
|
||||
uuid: string | null | undefined;
|
||||
selectedControllerDirection: TypeHelperWrapperControllerDirection | null;
|
||||
hoverControllerDirection: TypeHelperWrapperControllerDirection | null;
|
||||
selectedControllerDirection: HelperWrapperControllerDirection | null;
|
||||
hoverControllerDirection: HelperWrapperControllerDirection | null;
|
||||
directIndex: number | null;
|
||||
} {
|
||||
const ctx = this._ctx;
|
||||
const uuid = this._helperConfig?.selectedElementWrapper?.uuid || null;
|
||||
let directIndex = null;
|
||||
let selectedControllerDirection: TypeHelperWrapperControllerDirection | null =
|
||||
let selectedControllerDirection: HelperWrapperControllerDirection | null =
|
||||
null;
|
||||
let hoverControllerDirection: TypeHelperWrapperControllerDirection | null =
|
||||
let hoverControllerDirection: HelperWrapperControllerDirection | null =
|
||||
null;
|
||||
if (!this._helperConfig.selectedElementWrapper) {
|
||||
return {
|
||||
|
|
@ -90,7 +90,7 @@ export class Helper implements TypeHelper {
|
|||
wrapper.controllers.bottom,
|
||||
wrapper.controllers.bottomRight
|
||||
];
|
||||
const directionNames: TypeHelperWrapperControllerDirection[] = [
|
||||
const directionNames: HelperWrapperControllerDirection[] = [
|
||||
'right',
|
||||
'top-right',
|
||||
'top',
|
||||
|
|
@ -191,7 +191,7 @@ export class Helper implements TypeHelper {
|
|||
};
|
||||
}
|
||||
|
||||
isPointInElementList(p: TypePoint, data: TypeData): boolean {
|
||||
isPointInElementList(p: Point, data: IDrawData): boolean {
|
||||
const ctx = this._ctx;
|
||||
let idx = -1;
|
||||
let uuid = null;
|
||||
|
|
@ -232,12 +232,12 @@ export class Helper implements TypeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
startSelectArea(p: TypePoint) {
|
||||
startSelectArea(p: Point) {
|
||||
this._areaStart = p;
|
||||
this._areaEnd = p;
|
||||
}
|
||||
|
||||
changeSelectArea(p: TypePoint) {
|
||||
changeSelectArea(p: Point) {
|
||||
this._areaEnd = p;
|
||||
this._calcSelectedArea();
|
||||
}
|
||||
|
|
@ -248,7 +248,7 @@ export class Helper implements TypeHelper {
|
|||
this._calcSelectedArea();
|
||||
}
|
||||
|
||||
calcSelectedElements(data: TypeData) {
|
||||
calcSelectedElements(data: IDrawData) {
|
||||
const transform = this._ctx.getTransform();
|
||||
const { scale = 1, scrollX = 0, scrollY = 0 } = transform;
|
||||
const start = this._areaStart;
|
||||
|
|
@ -303,16 +303,16 @@ export class Helper implements TypeHelper {
|
|||
};
|
||||
}
|
||||
|
||||
private _updateElementIndex(data: TypeData) {
|
||||
private _updateElementIndex(data: IDrawData) {
|
||||
this._helperConfig.elementIndexMap = {};
|
||||
data.elements.forEach((elem: TypeElement<keyof TypeElemDesc>, i) => {
|
||||
data.elements.forEach((elem: DataElement<keyof DataElemDesc>, i) => {
|
||||
this._helperConfig.elementIndexMap[elem.uuid] = i;
|
||||
});
|
||||
}
|
||||
|
||||
private _updateSelectedElementWrapper(
|
||||
data: TypeData,
|
||||
opts: TypeHelperUpdateOpts
|
||||
data: IDrawData,
|
||||
opts: HelperUpdateOpts
|
||||
) {
|
||||
const { selectedUUID: uuid } = opts;
|
||||
if (
|
||||
|
|
@ -334,11 +334,11 @@ export class Helper implements TypeHelper {
|
|||
}
|
||||
|
||||
private _updateSelectedElementListWrapper(
|
||||
data: TypeData,
|
||||
opts: TypeHelperUpdateOpts
|
||||
data: IDrawData,
|
||||
opts: HelperUpdateOpts
|
||||
) {
|
||||
const { selectedUUIDList } = opts;
|
||||
const wrapperList: TypeHeplerSelectedElementWrapper[] = [];
|
||||
const wrapperList: HeplerSelectedElementWrapper[] = [];
|
||||
data.elements.forEach((elem) => {
|
||||
if (selectedUUIDList?.includes(elem.uuid)) {
|
||||
const wrapper = this._createSelectedElementWrapper(elem, opts);
|
||||
|
|
@ -349,9 +349,9 @@ export class Helper implements TypeHelper {
|
|||
}
|
||||
|
||||
private _createSelectedElementWrapper(
|
||||
elem: TypeElement<keyof TypeElemDesc>,
|
||||
opts: TypeHelperUpdateOpts
|
||||
): TypeHeplerSelectedElementWrapper {
|
||||
elem: DataElement<keyof DataElemDesc>,
|
||||
opts: HelperUpdateOpts
|
||||
): HeplerSelectedElementWrapper {
|
||||
const { scale } = opts;
|
||||
const elemWrapper = this._coreConfig.elementWrapper;
|
||||
const controllerSize = elemWrapper.controllerSize / scale;
|
||||
|
|
@ -372,7 +372,7 @@ export class Helper implements TypeHelper {
|
|||
// const controllerOffset = controllerSize;
|
||||
const controllerOffset = lineWidth;
|
||||
|
||||
const wrapper: TypeHeplerSelectedElementWrapper = {
|
||||
const wrapper: HeplerSelectedElementWrapper = {
|
||||
uuid: elem.uuid,
|
||||
controllerSize: controllerSize,
|
||||
controllerOffset: controllerOffset,
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ function fontWeight(value: any) {
|
|||
return ['bold'].includes(value);
|
||||
}
|
||||
|
||||
const is: TypeIs = {
|
||||
const is: IsTypeUtil = {
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
|
|
@ -124,7 +124,7 @@ const is: TypeIs = {
|
|||
strokeWidth
|
||||
};
|
||||
|
||||
type TypeIs = {
|
||||
type IsTypeUtil = {
|
||||
x: (value: any) => boolean;
|
||||
y: (value: any) => boolean;
|
||||
w: (value: any) => boolean;
|
||||
|
|
@ -150,4 +150,4 @@ type TypeIs = {
|
|||
|
||||
export default is;
|
||||
|
||||
export { TypeIs };
|
||||
export { IsTypeUtil };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { TypeData, TypePoint, TypePointCursor } from '@idraw/types';
|
||||
import { IDrawData, Point, PointCursor } from '@idraw/types';
|
||||
import Board from '@idraw/board';
|
||||
import { Helper } from './helper';
|
||||
import { Element } from './element';
|
||||
|
|
@ -27,7 +27,7 @@ export class Mapper {
|
|||
this[_helper] = this[_opts].helper;
|
||||
}
|
||||
|
||||
isEffectivePoint(p: TypePoint): boolean {
|
||||
isEffectivePoint(p: Point): boolean {
|
||||
const scrollLineWidth = this[_board].getScrollLineWidth();
|
||||
const screenInfo = this[_board].getScreenInfo();
|
||||
if (
|
||||
|
|
@ -40,13 +40,13 @@ export class Mapper {
|
|||
}
|
||||
|
||||
judgePointCursor(
|
||||
p: TypePoint,
|
||||
data: TypeData
|
||||
p: Point,
|
||||
data: IDrawData
|
||||
): {
|
||||
cursor: TypePointCursor;
|
||||
cursor: PointCursor;
|
||||
elementUUID: string | null;
|
||||
} {
|
||||
let cursor: TypePointCursor = 'auto';
|
||||
let cursor: PointCursor = 'auto';
|
||||
let elementUUID: string | null = null;
|
||||
if (!this.isEffectivePoint(p)) {
|
||||
return { cursor, elementUUID };
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { TypeData, TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
import { IDrawData, DataElement, DataElemDesc } from '@idraw/types';
|
||||
import { elementNames } from './../constant/element';
|
||||
|
||||
export function parseData(data: any): TypeData {
|
||||
const result: TypeData = {
|
||||
elements: [],
|
||||
export function parseData(data: any): IDrawData {
|
||||
const result: IDrawData = {
|
||||
elements: []
|
||||
};
|
||||
if (Array.isArray(data?.elements)) {
|
||||
data?.elements.forEach((elem: any = {}) => {
|
||||
|
|
@ -13,24 +13,28 @@ export function parseData(data: any): TypeData {
|
|||
});
|
||||
}
|
||||
if (typeof data.bgColor === 'string') {
|
||||
result.bgColor = data.bgColor;
|
||||
result.bgColor = data.bgColor;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function isElement(
|
||||
elem: TypeElement<keyof TypeElemDesc>
|
||||
): boolean{
|
||||
if (!(isNumber(elem.x) && isNumber(elem.y) && isNumber(elem.w) && isNumber(elem.h))) {
|
||||
function isElement(elem: DataElement<keyof DataElemDesc>): boolean {
|
||||
if (
|
||||
!(
|
||||
isNumber(elem.x) &&
|
||||
isNumber(elem.y) &&
|
||||
isNumber(elem.w) &&
|
||||
isNumber(elem.h)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!(typeof elem.type === 'string' && elementNames.includes(elem.type))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isNumber(num: any) {
|
||||
return (num >= 0 || num < 0);
|
||||
}
|
||||
return num >= 0 || num < 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,35 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypePoint,
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, Point, DataElement, DataElemDesc } from '@idraw/types';
|
||||
import { calcElementCenter, parseAngleToRadian } from './calculate';
|
||||
|
||||
function rotateElement(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<keyof TypeElemDesc>,
|
||||
callback: (ctx: TypeContext) => void
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<keyof DataElemDesc>,
|
||||
callback: (ctx: IDrawContext) => void
|
||||
): void {
|
||||
const center: TypePoint = calcElementCenter(elem);
|
||||
const center: Point = calcElementCenter(elem);
|
||||
const radian = parseAngleToRadian(elem.angle || 0);
|
||||
return rotateContext(ctx, center, radian || 0, callback);
|
||||
}
|
||||
|
||||
|
||||
function rotateContext(
|
||||
ctx: TypeContext,
|
||||
center: TypePoint | undefined,
|
||||
ctx: IDrawContext,
|
||||
center: Point | undefined,
|
||||
radian: number,
|
||||
callback: (ctx: TypeContext) => void
|
||||
callback: (ctx: IDrawContext) => void
|
||||
): void {
|
||||
if (center && (radian > 0 || radian < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(radian);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
ctx.translate(-center.x, -center.y);
|
||||
}
|
||||
|
||||
callback(ctx);
|
||||
|
||||
if (center && (radian > 0 || radian < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(- radian);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
ctx.rotate(-radian);
|
||||
ctx.translate(-center.x, -center.y);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
rotateContext,
|
||||
rotateElement,
|
||||
};
|
||||
export { rotateContext, rotateElement };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { TypeElement, TypeElemDesc, TypeElementBase } from '@idraw/types';
|
||||
import { DataElement, DataElemDesc, DataElementBase } from '@idraw/types';
|
||||
import { deepClone, createUUID } from '@idraw/util';
|
||||
import { _data, _element, _engine, _draw, _emitChangeData } from './../names';
|
||||
import { diffElementResourceChange } from './../lib/diff';
|
||||
|
|
@ -7,8 +7,8 @@ import { Mode } from './../constant/static';
|
|||
|
||||
export function getSelectedElements(
|
||||
core: Core
|
||||
): TypeElement<keyof TypeElemDesc>[] {
|
||||
const elems: TypeElement<keyof TypeElemDesc>[] = [];
|
||||
): DataElement<keyof DataElemDesc>[] {
|
||||
const elems: DataElement<keyof DataElemDesc>[] = [];
|
||||
let list: string[] = [];
|
||||
const uuid = core[_engine].temp.get('selectedUUID');
|
||||
if (typeof uuid === 'string' && uuid) {
|
||||
|
|
@ -29,8 +29,8 @@ export function getSelectedElements(
|
|||
export function getElement(
|
||||
core: Core,
|
||||
uuid: string
|
||||
): TypeElement<keyof TypeElemDesc> | null {
|
||||
let elem: TypeElement<keyof TypeElemDesc> | null = null;
|
||||
): DataElement<keyof DataElemDesc> | null {
|
||||
let elem: DataElement<keyof DataElemDesc> | null = null;
|
||||
const index = core[_engine].helper.getElementIndexByUUID(uuid);
|
||||
if (index !== null && core[_data].elements[index]) {
|
||||
elem = deepClone(core[_data].elements[index]);
|
||||
|
|
@ -41,8 +41,8 @@ export function getElement(
|
|||
export function getElementByIndex(
|
||||
core: Core,
|
||||
index: number
|
||||
): TypeElement<keyof TypeElemDesc> | null {
|
||||
let elem: TypeElement<keyof TypeElemDesc> | null = null;
|
||||
): DataElement<keyof DataElemDesc> | null {
|
||||
let elem: DataElement<keyof DataElemDesc> | null = null;
|
||||
if (index >= 0 && core[_data].elements[index]) {
|
||||
elem = deepClone(core[_data].elements[index]);
|
||||
}
|
||||
|
|
@ -51,9 +51,9 @@ export function getElementByIndex(
|
|||
|
||||
export function updateElement(
|
||||
core: Core,
|
||||
elem: TypeElement<keyof TypeElemDesc>
|
||||
elem: DataElement<keyof DataElemDesc>
|
||||
) {
|
||||
const _elem = deepClone(elem) as TypeElement<keyof TypeElemDesc>;
|
||||
const _elem = deepClone(elem) as DataElement<keyof DataElemDesc>;
|
||||
const data = core[_data];
|
||||
const resourceChangeUUIDs: string[] = [];
|
||||
for (let i = 0; i < data.elements.length; i++) {
|
||||
|
|
@ -145,7 +145,7 @@ export function moveDownElement(core: Core, uuid: string): void {
|
|||
|
||||
export function addElement(
|
||||
core: Core,
|
||||
elem: TypeElementBase<keyof TypeElemDesc>
|
||||
elem: DataElementBase<keyof DataElemDesc>
|
||||
): string | null {
|
||||
const _elem = deepClone(elem);
|
||||
_elem.uuid = createUUID();
|
||||
|
|
@ -166,7 +166,7 @@ export function deleteElement(core: Core, uuid: string) {
|
|||
|
||||
export function insertElementBefore(
|
||||
core: Core,
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
beforeUUID: string
|
||||
) {
|
||||
const index = core[_engine].helper.getElementIndexByUUID(beforeUUID);
|
||||
|
|
@ -178,7 +178,7 @@ export function insertElementBefore(
|
|||
|
||||
export function insertElementBeforeIndex(
|
||||
core: Core,
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
index: number
|
||||
) {
|
||||
const _elem = deepClone(elem);
|
||||
|
|
@ -194,7 +194,7 @@ export function insertElementBeforeIndex(
|
|||
|
||||
export function insertElementAfter(
|
||||
core: Core,
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
beforeUUID: string
|
||||
) {
|
||||
const index = core[_engine].helper.getElementIndexByUUID(beforeUUID);
|
||||
|
|
@ -206,7 +206,7 @@ export function insertElementAfter(
|
|||
|
||||
export function insertElementAfterIndex(
|
||||
core: Core,
|
||||
elem: TypeElementBase<keyof TypeElemDesc>,
|
||||
elem: DataElementBase<keyof DataElemDesc>,
|
||||
index: number
|
||||
) {
|
||||
const _elem = deepClone(elem);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import {
|
||||
InterfaceHelperPlugin, TypeHelperPluginEventDetail,
|
||||
TypeHelperPluginEventResult,
|
||||
InterfaceHelperPlugin,
|
||||
HelperPluginEventDetail,
|
||||
HelperPluginEventResult
|
||||
} from '@idraw/types';
|
||||
import { createUUID } from '@idraw/util';
|
||||
|
||||
|
||||
export class HelperPlugin implements Required<InterfaceHelperPlugin> {
|
||||
|
||||
readonly name: string = 'helper-plugin';
|
||||
|
||||
readonly uuid: string;
|
||||
|
|
@ -16,31 +15,20 @@ export class HelperPlugin implements Required<InterfaceHelperPlugin> {
|
|||
this.uuid = createUUID();
|
||||
}
|
||||
|
||||
onHover(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
onHover(detail: HelperPluginEventDetail): void | HelperPluginEventResult {
|
||||
if (detail.controller === null) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
onPoint(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
|
||||
}
|
||||
onPoint(detail: HelperPluginEventDetail): void | HelperPluginEventResult {}
|
||||
|
||||
onClick(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
|
||||
}
|
||||
onClick(detail: HelperPluginEventDetail): void | HelperPluginEventResult {}
|
||||
|
||||
onMoveStart(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
|
||||
}
|
||||
onMoveStart(
|
||||
detail: HelperPluginEventDetail
|
||||
): void | HelperPluginEventResult {}
|
||||
|
||||
onMove(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
|
||||
onMove(detail: HelperPluginEventDetail): void | HelperPluginEventResult {}
|
||||
|
||||
}
|
||||
|
||||
onMoveEnd(detail: TypeHelperPluginEventDetail): void | TypeHelperPluginEventResult {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
onMoveEnd(detail: HelperPluginEventDetail): void | HelperPluginEventResult {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { TypeDataBase } from '@idraw/types';
|
||||
import type { IDrawDataBase } from '@idraw/types';
|
||||
|
||||
const data: TypeDataBase = {
|
||||
const data: IDrawDataBase = {
|
||||
bgColor: '#ffffff',
|
||||
elements: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Core from '@idraw/core';
|
||||
import { TypeData, TypeConfig } from '@idraw/types';
|
||||
import { IDrawData, IDrawConfig } from '@idraw/types';
|
||||
import { Options, PrivateOptions } from './types';
|
||||
import { defaultOptions } from './config';
|
||||
import { TempData } from './lib/temp';
|
||||
|
|
@ -36,7 +36,7 @@ export default class iDraw extends Core {
|
|||
|
||||
// static version = version;
|
||||
|
||||
constructor(mount: HTMLDivElement, opts: Options, config?: TypeConfig) {
|
||||
constructor(mount: HTMLDivElement, opts: Options, config?: IDrawConfig) {
|
||||
super(
|
||||
mount,
|
||||
{
|
||||
|
|
@ -54,11 +54,11 @@ export default class iDraw extends Core {
|
|||
this[_initEvent]();
|
||||
}
|
||||
|
||||
undo(): { doRecordCount: number; data: TypeData | null } {
|
||||
undo(): { doRecordCount: number; data: IDrawData | null } {
|
||||
return undo(this);
|
||||
}
|
||||
|
||||
redo(): { undoRecordCount: number; data: TypeData | null } {
|
||||
redo(): { undoRecordCount: number; data: IDrawData | null } {
|
||||
return redo(this);
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ export default class iDraw extends Core {
|
|||
if (this[_hasInited] === true) {
|
||||
return;
|
||||
}
|
||||
this.on('changeData', (data: TypeData) => {
|
||||
this.on('changeData', (data: IDrawData) => {
|
||||
this[_pushRecord](data);
|
||||
});
|
||||
this.on('mouseLeaveScreen', () => {
|
||||
|
|
@ -101,7 +101,7 @@ export default class iDraw extends Core {
|
|||
this[_hasInited] = true;
|
||||
}
|
||||
|
||||
private [_pushRecord](data: TypeData) {
|
||||
private [_pushRecord](data: IDrawData) {
|
||||
const doRecords = this[_tempData].get('doRecords');
|
||||
if (doRecords.length >= this[_opts].maxRecords) {
|
||||
doRecords.shift();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import { TypeElemDesc, TypeElement } from '@idraw/types';
|
||||
import { DataElemDesc, DataElement } from '@idraw/types';
|
||||
import { Record } from './../types';
|
||||
|
||||
|
||||
type TempDataDesc = {
|
||||
isDownloading: boolean;
|
||||
isFocus: boolean,
|
||||
doRecords: Record[],
|
||||
unDoRecords: Record[],
|
||||
clipboardElements: TypeElement<keyof TypeElemDesc>[]
|
||||
}
|
||||
isFocus: boolean;
|
||||
doRecords: Record[];
|
||||
unDoRecords: Record[];
|
||||
clipboardElements: DataElement<keyof DataElemDesc>[];
|
||||
};
|
||||
|
||||
function createDefaultData() {
|
||||
return {
|
||||
|
|
@ -16,27 +15,26 @@ function createDefaultData() {
|
|||
doRecords: [],
|
||||
unDoRecords: [],
|
||||
clipboardElements: [],
|
||||
isDownloading: false,
|
||||
}
|
||||
isDownloading: false
|
||||
};
|
||||
}
|
||||
|
||||
export class TempData {
|
||||
|
||||
private _temp: TempDataDesc
|
||||
private _temp: TempDataDesc;
|
||||
|
||||
constructor() {
|
||||
this._temp = createDefaultData();
|
||||
}
|
||||
|
||||
set<T extends keyof TempDataDesc >(name: T, value: TempDataDesc[T]) {
|
||||
set<T extends keyof TempDataDesc>(name: T, value: TempDataDesc[T]) {
|
||||
this._temp[name] = value;
|
||||
}
|
||||
|
||||
get<T extends keyof TempDataDesc >(name: T): TempDataDesc[T] {
|
||||
get<T extends keyof TempDataDesc>(name: T): TempDataDesc[T] {
|
||||
return this._temp[name];
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._temp = createDefaultData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { deepClone } from '@idraw/util';
|
||||
import { TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
import { DataElement, DataElemDesc } from '@idraw/types';
|
||||
import iDraw from './../index';
|
||||
import { _tempData } from './../names';
|
||||
|
||||
|
|
@ -30,9 +30,9 @@ export function cutElements(idraw: iDraw) {
|
|||
return;
|
||||
}
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
idraw.deleteElement(elem.uuid);
|
||||
})
|
||||
});
|
||||
idraw[_tempData].set('clipboardElements', elems);
|
||||
}
|
||||
|
||||
|
|
@ -41,18 +41,17 @@ export function deleteElements(idraw: iDraw) {
|
|||
return;
|
||||
}
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
idraw.deleteElement(elem.uuid);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const keyArrowMoveDistance = 4;
|
||||
|
||||
export function keyArrowUp(idraw: iDraw) {
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
if (elems.length > 0) {
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
elem.y -= keyArrowMoveDistance;
|
||||
idraw.updateElement(elem);
|
||||
});
|
||||
|
|
@ -65,7 +64,7 @@ export function keyArrowUp(idraw: iDraw) {
|
|||
export function keyArrowDown(idraw: iDraw) {
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
if (elems.length > 0) {
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
elem.y += keyArrowMoveDistance;
|
||||
idraw.updateElement(elem);
|
||||
});
|
||||
|
|
@ -78,7 +77,7 @@ export function keyArrowDown(idraw: iDraw) {
|
|||
export function keyArrowLeft(idraw: iDraw) {
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
if (elems.length > 0) {
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
elem.x -= keyArrowMoveDistance;
|
||||
idraw.updateElement(elem);
|
||||
});
|
||||
|
|
@ -91,7 +90,7 @@ export function keyArrowLeft(idraw: iDraw) {
|
|||
export function keyArrowRight(idraw: iDraw) {
|
||||
const elems = deepClone(idraw.getSelectedElements());
|
||||
if (elems.length > 0) {
|
||||
elems.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
elems.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
elem.x += keyArrowMoveDistance;
|
||||
idraw.updateElement(elem);
|
||||
});
|
||||
|
|
@ -103,4 +102,4 @@ export function keyArrowRight(idraw: iDraw) {
|
|||
|
||||
export function keyUndo(idraw: iDraw) {
|
||||
idraw.undo();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import { TypeData } from '@idraw/types';
|
||||
import { IDrawData } from '@idraw/types';
|
||||
import iDraw from './../index';
|
||||
import { _tempData } from './../names';
|
||||
|
||||
export function undo(idraw: iDraw): {
|
||||
doRecordCount: number,
|
||||
data: TypeData | null,
|
||||
doRecordCount: number;
|
||||
data: IDrawData | null;
|
||||
} {
|
||||
const doRecords = idraw[_tempData].get('doRecords');
|
||||
const unDoRecords = idraw[_tempData].get('unDoRecords');
|
||||
if (!(doRecords.length > 1)) {
|
||||
return {
|
||||
doRecordCount: doRecords.length,
|
||||
data: null,
|
||||
data: null
|
||||
};
|
||||
}
|
||||
const popRecord = doRecords.pop();
|
||||
|
|
@ -26,19 +26,19 @@ export function undo(idraw: iDraw): {
|
|||
idraw[_tempData].set('unDoRecords', unDoRecords);
|
||||
return {
|
||||
doRecordCount: doRecords.length,
|
||||
data: record?.data || null,
|
||||
data: record?.data || null
|
||||
};
|
||||
}
|
||||
|
||||
export function redo(idraw: iDraw): {
|
||||
undoRecordCount: number,
|
||||
data: TypeData | null,
|
||||
undoRecordCount: number;
|
||||
data: IDrawData | null;
|
||||
} {
|
||||
const unDoRecords = idraw[_tempData].get('unDoRecords');
|
||||
if (!(unDoRecords.length > 0)) {
|
||||
return {
|
||||
undoRecordCount: unDoRecords.length,
|
||||
data: null,
|
||||
data: null
|
||||
};
|
||||
}
|
||||
const record = unDoRecords.pop();
|
||||
|
|
@ -48,6 +48,6 @@ export function redo(idraw: iDraw): {
|
|||
idraw[_tempData].set('unDoRecords', unDoRecords);
|
||||
return {
|
||||
undoRecordCount: unDoRecords.length,
|
||||
data: record?.data || null,
|
||||
data: record?.data || null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
import {
|
||||
TypeData,
|
||||
TypeCoreOptions,
|
||||
} from '@idraw/types';
|
||||
import { IDrawData, CoreOptions } from '@idraw/types';
|
||||
|
||||
export type Options = {
|
||||
maxRecords?: number;
|
||||
disableKeyboard?: boolean;
|
||||
} & TypeCoreOptions;
|
||||
} & CoreOptions;
|
||||
|
||||
export type PrivateOptions = {
|
||||
maxRecords: number;
|
||||
|
|
@ -14,6 +11,6 @@ export type PrivateOptions = {
|
|||
} & Options;
|
||||
|
||||
export type Record = {
|
||||
data: TypeData;
|
||||
data: IDrawData;
|
||||
time: number;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
import { TypeData, TypeContext, TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
import {
|
||||
IDrawData,
|
||||
IDrawContext,
|
||||
DataElement,
|
||||
DataElemDesc
|
||||
} from '@idraw/types';
|
||||
import { createUUID, deepClone, Context } from '@idraw/util';
|
||||
import { drawContext } from './lib/draw';
|
||||
import { TypeLoadDataItem } from './lib/loader-event';
|
||||
|
|
@ -17,7 +22,7 @@ import {
|
|||
|
||||
const { requestAnimationFrame } = window;
|
||||
|
||||
type QueueItem = { data: TypeData };
|
||||
type QueueItem = { data: IDrawData };
|
||||
enum DrawStatus {
|
||||
NULL = 'null',
|
||||
FREE = 'free',
|
||||
|
|
@ -36,7 +41,7 @@ type Options = {
|
|||
|
||||
export default class Renderer extends RendererEvent {
|
||||
private [_queue]: QueueItem[] = [];
|
||||
private [_ctx]: TypeContext | null = null;
|
||||
private [_ctx]: IDrawContext | null = null;
|
||||
private [_status]: DrawStatus = DrawStatus.NULL;
|
||||
private [_loader]: Loader;
|
||||
private [_opts]?: Options;
|
||||
|
|
@ -60,8 +65,8 @@ export default class Renderer extends RendererEvent {
|
|||
}
|
||||
|
||||
render(
|
||||
target: HTMLCanvasElement | TypeContext,
|
||||
originData: TypeData,
|
||||
target: HTMLCanvasElement | IDrawContext,
|
||||
originData: IDrawData,
|
||||
opts?: {
|
||||
// forceUpdate?: boolean,
|
||||
changeResourceUUIDs?: string[];
|
||||
|
|
@ -77,7 +82,7 @@ export default class Renderer extends RendererEvent {
|
|||
|
||||
const data = deepClone(originData);
|
||||
if (Array.isArray(data.elements)) {
|
||||
data.elements.forEach((elem: TypeElement<keyof TypeElemDesc>) => {
|
||||
data.elements.forEach((elem: DataElement<keyof DataElemDesc>) => {
|
||||
if (!(typeof elem.uuid === 'string' && elem.uuid)) {
|
||||
elem.uuid = createUUID();
|
||||
}
|
||||
|
|
@ -105,7 +110,7 @@ export default class Renderer extends RendererEvent {
|
|||
});
|
||||
} else if (target) {
|
||||
// TODO
|
||||
this[_ctx] = target as TypeContext;
|
||||
this[_ctx] = target as IDrawContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +127,7 @@ export default class Renderer extends RendererEvent {
|
|||
this[_loader].load(data, changeResourceUUIDs || []);
|
||||
}
|
||||
|
||||
getContext(): TypeContext | null {
|
||||
getContext(): IDrawContext | null {
|
||||
return this[_ctx];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,30 @@
|
|||
import {
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
TypePoint,
|
||||
} from '@idraw/types';
|
||||
|
||||
import { DataElement, DataElemDesc, Point } from '@idraw/types';
|
||||
|
||||
export function parseRadianToAngle(radian: number): number {
|
||||
return radian / Math.PI * 180;
|
||||
return (radian / Math.PI) * 180;
|
||||
}
|
||||
|
||||
export function parseAngleToRadian(angle: number): number {
|
||||
return angle / 180 * Math.PI;
|
||||
return (angle / 180) * Math.PI;
|
||||
}
|
||||
|
||||
export function calcElementCenter(elem: TypeElement<keyof TypeElemDesc>): TypePoint {
|
||||
export function calcElementCenter(
|
||||
elem: DataElement<keyof DataElemDesc>
|
||||
): Point {
|
||||
const p = {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y + elem.h / 2,
|
||||
y: elem.y + elem.h / 2
|
||||
};
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
export function calcRadian(center: TypePoint, start: TypePoint, end: TypePoint): number {
|
||||
export function calcRadian(center: Point, start: Point, end: Point): number {
|
||||
const startAngle = calcLineAngle(center, start);
|
||||
const endAngle = calcLineAngle(center, end);
|
||||
if (endAngle !== null && startAngle !== null ) {
|
||||
if (startAngle > Math.PI * 3 / 2 && endAngle < Math.PI / 2) {
|
||||
if (endAngle !== null && startAngle !== null) {
|
||||
if (startAngle > (Math.PI * 3) / 2 && endAngle < Math.PI / 2) {
|
||||
return endAngle + (Math.PI * 2 - startAngle);
|
||||
} else if (endAngle > Math.PI * 3 / 2 && startAngle < Math.PI / 2) {
|
||||
} else if (endAngle > (Math.PI * 3) / 2 && startAngle < Math.PI / 2) {
|
||||
return startAngle + (Math.PI * 2 - endAngle);
|
||||
} else {
|
||||
return endAngle - startAngle;
|
||||
|
|
@ -38,14 +34,14 @@ export function calcRadian(center: TypePoint, start: TypePoint, end: TypePoint):
|
|||
}
|
||||
}
|
||||
|
||||
function calcLineAngle(center: TypePoint, p: TypePoint): number | null {
|
||||
function calcLineAngle(center: Point, p: Point): number | null {
|
||||
const x = p.x - center.x;
|
||||
const y = center.y - p.y;
|
||||
if (x === 0) {
|
||||
if (y < 0) {
|
||||
return Math.PI / 2;
|
||||
} else if (y > 0) {
|
||||
return Math.PI * ( 3 / 2 );
|
||||
return Math.PI * (3 / 2);
|
||||
}
|
||||
} else if (y === 0) {
|
||||
if (x < 0) {
|
||||
|
|
@ -64,4 +60,4 @@ function calcLineAngle(center: TypePoint, p: TypePoint): number | null {
|
|||
return Math.PI * 2 - Math.atan(Math.abs(y) / Math.abs(x));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +1,64 @@
|
|||
import { TypeElement, TypeData, TypeElemDesc } from '@idraw/types';
|
||||
|
||||
type TypeElementMap = {
|
||||
[uuid: string]: TypeElement<keyof TypeElemDesc>
|
||||
}
|
||||
import { DataElement, IDrawData, DataElemDesc } from '@idraw/types';
|
||||
|
||||
type DataElementMap = {
|
||||
[uuid: string]: DataElement<keyof DataElemDesc>;
|
||||
};
|
||||
|
||||
export function isChangeImageElementResource(
|
||||
before: TypeElement<'image'>,
|
||||
after: TypeElement<'image'>,
|
||||
before: DataElement<'image'>,
|
||||
after: DataElement<'image'>
|
||||
): boolean {
|
||||
return (before?.desc?.src !== after?.desc?.src);
|
||||
return before?.desc?.src !== after?.desc?.src;
|
||||
}
|
||||
|
||||
|
||||
export function isChangeSVGElementResource(
|
||||
before: TypeElement<'svg'>,
|
||||
after: TypeElement<'svg'>,
|
||||
before: DataElement<'svg'>,
|
||||
after: DataElement<'svg'>
|
||||
): boolean {
|
||||
return (before?.desc?.svg !== after?.desc?.svg);
|
||||
return before?.desc?.svg !== after?.desc?.svg;
|
||||
}
|
||||
|
||||
export function isChangeHTMLElementResource(
|
||||
before: TypeElement<'html'>,
|
||||
after: TypeElement<'html'>,
|
||||
before: DataElement<'html'>,
|
||||
after: DataElement<'html'>
|
||||
): boolean {
|
||||
return (
|
||||
before?.desc?.html !== after?.desc?.html
|
||||
|| before?.desc?.width !== after?.desc?.width
|
||||
|| before?.desc?.height !== after?.desc?.height
|
||||
before?.desc?.html !== after?.desc?.html ||
|
||||
before?.desc?.width !== after?.desc?.width ||
|
||||
before?.desc?.height !== after?.desc?.height
|
||||
);
|
||||
}
|
||||
|
||||
export function diffElementResourceChange(
|
||||
before: TypeElement<keyof TypeElemDesc>,
|
||||
after: TypeElement<keyof TypeElemDesc>,
|
||||
before: DataElement<keyof DataElemDesc>,
|
||||
after: DataElement<keyof DataElemDesc>
|
||||
): string | null {
|
||||
let result = null;
|
||||
let isChange = false;
|
||||
switch (after.type) {
|
||||
case 'image': {
|
||||
isChange = isChangeImageElementResource(
|
||||
before as TypeElement<'image'>,
|
||||
after as TypeElement<'image'>
|
||||
before as DataElement<'image'>,
|
||||
after as DataElement<'image'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'svg': {
|
||||
isChange = isChangeSVGElementResource(
|
||||
before as TypeElement<'svg'>,
|
||||
after as TypeElement<'svg'>
|
||||
before as DataElement<'svg'>,
|
||||
after as DataElement<'svg'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
isChange = isChangeHTMLElementResource(
|
||||
before as TypeElement<'html'>,
|
||||
after as TypeElement<'html'>
|
||||
before as DataElement<'html'>,
|
||||
after as DataElement<'html'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isChange === true) {
|
||||
result = after.uuid;
|
||||
|
|
@ -68,8 +67,8 @@ export function diffElementResourceChange(
|
|||
}
|
||||
|
||||
export function diffElementResourceChangeList(
|
||||
before: TypeData,
|
||||
after: TypeData,
|
||||
before: IDrawData,
|
||||
after: IDrawData
|
||||
): string[] {
|
||||
const uuids: string[] = [];
|
||||
const beforeMap = parseDataElementMap(before);
|
||||
|
|
@ -83,26 +82,27 @@ export function diffElementResourceChangeList(
|
|||
switch (beforeMap[uuid].type) {
|
||||
case 'image': {
|
||||
isChange = isChangeImageElementResource(
|
||||
beforeMap[uuid] as TypeElement<'image'>,
|
||||
afterMap[uuid] as TypeElement<'image'>
|
||||
beforeMap[uuid] as DataElement<'image'>,
|
||||
afterMap[uuid] as DataElement<'image'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'svg': {
|
||||
isChange = isChangeSVGElementResource(
|
||||
beforeMap[uuid] as TypeElement<'svg'>,
|
||||
afterMap[uuid] as TypeElement<'svg'>
|
||||
beforeMap[uuid] as DataElement<'svg'>,
|
||||
afterMap[uuid] as DataElement<'svg'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
isChange = isChangeHTMLElementResource(
|
||||
beforeMap[uuid] as TypeElement<'html'>,
|
||||
afterMap[uuid] as TypeElement<'html'>
|
||||
beforeMap[uuid] as DataElement<'html'>,
|
||||
afterMap[uuid] as DataElement<'html'>
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isChange === true) {
|
||||
uuids.push(uuid);
|
||||
|
|
@ -114,11 +114,10 @@ export function diffElementResourceChangeList(
|
|||
return uuids;
|
||||
}
|
||||
|
||||
|
||||
function parseDataElementMap(data: TypeData): TypeElementMap {
|
||||
const elemMap: TypeElementMap = {};
|
||||
function parseDataElementMap(data: IDrawData): DataElementMap {
|
||||
const elemMap: DataElementMap = {};
|
||||
data.elements.forEach((elem) => {
|
||||
elemMap[elem.uuid] = elem;
|
||||
})
|
||||
});
|
||||
return elemMap;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
TypeContext,
|
||||
// TypeElemDesc,
|
||||
TypeElement
|
||||
IDrawContext,
|
||||
// DataElemDesc,
|
||||
DataElement
|
||||
} from '@idraw/types';
|
||||
import { is, istype, isColorStr } from '@idraw/util';
|
||||
import { rotateElement } from './../transform';
|
||||
|
||||
export function clearContext(ctx: TypeContext) {
|
||||
export function clearContext(ctx: IDrawContext) {
|
||||
// ctx.setFillStyle('rgb(0 0 0 / 100%)');
|
||||
// ctx.setStrokeStyle('rgb(0 0 0 / 100%)');
|
||||
ctx.setFillStyle('#000000');
|
||||
|
|
@ -19,15 +19,15 @@ export function clearContext(ctx: TypeContext) {
|
|||
ctx.setShadowBlur(0);
|
||||
}
|
||||
|
||||
export function drawBgColor(ctx: TypeContext, color: string) {
|
||||
export function drawBgColor(ctx: IDrawContext, color: string) {
|
||||
const size = ctx.getSize();
|
||||
ctx.setFillStyle(color);
|
||||
ctx.fillRect(0, 0, size.contextWidth, size.contextHeight);
|
||||
}
|
||||
|
||||
export function drawBox(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'text' | 'rect'>,
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'text' | 'rect'>,
|
||||
pattern: string | CanvasPattern | null
|
||||
): void {
|
||||
clearContext(ctx);
|
||||
|
|
@ -57,8 +57,8 @@ export function drawBox(
|
|||
}
|
||||
|
||||
export function drawBoxBorder(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'text' | 'rect'>
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'text' | 'rect'>
|
||||
): void {
|
||||
clearContext(ctx);
|
||||
rotateElement(ctx, elem, () => {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { TypeContext, TypeElement, } from '@idraw/types';
|
||||
import { IDrawContext, DataElement } from '@idraw/types';
|
||||
import { rotateElement } from './../transform';
|
||||
import { clearContext } from './base';
|
||||
|
||||
export function drawCircle(ctx: TypeContext, elem: TypeElement<'circle'>) {
|
||||
export function drawCircle(ctx: IDrawContext, elem: DataElement<'circle'>) {
|
||||
clearContext(ctx);
|
||||
rotateElement(ctx, elem, (ctx) => {
|
||||
const { x, y, w, h, desc } = elem;
|
||||
const {
|
||||
bgColor = '#000000',
|
||||
borderColor = '#000000',
|
||||
borderWidth = 0,
|
||||
borderWidth = 0
|
||||
} = desc;
|
||||
|
||||
const a = w / 2;
|
||||
|
|
@ -19,14 +19,13 @@ export function drawCircle(ctx: TypeContext, elem: TypeElement<'circle'>) {
|
|||
|
||||
// draw border
|
||||
if (borderWidth && borderWidth > 0) {
|
||||
|
||||
const ba = borderWidth / 2 + a;
|
||||
const bb = borderWidth / 2 + b;
|
||||
ctx.beginPath();
|
||||
ctx.setStrokeStyle(borderColor);
|
||||
ctx.setLineWidth(borderWidth);
|
||||
ctx.ellipse(centerX, centerY, ba, bb, 0, 0, 2 * Math.PI)
|
||||
|
||||
ctx.ellipse(centerX, centerY, ba, bb, 0, 0, 2 * Math.PI);
|
||||
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
|
@ -34,10 +33,10 @@ export function drawCircle(ctx: TypeContext, elem: TypeElement<'circle'>) {
|
|||
// draw content
|
||||
ctx.beginPath();
|
||||
ctx.setFillStyle(bgColor);
|
||||
ctx.ellipse(centerX, centerY, a, b, 0, 0, 2 * Math.PI)
|
||||
ctx.ellipse(centerX, centerY, a, b, 0, 0, 2 * Math.PI);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
|
||||
// // draw shadow
|
||||
// clearContext(ctx);
|
||||
// if ((desc.shadowOffsetX !== undefined && is.number(desc.shadowOffsetX)) || desc.shadowOffsetY !== undefined && is.number(desc.shadowOffsetY)) {
|
||||
|
|
@ -70,6 +69,5 @@ export function drawCircle(ctx: TypeContext, elem: TypeElement<'circle'>) {
|
|||
// ctx.closePath();
|
||||
// ctx.fill();
|
||||
// }
|
||||
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypeElement,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, DataElement } from '@idraw/types';
|
||||
import { rotateElement } from '../transform';
|
||||
import Loader from '../loader';
|
||||
|
||||
|
||||
export function drawHTML(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'html'>,
|
||||
loader: Loader,
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'html'>,
|
||||
loader: Loader
|
||||
) {
|
||||
const content = loader.getContent(elem.uuid);
|
||||
rotateElement(ctx, elem, () => {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypeElement,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, DataElement } from '@idraw/types';
|
||||
import { rotateElement } from '../transform';
|
||||
import Loader from '../loader';
|
||||
|
||||
|
||||
export function drawImage (
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'image'>,
|
||||
loader: Loader,
|
||||
export function drawImage(
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'image'>,
|
||||
loader: Loader
|
||||
) {
|
||||
// const desc = elem.desc as TypeElemDesc['rect'];
|
||||
// const desc = elem.desc as DataElemDesc['rect'];
|
||||
const content = loader.getContent(elem.uuid);
|
||||
rotateElement(ctx, elem, () => {
|
||||
// ctx.setFillStyle(desc.color);
|
||||
|
|
@ -23,31 +19,23 @@ export function drawImage (
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// import {
|
||||
// TypeContext,
|
||||
// TypeElement,
|
||||
// TypeHelperConfig,
|
||||
// TypeElemDesc,
|
||||
// IDrawContext,
|
||||
// DataElement,
|
||||
// HelperConfig,
|
||||
// DataElemDesc,
|
||||
// } from '@idraw/types';
|
||||
// import Loader from '../loader';
|
||||
// import { drawBox } from './base';
|
||||
|
||||
// export function drawImage(
|
||||
// ctx: TypeContext,
|
||||
// elem: TypeElement<'image'>,
|
||||
// ctx: IDrawContext,
|
||||
// elem: DataElement<'image'>,
|
||||
// loader: Loader,
|
||||
// helperConfig: TypeHelperConfig
|
||||
// helperConfig: HelperConfig
|
||||
// ) {
|
||||
// const content = loader.getPattern(elem, {
|
||||
// forceUpdate: helperConfig?.selectedElementWrapper?.uuid === elem.uuid
|
||||
// });
|
||||
// drawBox(ctx, elem, content);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypeData,
|
||||
TypeElement,
|
||||
// TypePoint,
|
||||
IDrawContext,
|
||||
IDrawData,
|
||||
DataElement
|
||||
// Point,
|
||||
} from '@idraw/types';
|
||||
import { isColorStr } from '@idraw/util';
|
||||
import Loader from '../loader';
|
||||
|
|
@ -15,9 +15,9 @@ import { drawText } from './text';
|
|||
import { drawCircle } from './circle';
|
||||
|
||||
export function drawContext(
|
||||
ctx: TypeContext,
|
||||
data: TypeData,
|
||||
loader: Loader,
|
||||
ctx: IDrawContext,
|
||||
data: IDrawData,
|
||||
loader: Loader
|
||||
): void {
|
||||
clearContext(ctx);
|
||||
const size = ctx.getSize();
|
||||
|
|
@ -37,27 +37,27 @@ export function drawContext(
|
|||
}
|
||||
switch (elem.type) {
|
||||
case 'rect': {
|
||||
drawRect(ctx, elem as TypeElement<'rect'>);
|
||||
drawRect(ctx, elem as DataElement<'rect'>);
|
||||
break;
|
||||
}
|
||||
case 'text': {
|
||||
drawText(ctx, elem as TypeElement<'text'>, loader);
|
||||
drawText(ctx, elem as DataElement<'text'>, loader);
|
||||
break;
|
||||
}
|
||||
case 'image': {
|
||||
drawImage(ctx, elem as TypeElement<'image'>, loader);
|
||||
drawImage(ctx, elem as DataElement<'image'>, loader);
|
||||
break;
|
||||
}
|
||||
case 'svg': {
|
||||
drawSVG(ctx, elem as TypeElement<'svg'>, loader);
|
||||
drawSVG(ctx, elem as DataElement<'svg'>, loader);
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
drawHTML(ctx, elem as TypeElement<'html'>, loader);
|
||||
drawHTML(ctx, elem as DataElement<'html'>, loader);
|
||||
break;
|
||||
}
|
||||
case 'circle': {
|
||||
drawCircle(ctx, elem as TypeElement<'circle'>);
|
||||
drawCircle(ctx, elem as DataElement<'circle'>);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
@ -66,6 +66,4 @@ export function drawContext(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypeElement,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, DataElement } from '@idraw/types';
|
||||
import { drawBox } from './base';
|
||||
|
||||
export function drawRect(ctx: TypeContext, elem: TypeElement<'rect'>) {
|
||||
|
||||
export function drawRect(ctx: IDrawContext, elem: DataElement<'rect'>) {
|
||||
drawBox(ctx, elem, elem.desc.bgColor as string);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,17 +1,13 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypeElement,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, DataElement } from '@idraw/types';
|
||||
import { rotateElement } from '../transform';
|
||||
import Loader from '../loader';
|
||||
|
||||
|
||||
export function drawSVG (
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'svg'>,
|
||||
loader: Loader,
|
||||
export function drawSVG(
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'svg'>,
|
||||
loader: Loader
|
||||
) {
|
||||
// const desc = elem.desc as TypeElemDesc['rect'];
|
||||
// const desc = elem.desc as DataElemDesc['rect'];
|
||||
const content = loader.getContent(elem.uuid);
|
||||
rotateElement(ctx, elem, () => {
|
||||
// ctx.setFillStyle(desc.color);
|
||||
|
|
@ -24,24 +20,21 @@ export function drawSVG (
|
|||
}
|
||||
|
||||
// import {
|
||||
// TypeContext,
|
||||
// TypeElement,
|
||||
// TypeHelperConfig,
|
||||
// IDrawContext,
|
||||
// DataElement,
|
||||
// HelperConfig,
|
||||
// } from '@idraw/types';
|
||||
// import Loader from '../loader';
|
||||
// import { drawBox } from './base';
|
||||
|
||||
// export function drawSVG(
|
||||
// ctx: TypeContext,
|
||||
// elem: TypeElement<'svg'>,
|
||||
// ctx: IDrawContext,
|
||||
// elem: DataElement<'svg'>,
|
||||
// loader: Loader,
|
||||
// helperConfig: TypeHelperConfig
|
||||
// helperConfig: HelperConfig
|
||||
// ) {
|
||||
// const content = loader.getPattern(elem, {
|
||||
// forceUpdate: helperConfig?.selectedElementWrapper?.uuid === elem.uuid
|
||||
// });
|
||||
// drawBox(ctx, elem, content);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { TypeContext, TypeElemDescText, TypeElement } from '@idraw/types';
|
||||
import { IDrawContext, DataElemDescText, DataElement } from '@idraw/types';
|
||||
import { is, isColorStr } from '@idraw/util';
|
||||
import Loader from '../loader';
|
||||
import { clearContext, drawBox } from './base';
|
||||
import { rotateElement } from './../transform';
|
||||
|
||||
export function drawText(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<'text'>,
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<'text'>,
|
||||
loader: Loader
|
||||
) {
|
||||
clearContext(ctx);
|
||||
drawBox(ctx, elem, elem.desc.bgColor || 'transparent');
|
||||
rotateElement(ctx, elem, () => {
|
||||
const desc: TypeElemDescText = {
|
||||
const desc: DataElemDescText = {
|
||||
...{
|
||||
fontSize: 12,
|
||||
fontFamily: 'sans-serif',
|
||||
|
|
@ -149,7 +149,7 @@ export function drawText(
|
|||
});
|
||||
}
|
||||
|
||||
// export function createTextSVG(elem: TypeElement<'text'>): string {
|
||||
// export function createTextSVG(elem: DataElement<'text'>): string {
|
||||
// const svg = `
|
||||
// <svg xmlns="http://www.w3.org/2000/svg" width="${elem.w}" height = "${elem.h}">
|
||||
// <foreignObject width="100%" height="100%">
|
||||
|
|
|
|||
|
|
@ -1,43 +1,53 @@
|
|||
import { TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
import { DataElement, DataElemDesc } from '@idraw/types';
|
||||
|
||||
export type TypeLoadDataItem = {
|
||||
uuid: string,
|
||||
type: 'image' | 'svg' | 'html',
|
||||
status: 'null' | 'loaded' | 'fail',
|
||||
content: null | HTMLImageElement | HTMLCanvasElement,
|
||||
uuid: string;
|
||||
type: 'image' | 'svg' | 'html';
|
||||
status: 'null' | 'loaded' | 'fail';
|
||||
content: null | HTMLImageElement | HTMLCanvasElement;
|
||||
elemW: number;
|
||||
elemH: number;
|
||||
source: string,
|
||||
element: TypeElement<keyof TypeElemDesc>
|
||||
error?: any,
|
||||
}
|
||||
source: string;
|
||||
element: DataElement<keyof DataElemDesc>;
|
||||
error?: any;
|
||||
};
|
||||
|
||||
export type TypeLoadData = {
|
||||
[uuid: string]: TypeLoadDataItem
|
||||
}
|
||||
[uuid: string]: TypeLoadDataItem;
|
||||
};
|
||||
|
||||
export type TypeLoaderEventArgMap = {
|
||||
'complete': void;
|
||||
'load': TypeLoadData[string];
|
||||
'error': TypeLoadData[string];
|
||||
}
|
||||
|
||||
export interface TypeLoaderEvent {
|
||||
on<T extends keyof TypeLoaderEventArgMap >(key: T, callback: (p: TypeLoaderEventArgMap[T]) => void): void
|
||||
off<T extends keyof TypeLoaderEventArgMap >(key: T, callback: (p: TypeLoaderEventArgMap[T]) => void): void
|
||||
trigger<T extends keyof TypeLoaderEventArgMap >(key: T, p: TypeLoaderEventArgMap[T]): void
|
||||
}
|
||||
complete: void;
|
||||
load: TypeLoadData[string];
|
||||
error: TypeLoadData[string];
|
||||
};
|
||||
|
||||
export interface TypeLoaderEvent {
|
||||
on<T extends keyof TypeLoaderEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeLoaderEventArgMap[T]) => void
|
||||
): void;
|
||||
off<T extends keyof TypeLoaderEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeLoaderEventArgMap[T]) => void
|
||||
): void;
|
||||
trigger<T extends keyof TypeLoaderEventArgMap>(
|
||||
key: T,
|
||||
p: TypeLoaderEventArgMap[T]
|
||||
): void;
|
||||
}
|
||||
|
||||
export class LoaderEvent implements TypeLoaderEvent {
|
||||
|
||||
private _listeners: Map<string, ((p: any) => void)[]>;
|
||||
|
||||
constructor() {
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
||||
on<T extends keyof TypeLoaderEventArgMap >(eventKey: T, callback: (p: TypeLoaderEventArgMap[T]) => void) {
|
||||
on<T extends keyof TypeLoaderEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeLoaderEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
callbacks?.push(callback);
|
||||
|
|
@ -46,8 +56,11 @@ export class LoaderEvent implements TypeLoaderEvent {
|
|||
this._listeners.set(eventKey, [callback]);
|
||||
}
|
||||
}
|
||||
|
||||
off<T extends keyof TypeLoaderEventArgMap >(eventKey: T, callback: (p: TypeLoaderEventArgMap[T]) => void) {
|
||||
|
||||
off<T extends keyof TypeLoaderEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeLoaderEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
|
|
@ -62,7 +75,10 @@ export class LoaderEvent implements TypeLoaderEvent {
|
|||
}
|
||||
}
|
||||
|
||||
trigger<T extends keyof TypeLoaderEventArgMap >(eventKey: T, arg: TypeLoaderEventArgMap[T]) {
|
||||
trigger<T extends keyof TypeLoaderEventArgMap>(
|
||||
eventKey: T,
|
||||
arg: TypeLoaderEventArgMap[T]
|
||||
) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.forEach((cb) => {
|
||||
|
|
@ -74,14 +90,14 @@ export class LoaderEvent implements TypeLoaderEvent {
|
|||
}
|
||||
}
|
||||
|
||||
has<T extends keyof TypeLoaderEventArgMap> (name: string) {
|
||||
has<T extends keyof TypeLoaderEventArgMap>(name: string) {
|
||||
if (this._listeners.has(name)) {
|
||||
const list: ((p: TypeLoaderEventArgMap[T]) => void)[] | undefined = this._listeners.get(name);
|
||||
const list: ((p: TypeLoaderEventArgMap[T]) => void)[] | undefined =
|
||||
this._listeners.get(name);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
import { TypeData, TypeElement } from '@idraw/types';
|
||||
import { IDrawData, DataElement } from '@idraw/types';
|
||||
import { loadImage, loadSVG, loadHTML, deepClone } from '@idraw/util';
|
||||
import { LoaderEvent, TypeLoadData, TypeLoaderEventArgMap } from './loader-event';
|
||||
import {
|
||||
LoaderEvent,
|
||||
TypeLoadData,
|
||||
TypeLoaderEventArgMap
|
||||
} from './loader-event';
|
||||
import { filterScript } from './../util/filter';
|
||||
|
||||
type Options = {
|
||||
maxParallelNum: number
|
||||
}
|
||||
maxParallelNum: number;
|
||||
};
|
||||
|
||||
enum LoaderStatus {
|
||||
FREE = 'free',
|
||||
LOADING = 'loading',
|
||||
COMPLETE = 'complete',
|
||||
COMPLETE = 'complete'
|
||||
}
|
||||
|
||||
export default class Loader {
|
||||
|
||||
private _opts: Options;
|
||||
private _event: LoaderEvent;
|
||||
// private _patternMap: {[uuid: string]: CanvasPattern} = {}
|
||||
|
|
@ -24,8 +27,8 @@ export default class Loader {
|
|||
private _status: LoaderStatus = LoaderStatus.FREE;
|
||||
|
||||
private _waitingLoadQueue: Array<{
|
||||
uuidQueue: string[],
|
||||
loadData: TypeLoadData,
|
||||
uuidQueue: string[];
|
||||
loadData: TypeLoadData;
|
||||
}> = [];
|
||||
|
||||
constructor(opts: Options) {
|
||||
|
|
@ -34,31 +37,37 @@ export default class Loader {
|
|||
this._waitingLoadQueue = [];
|
||||
}
|
||||
|
||||
load(data: TypeData, changeResourceUUIDs: string[]): void {
|
||||
const [uuidQueue, loadData] = this._resetLoadData(data, changeResourceUUIDs);
|
||||
if (this._status === LoaderStatus.FREE || this._status === LoaderStatus.COMPLETE) {
|
||||
load(data: IDrawData, changeResourceUUIDs: string[]): void {
|
||||
const [uuidQueue, loadData] = this._resetLoadData(
|
||||
data,
|
||||
changeResourceUUIDs
|
||||
);
|
||||
if (
|
||||
this._status === LoaderStatus.FREE ||
|
||||
this._status === LoaderStatus.COMPLETE
|
||||
) {
|
||||
this._currentUUIDQueue = uuidQueue;
|
||||
this._currentLoadData = loadData;
|
||||
this._loadTask();
|
||||
} else if (this._status === LoaderStatus.LOADING && uuidQueue.length > 0) {
|
||||
this._waitingLoadQueue.push({
|
||||
uuidQueue,
|
||||
loadData,
|
||||
loadData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
on<T extends keyof TypeLoaderEventArgMap>(
|
||||
name: T,
|
||||
callback: (arg: TypeLoaderEventArgMap[T]
|
||||
) => void) {
|
||||
callback: (arg: TypeLoaderEventArgMap[T]) => void
|
||||
) {
|
||||
this._event.on(name, callback);
|
||||
}
|
||||
|
||||
off<T extends keyof TypeLoaderEventArgMap>(
|
||||
name: T,
|
||||
callback: (arg: TypeLoaderEventArgMap[T]
|
||||
) => void) {
|
||||
callback: (arg: TypeLoaderEventArgMap[T]) => void
|
||||
) {
|
||||
this._event.off(name, callback);
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +83,7 @@ export default class Loader {
|
|||
}
|
||||
|
||||
// getPattern(
|
||||
// elem: TypeElement<keyof TypeElemDesc>,
|
||||
// elem: DataElement<keyof DataElemDesc>,
|
||||
// opts?: {
|
||||
// forceUpdate: boolean
|
||||
// }
|
||||
|
|
@ -91,7 +100,7 @@ export default class Loader {
|
|||
// const tempCtx = board.createContext(tempCanvas);
|
||||
// const image = this.getContent(elem.uuid);
|
||||
// tempCtx.drawImage(image, elem.x, elem.y, elem.w, elem.h);
|
||||
|
||||
|
||||
// const canvas = board.createCanvas();
|
||||
// const ctx = board.createContext(canvas);
|
||||
// const pattern = ctx.createPattern(tempCanvas, 'no-repeat');
|
||||
|
|
@ -101,7 +110,10 @@ export default class Loader {
|
|||
// return null;
|
||||
// }
|
||||
|
||||
private _resetLoadData(data: TypeData, changeResourceUUIDs: string[]): [string[], TypeLoadData] {
|
||||
private _resetLoadData(
|
||||
data: IDrawData,
|
||||
changeResourceUUIDs: string[]
|
||||
): [string[], TypeLoadData] {
|
||||
const loadData: TypeLoadData = {};
|
||||
const uuidQueue: string[] = [];
|
||||
|
||||
|
|
@ -109,10 +121,10 @@ export default class Loader {
|
|||
// const currentUUIDs: string[] = []
|
||||
|
||||
// add new load-data
|
||||
for (let i = data.elements.length - 1; i >= 0; i --) {
|
||||
const elem = data.elements[i] as TypeElement<'image' | 'svg' | 'html'>;
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const elem = data.elements[i] as DataElement<'image' | 'svg' | 'html'>;
|
||||
// currentUUIDs.push(elem.uuid);
|
||||
if (['image', 'svg', 'html', ].includes(elem.type)) {
|
||||
if (['image', 'svg', 'html'].includes(elem.type)) {
|
||||
if (!storageLoadData[elem.uuid]) {
|
||||
loadData[elem.uuid] = this._createEmptyLoadItem(elem);
|
||||
uuidQueue.push(elem.uuid);
|
||||
|
|
@ -122,24 +134,24 @@ export default class Loader {
|
|||
uuidQueue.push(elem.uuid);
|
||||
}
|
||||
// if (elem.type === 'image') {
|
||||
// const _ele = elem as TypeElement<'image'>;
|
||||
// const _ele = elem as DataElement<'image'>;
|
||||
// if (_ele.desc.src !== storageLoadData[elem.uuid].source) {
|
||||
// loadData[elem.uuid] = this._createEmptyLoadItem(elem);
|
||||
// uuidQueue.push(elem.uuid);
|
||||
// }
|
||||
// } else if (elem.type === 'svg') {
|
||||
// const _ele = elem as TypeElement<'svg'>;
|
||||
// const _ele = elem as DataElement<'svg'>;
|
||||
// if (_ele.desc.svg !== storageLoadData[elem.uuid].source) {
|
||||
// loadData[elem.uuid] = this._createEmptyLoadItem(elem);
|
||||
// uuidQueue.push(elem.uuid);
|
||||
// }
|
||||
// } else if (elem.type === 'html') {
|
||||
// const _ele = elem as TypeElement<'html'>;
|
||||
// const _ele = elem as DataElement<'html'>;
|
||||
// if (filterScript(_ele.desc.html) !== storageLoadData[elem.uuid].source) {
|
||||
// loadData[elem.uuid] = this._createEmptyLoadItem(elem);
|
||||
// uuidQueue.push(elem.uuid);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -154,20 +166,23 @@ export default class Loader {
|
|||
return [uuidQueue, loadData];
|
||||
}
|
||||
|
||||
private _createEmptyLoadItem(elem: TypeElement<'image' | 'svg' | 'html'>): TypeLoadData[string] {
|
||||
private _createEmptyLoadItem(
|
||||
elem: DataElement<'image' | 'svg' | 'html'>
|
||||
): TypeLoadData[string] {
|
||||
let source = '';
|
||||
|
||||
const type: TypeLoadData[string]['type'] = elem.type as TypeLoadData[string]['type'];
|
||||
const type: TypeLoadData[string]['type'] =
|
||||
elem.type as TypeLoadData[string]['type'];
|
||||
let elemW: number = elem.w;
|
||||
let elemH: number = elem.h;
|
||||
if (elem.type === 'image') {
|
||||
const _elem = elem as TypeElement<'image'>;
|
||||
const _elem = elem as DataElement<'image'>;
|
||||
source = _elem.desc.src || '';
|
||||
} else if (elem.type === 'svg') {
|
||||
const _elem = elem as TypeElement<'svg'>;
|
||||
const _elem = elem as DataElement<'svg'>;
|
||||
source = _elem.desc.svg || '';
|
||||
} else if (elem.type === 'html') {
|
||||
const _elem = elem as TypeElement<'html'>;
|
||||
const _elem = elem as DataElement<'html'>;
|
||||
source = filterScript(_elem.desc.html || '');
|
||||
elemW = _elem.desc.width || elem.w;
|
||||
elemH = _elem.desc.height || elem.h;
|
||||
|
|
@ -180,7 +195,7 @@ export default class Loader {
|
|||
source,
|
||||
elemW,
|
||||
elemH,
|
||||
element: deepClone(elem),
|
||||
element: deepClone(elem)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -207,14 +222,13 @@ export default class Loader {
|
|||
|
||||
const { maxParallelNum } = this._opts;
|
||||
const uuids = this._currentUUIDQueue.splice(0, maxParallelNum);
|
||||
const uuidMap: {[uuid: string]: number} = {};
|
||||
const uuidMap: { [uuid: string]: number } = {};
|
||||
|
||||
uuids.forEach((url, i) => {
|
||||
uuidMap[url] = i;
|
||||
});
|
||||
const loadUUIDList: string[] = [];
|
||||
const _loadAction = () => {
|
||||
|
||||
if (loadUUIDList.length >= maxParallelNum) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -229,75 +243,83 @@ export default class Loader {
|
|||
}
|
||||
loadUUIDList.push(uuid);
|
||||
|
||||
this._loadElementSource(this._currentLoadData[uuid]).then((image) => {
|
||||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1);
|
||||
const status = _loadAction();
|
||||
this._loadElementSource(this._currentLoadData[uuid])
|
||||
.then((image) => {
|
||||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1);
|
||||
const status = _loadAction();
|
||||
|
||||
this._storageLoadData[uuid] = {
|
||||
uuid,
|
||||
type: this._currentLoadData[uuid].type,
|
||||
status: 'loaded',
|
||||
content: image,
|
||||
source: this._currentLoadData[uuid].source,
|
||||
elemW: this._currentLoadData[uuid].elemW,
|
||||
elemH: this._currentLoadData[uuid].elemH,
|
||||
element: this._currentLoadData[uuid].element,
|
||||
};
|
||||
|
||||
if (loadUUIDList.length === 0 && uuids.length === 0 && status === true) {
|
||||
this._status = LoaderStatus.FREE;
|
||||
this._loadTask();
|
||||
}
|
||||
this._event.trigger('load', {
|
||||
uuid: this._storageLoadData[uuid]?.uuid,
|
||||
type: this._storageLoadData[uuid].type,
|
||||
status: this._storageLoadData[uuid].status,
|
||||
content: this._storageLoadData[uuid].content,
|
||||
source: this._storageLoadData[uuid].source,
|
||||
elemW: this._storageLoadData[uuid].elemW,
|
||||
elemH: this._storageLoadData[uuid].elemH,
|
||||
element: this._storageLoadData[uuid]?.element,
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn(err);
|
||||
|
||||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1);
|
||||
const status = _loadAction();
|
||||
|
||||
if (this._currentLoadData[uuid]) {
|
||||
this._storageLoadData[uuid] = {
|
||||
uuid,
|
||||
type: this._currentLoadData[uuid]?.type,
|
||||
status: 'fail',
|
||||
content: null,
|
||||
error: err,
|
||||
source: this._currentLoadData[uuid]?.source,
|
||||
elemW: this._currentLoadData[uuid]?.elemW,
|
||||
elemH: this._currentLoadData[uuid]?.elemH,
|
||||
element: this._currentLoadData[uuid]?.element,
|
||||
type: this._currentLoadData[uuid].type,
|
||||
status: 'loaded',
|
||||
content: image,
|
||||
source: this._currentLoadData[uuid].source,
|
||||
elemW: this._currentLoadData[uuid].elemW,
|
||||
elemH: this._currentLoadData[uuid].elemH,
|
||||
element: this._currentLoadData[uuid].element
|
||||
};
|
||||
}
|
||||
|
||||
if (loadUUIDList.length === 0 && uuids.length === 0 && status === true) {
|
||||
this._status = LoaderStatus.FREE;
|
||||
this._loadTask();
|
||||
}
|
||||
|
||||
if (this._currentLoadData[uuid]) {
|
||||
this._event.trigger('error', {
|
||||
uuid: uuid,
|
||||
type: this._storageLoadData[uuid]?.type,
|
||||
status: this._storageLoadData[uuid]?.status,
|
||||
content: this._storageLoadData[uuid]?.content,
|
||||
source: this._storageLoadData[uuid]?.source,
|
||||
elemW: this._storageLoadData[uuid]?.elemW,
|
||||
elemH: this._storageLoadData[uuid]?.elemH,
|
||||
element: this._storageLoadData[uuid]?.element,
|
||||
if (
|
||||
loadUUIDList.length === 0 &&
|
||||
uuids.length === 0 &&
|
||||
status === true
|
||||
) {
|
||||
this._status = LoaderStatus.FREE;
|
||||
this._loadTask();
|
||||
}
|
||||
this._event.trigger('load', {
|
||||
uuid: this._storageLoadData[uuid]?.uuid,
|
||||
type: this._storageLoadData[uuid].type,
|
||||
status: this._storageLoadData[uuid].status,
|
||||
content: this._storageLoadData[uuid].content,
|
||||
source: this._storageLoadData[uuid].source,
|
||||
elemW: this._storageLoadData[uuid].elemW,
|
||||
elemH: this._storageLoadData[uuid].elemH,
|
||||
element: this._storageLoadData[uuid]?.element
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn(err);
|
||||
|
||||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1);
|
||||
const status = _loadAction();
|
||||
|
||||
if (this._currentLoadData[uuid]) {
|
||||
this._storageLoadData[uuid] = {
|
||||
uuid,
|
||||
type: this._currentLoadData[uuid]?.type,
|
||||
status: 'fail',
|
||||
content: null,
|
||||
error: err,
|
||||
source: this._currentLoadData[uuid]?.source,
|
||||
elemW: this._currentLoadData[uuid]?.elemW,
|
||||
elemH: this._currentLoadData[uuid]?.elemH,
|
||||
element: this._currentLoadData[uuid]?.element
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
loadUUIDList.length === 0 &&
|
||||
uuids.length === 0 &&
|
||||
status === true
|
||||
) {
|
||||
this._status = LoaderStatus.FREE;
|
||||
this._loadTask();
|
||||
}
|
||||
|
||||
if (this._currentLoadData[uuid]) {
|
||||
this._event.trigger('error', {
|
||||
uuid: uuid,
|
||||
type: this._storageLoadData[uuid]?.type,
|
||||
status: this._storageLoadData[uuid]?.status,
|
||||
content: this._storageLoadData[uuid]?.content,
|
||||
source: this._storageLoadData[uuid]?.source,
|
||||
elemW: this._storageLoadData[uuid]?.elemW,
|
||||
elemH: this._storageLoadData[uuid]?.elemH,
|
||||
element: this._storageLoadData[uuid]?.element
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
@ -311,20 +333,15 @@ export default class Loader {
|
|||
const image = await loadImage(params.source);
|
||||
return image;
|
||||
} else if (params && params.type === 'svg') {
|
||||
const image = await loadSVG(
|
||||
params.source
|
||||
);
|
||||
const image = await loadSVG(params.source);
|
||||
return image;
|
||||
} else if (params && params.type === 'html') {
|
||||
const image = await loadHTML(
|
||||
params.source, {
|
||||
width: params.elemW, height: params.elemH
|
||||
}
|
||||
);
|
||||
const image = await loadHTML(params.source, {
|
||||
width: params.elemW,
|
||||
height: params.elemH
|
||||
});
|
||||
return image;
|
||||
}
|
||||
throw Error('Element\'s source is not support!');
|
||||
throw Error("Element's source is not support!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { TypeData, TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
import { IDrawData, DataElement, DataElemDesc } from '@idraw/types';
|
||||
import { elementNames } from './../constant/element';
|
||||
|
||||
export function parseData(data: any): TypeData {
|
||||
const result: TypeData = {
|
||||
export function parseData(data: any): IDrawData {
|
||||
const result: IDrawData = {
|
||||
elements: []
|
||||
};
|
||||
if (Array.isArray(data?.elements)) {
|
||||
|
|
@ -18,7 +18,7 @@ export function parseData(data: any): TypeData {
|
|||
return result;
|
||||
}
|
||||
|
||||
function isElement(elem: TypeElement<keyof TypeElemDesc>): boolean {
|
||||
function isElement(elem: DataElement<keyof DataElemDesc>): boolean {
|
||||
if (
|
||||
!(
|
||||
isNumber(elem.x) &&
|
||||
|
|
|
|||
|
|
@ -1,30 +1,39 @@
|
|||
import { TypeElement, TypeElemDesc } from '@idraw/types';
|
||||
|
||||
import { DataElement, DataElemDesc } from '@idraw/types';
|
||||
|
||||
export type TypeRendererEventArgMap = {
|
||||
'drawFrame': { t: number };
|
||||
'drawFrameComplete': { t: number };
|
||||
'load': { element: TypeElement<keyof TypeElemDesc> },
|
||||
'loadComplete': { t: number },
|
||||
'error': { element: TypeElement<keyof TypeElemDesc>, error: any }
|
||||
}
|
||||
|
||||
export interface TypeRendererEvent {
|
||||
on<T extends keyof TypeRendererEventArgMap >(key: T, callback: (p: TypeRendererEventArgMap[T]) => void): void
|
||||
off<T extends keyof TypeRendererEventArgMap >(key: T, callback: (p: TypeRendererEventArgMap[T]) => void): void
|
||||
trigger<T extends keyof TypeRendererEventArgMap >(key: T, p: TypeRendererEventArgMap[T]): void
|
||||
}
|
||||
drawFrame: { t: number };
|
||||
drawFrameComplete: { t: number };
|
||||
load: { element: DataElement<keyof DataElemDesc> };
|
||||
loadComplete: { t: number };
|
||||
error: { element: DataElement<keyof DataElemDesc>; error: any };
|
||||
};
|
||||
|
||||
export interface TypeRendererEvent {
|
||||
on<T extends keyof TypeRendererEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeRendererEventArgMap[T]) => void
|
||||
): void;
|
||||
off<T extends keyof TypeRendererEventArgMap>(
|
||||
key: T,
|
||||
callback: (p: TypeRendererEventArgMap[T]) => void
|
||||
): void;
|
||||
trigger<T extends keyof TypeRendererEventArgMap>(
|
||||
key: T,
|
||||
p: TypeRendererEventArgMap[T]
|
||||
): void;
|
||||
}
|
||||
|
||||
export class RendererEvent implements TypeRendererEvent {
|
||||
|
||||
private _listeners: Map<string, ((p: any) => void)[]>;
|
||||
|
||||
constructor() {
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
||||
on<T extends keyof TypeRendererEventArgMap >(eventKey: T, callback: (p: TypeRendererEventArgMap[T]) => void) {
|
||||
on<T extends keyof TypeRendererEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeRendererEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
callbacks?.push(callback);
|
||||
|
|
@ -33,8 +42,11 @@ export class RendererEvent implements TypeRendererEvent {
|
|||
this._listeners.set(eventKey, [callback]);
|
||||
}
|
||||
}
|
||||
|
||||
off<T extends keyof TypeRendererEventArgMap >(eventKey: T, callback: (p: TypeRendererEventArgMap[T]) => void) {
|
||||
|
||||
off<T extends keyof TypeRendererEventArgMap>(
|
||||
eventKey: T,
|
||||
callback: (p: TypeRendererEventArgMap[T]) => void
|
||||
) {
|
||||
if (this._listeners.has(eventKey)) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
|
|
@ -49,7 +61,10 @@ export class RendererEvent implements TypeRendererEvent {
|
|||
}
|
||||
}
|
||||
|
||||
trigger<T extends keyof TypeRendererEventArgMap >(eventKey: T, arg: TypeRendererEventArgMap[T]) {
|
||||
trigger<T extends keyof TypeRendererEventArgMap>(
|
||||
eventKey: T,
|
||||
arg: TypeRendererEventArgMap[T]
|
||||
) {
|
||||
const callbacks = this._listeners.get(eventKey);
|
||||
if (Array.isArray(callbacks)) {
|
||||
callbacks.forEach((cb) => {
|
||||
|
|
@ -61,14 +76,14 @@ export class RendererEvent implements TypeRendererEvent {
|
|||
}
|
||||
}
|
||||
|
||||
has<T extends keyof TypeRendererEventArgMap> (name: string) {
|
||||
has<T extends keyof TypeRendererEventArgMap>(name: string) {
|
||||
if (this._listeners.has(name)) {
|
||||
const list: ((p: TypeRendererEventArgMap[T]) => void)[] | undefined = this._listeners.get(name);
|
||||
const list: ((p: TypeRendererEventArgMap[T]) => void)[] | undefined =
|
||||
this._listeners.get(name);
|
||||
if (Array.isArray(list) && list.length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { TypeHelperWrapperControllerDirection, TypePoint } from '@idraw/types';
|
||||
import { HelperWrapperControllerDirection, Point } from '@idraw/types';
|
||||
import { Mode, CursorStatus } from './../constant/static';
|
||||
|
||||
type TempDataDesc = {
|
||||
hasInited: boolean;
|
||||
onlyRender: boolean;
|
||||
mode: Mode,
|
||||
cursorStatus: CursorStatus
|
||||
selectedUUID: string | null,
|
||||
selectedUUIDList: string[],
|
||||
hoverUUID: string | null,
|
||||
selectedControllerDirection: TypeHelperWrapperControllerDirection | null,
|
||||
hoverControllerDirection: TypeHelperWrapperControllerDirection | null,
|
||||
prevPoint: TypePoint | null,
|
||||
}
|
||||
mode: Mode;
|
||||
cursorStatus: CursorStatus;
|
||||
selectedUUID: string | null;
|
||||
selectedUUIDList: string[];
|
||||
hoverUUID: string | null;
|
||||
selectedControllerDirection: HelperWrapperControllerDirection | null;
|
||||
hoverControllerDirection: HelperWrapperControllerDirection | null;
|
||||
prevPoint: Point | null;
|
||||
};
|
||||
|
||||
function createData(): TempDataDesc {
|
||||
return {
|
||||
|
|
@ -25,28 +25,26 @@ function createData(): TempDataDesc {
|
|||
hoverUUID: null,
|
||||
selectedControllerDirection: null,
|
||||
hoverControllerDirection: null,
|
||||
prevPoint: null,
|
||||
}
|
||||
prevPoint: null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export class TempData {
|
||||
|
||||
private _temp: TempDataDesc
|
||||
private _temp: TempDataDesc;
|
||||
|
||||
constructor() {
|
||||
this._temp = createData();
|
||||
}
|
||||
|
||||
set<T extends keyof TempDataDesc >(name: T, value: TempDataDesc[T]) {
|
||||
set<T extends keyof TempDataDesc>(name: T, value: TempDataDesc[T]) {
|
||||
this._temp[name] = value;
|
||||
}
|
||||
|
||||
get<T extends keyof TempDataDesc >(name: T): TempDataDesc[T] {
|
||||
get<T extends keyof TempDataDesc>(name: T): TempDataDesc[T] {
|
||||
return this._temp[name];
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._temp = createData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,35 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypePoint,
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
} from '@idraw/types';
|
||||
import { IDrawContext, Point, DataElement, DataElemDesc } from '@idraw/types';
|
||||
import { calcElementCenter, parseAngleToRadian } from './calculate';
|
||||
|
||||
function rotateElement(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<keyof TypeElemDesc>,
|
||||
callback: (ctx: TypeContext) => void
|
||||
ctx: IDrawContext,
|
||||
elem: DataElement<keyof DataElemDesc>,
|
||||
callback: (ctx: IDrawContext) => void
|
||||
): void {
|
||||
const center: TypePoint = calcElementCenter(elem);
|
||||
const center: Point = calcElementCenter(elem);
|
||||
const radian = parseAngleToRadian(elem.angle || 0);
|
||||
return rotateContext(ctx, center, radian || 0, callback);
|
||||
}
|
||||
|
||||
|
||||
function rotateContext(
|
||||
ctx: TypeContext,
|
||||
center: TypePoint | undefined,
|
||||
ctx: IDrawContext,
|
||||
center: Point | undefined,
|
||||
radian: number,
|
||||
callback: (ctx: TypeContext) => void
|
||||
callback: (ctx: IDrawContext) => void
|
||||
): void {
|
||||
if (center && (radian > 0 || radian < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(radian);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
ctx.translate(-center.x, -center.y);
|
||||
}
|
||||
|
||||
callback(ctx);
|
||||
|
||||
if (center && (radian > 0 || radian < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(- radian);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
ctx.rotate(-radian);
|
||||
ctx.translate(-center.x, -center.y);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
rotateContext,
|
||||
rotateElement,
|
||||
};
|
||||
export { rotateContext, rotateElement };
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
type TypePoint = {
|
||||
type Point = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
type TypeBoardScrollConfig = {
|
||||
type BoardScrollConfig = {
|
||||
color: string;
|
||||
width: number;
|
||||
showBackground?: boolean;
|
||||
};
|
||||
|
||||
type TypeBoardSizeOptions = {
|
||||
type BoardSizeOptions = {
|
||||
width?: number;
|
||||
height?: number;
|
||||
contextWidth?: number;
|
||||
|
|
@ -17,16 +17,16 @@ type TypeBoardSizeOptions = {
|
|||
devicePixelRatio?: number;
|
||||
};
|
||||
|
||||
type TypeBoardOptions = TypeBoardSizeOptions & {
|
||||
type BoardOptions = BoardSizeOptions & {
|
||||
width: number;
|
||||
height: number;
|
||||
contextWidth: number;
|
||||
contextHeight: number;
|
||||
canScroll?: boolean;
|
||||
scrollConfig?: TypeBoardScrollConfig;
|
||||
scrollConfig?: BoardScrollConfig;
|
||||
};
|
||||
|
||||
type TypePointCursor =
|
||||
type PointCursor =
|
||||
| 'auto'
|
||||
| 'move'
|
||||
| 'n-resize'
|
||||
|
|
@ -40,9 +40,9 @@ type TypePointCursor =
|
|||
| 'grab';
|
||||
|
||||
export {
|
||||
TypePoint,
|
||||
TypePointCursor,
|
||||
TypeBoardSizeOptions,
|
||||
TypeBoardOptions,
|
||||
TypeBoardScrollConfig
|
||||
Point,
|
||||
PointCursor,
|
||||
BoardSizeOptions,
|
||||
BoardOptions,
|
||||
BoardScrollConfig
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,38 +1,35 @@
|
|||
type TypeIs = {
|
||||
x: (value: any) => boolean,
|
||||
y: (value: any) => boolean,
|
||||
w: (value: any) => boolean,
|
||||
h: (value: any) => boolean,
|
||||
angle: (value: any) => boolean,
|
||||
number: (value: any) => boolean,
|
||||
borderWidth: (value: any) => boolean,
|
||||
borderRadius: (value: any) => boolean,
|
||||
color: (value: any) => boolean,
|
||||
imageSrc: (value: any) => boolean,
|
||||
imageURL: (value: any) => boolean,
|
||||
imageBase64: (value: any) => boolean,
|
||||
svg: (value: any) => boolean,
|
||||
html: (value: any) => boolean,
|
||||
text: (value: any) => boolean,
|
||||
fontSize: (value: any) => boolean,
|
||||
fontWeight: (value: any) => boolean,
|
||||
lineHeight: (value: any) => boolean,
|
||||
textAlign: (value: any) => boolean,
|
||||
fontFamily: (value: any) => boolean,
|
||||
strokeWidth: (value: any) => boolean,
|
||||
}
|
||||
type IsTypeUtil = {
|
||||
x: (value: any) => boolean;
|
||||
y: (value: any) => boolean;
|
||||
w: (value: any) => boolean;
|
||||
h: (value: any) => boolean;
|
||||
angle: (value: any) => boolean;
|
||||
number: (value: any) => boolean;
|
||||
borderWidth: (value: any) => boolean;
|
||||
borderRadius: (value: any) => boolean;
|
||||
color: (value: any) => boolean;
|
||||
imageSrc: (value: any) => boolean;
|
||||
imageURL: (value: any) => boolean;
|
||||
imageBase64: (value: any) => boolean;
|
||||
svg: (value: any) => boolean;
|
||||
html: (value: any) => boolean;
|
||||
text: (value: any) => boolean;
|
||||
fontSize: (value: any) => boolean;
|
||||
fontWeight: (value: any) => boolean;
|
||||
lineHeight: (value: any) => boolean;
|
||||
textAlign: (value: any) => boolean;
|
||||
fontFamily: (value: any) => boolean;
|
||||
strokeWidth: (value: any) => boolean;
|
||||
};
|
||||
|
||||
type TypeCheck = {
|
||||
attrs: (value: any) => boolean,
|
||||
rectDesc: (value: any) => boolean,
|
||||
circleDesc: (value: any) => boolean,
|
||||
imageDesc: (value: any) => boolean,
|
||||
svgDesc: (value: any) => boolean,
|
||||
htmlDesc: (value: any) => boolean,
|
||||
textDesc: (value: any) => boolean,
|
||||
}
|
||||
type CheckTypeUtil = {
|
||||
attrs: (value: any) => boolean;
|
||||
rectDesc: (value: any) => boolean;
|
||||
circleDesc: (value: any) => boolean;
|
||||
imageDesc: (value: any) => boolean;
|
||||
svgDesc: (value: any) => boolean;
|
||||
htmlDesc: (value: any) => boolean;
|
||||
textDesc: (value: any) => boolean;
|
||||
};
|
||||
|
||||
export {
|
||||
TypeIs,
|
||||
TypeCheck,
|
||||
}
|
||||
export { IsTypeUtil, CheckTypeUtil };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
type TypeConfig = {
|
||||
type IDrawConfig = {
|
||||
elementWrapper?: {
|
||||
color?: string;
|
||||
controllerSize?: number;
|
||||
|
|
@ -13,7 +13,7 @@ type TypeConfig = {
|
|||
};
|
||||
};
|
||||
|
||||
type TypeConfigStrict = TypeConfig & {
|
||||
type IDrawConfigStrict = IDrawConfig & {
|
||||
elementWrapper: {
|
||||
color: string;
|
||||
lockColor: string;
|
||||
|
|
@ -23,4 +23,4 @@ type TypeConfigStrict = TypeConfig & {
|
|||
};
|
||||
};
|
||||
|
||||
export { TypeConfig, TypeConfigStrict };
|
||||
export { IDrawConfig, IDrawConfigStrict };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
interface TypeContext {
|
||||
interface IDrawContext {
|
||||
getContext(): CanvasRenderingContext2D;
|
||||
setTransform(config: {
|
||||
scale?: number;
|
||||
|
|
@ -67,5 +67,5 @@ interface TypeContext {
|
|||
}
|
||||
|
||||
export {
|
||||
TypeContext
|
||||
IDrawContext
|
||||
};
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
|
||||
type TypeCoreOptions = {
|
||||
type CoreOptions = {
|
||||
width: number;
|
||||
height: number;
|
||||
devicePixelRatio: number;
|
||||
contextWidth: number;
|
||||
contextHeight: number;
|
||||
onlyRender?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
TypeCoreOptions
|
||||
};
|
||||
export { CoreOptions };
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
import { TypeElemDesc, TypeElement, TypeElementBase } from './element';
|
||||
import { DataElemDesc, DataElement, DataElementBase } from './element';
|
||||
|
||||
type TypeDataBase = {
|
||||
elements: TypeElementBase<keyof TypeElemDesc>[];
|
||||
type IDrawDataBase = {
|
||||
elements: DataElementBase<keyof DataElemDesc>[];
|
||||
bgColor?: string;
|
||||
}
|
||||
};
|
||||
|
||||
type TypeData = {
|
||||
elements: TypeElement<keyof TypeElemDesc>[];
|
||||
type IDrawData = {
|
||||
elements: DataElement<keyof DataElemDesc>[];
|
||||
bgColor?: string;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export {
|
||||
TypeData,
|
||||
TypeDataBase,
|
||||
};
|
||||
export { IDrawData, IDrawDataBase };
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
type TypeDeviceSize = {
|
||||
type DeviceSize = {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
TypeDeviceSize,
|
||||
};
|
||||
export { DeviceSize };
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// import { TypePaintData } from './paint';
|
||||
// import { PaintData } from './paint';
|
||||
|
||||
type TypeElementAttrs = {
|
||||
type DataElementAttrs = {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
|
|
@ -16,43 +16,43 @@ type TypeElementAttrs = {
|
|||
extension?: { [key: string]: any } | any;
|
||||
};
|
||||
|
||||
type TypeElementBase<T extends keyof TypeElemDesc | TypeElemType> =
|
||||
TypeElementAttrs & {
|
||||
type DataElementBase<T extends keyof DataElemDesc | DataElemType> =
|
||||
DataElementAttrs & {
|
||||
name?: string;
|
||||
uuid?: string;
|
||||
type: T | TypeElemType;
|
||||
desc: TypeElemDesc[T];
|
||||
type: T | DataElemType;
|
||||
desc: DataElemDesc[T];
|
||||
};
|
||||
|
||||
type TypeElement<T extends keyof TypeElemDesc | TypeElemType> =
|
||||
TypeElementBase<T> & {
|
||||
type DataElement<T extends keyof DataElemDesc | DataElemType> =
|
||||
DataElementBase<T> & {
|
||||
uuid: string;
|
||||
};
|
||||
|
||||
type TypeElemDescBase = {
|
||||
type DataElemDescBase = {
|
||||
shadowColor?: string;
|
||||
shadowOffsetX?: number;
|
||||
shadowOffsetY?: number;
|
||||
shadowBlur?: number;
|
||||
};
|
||||
|
||||
type TypeElemBoxDesc = {
|
||||
type DataElemBoxDesc = {
|
||||
borderRadius?: number;
|
||||
borderWidth?: number;
|
||||
borderColor?: string;
|
||||
} & TypeElemDescBase;
|
||||
} & DataElemDescBase;
|
||||
|
||||
type TypeElemDesc = {
|
||||
text: TypeElemDescText;
|
||||
rect: TypeElemDescRect;
|
||||
circle: TypeElemDescCircle;
|
||||
image: TypeElemDescImage;
|
||||
svg: TypeElemDescSVG;
|
||||
html: TypeElemDescHTML;
|
||||
// paint: TypeElemDescPaint,
|
||||
type DataElemDesc = {
|
||||
text: DataElemDescText;
|
||||
rect: DataElemDescRect;
|
||||
circle: DataElemDescCircle;
|
||||
image: DataElemDescImage;
|
||||
svg: DataElemDescSVG;
|
||||
html: DataElemDescHTML;
|
||||
// paint: DataElemDescPaint,
|
||||
};
|
||||
|
||||
// enum TypeElemType {
|
||||
// enum DataElemType {
|
||||
// text = 'text',
|
||||
// rect = 'rect',
|
||||
// circle = 'circle',
|
||||
|
|
@ -61,13 +61,13 @@ type TypeElemDesc = {
|
|||
// html = 'html',
|
||||
// }
|
||||
|
||||
type TypeElemType = 'text' | 'rect' | 'circle' | 'image' | 'svg' | 'html';
|
||||
type DataElemType = 'text' | 'rect' | 'circle' | 'image' | 'svg' | 'html';
|
||||
|
||||
type TypeElemDescRect = {
|
||||
type DataElemDescRect = {
|
||||
bgColor?: string;
|
||||
} & TypeElemBoxDesc;
|
||||
} & DataElemBoxDesc;
|
||||
|
||||
type TypeElemDescText = {
|
||||
type DataElemDescText = {
|
||||
text: string;
|
||||
color: string;
|
||||
fontSize: number;
|
||||
|
|
@ -83,38 +83,38 @@ type TypeElemDescText = {
|
|||
textShadowOffsetX?: number;
|
||||
textShadowOffsetY?: number;
|
||||
textShadowBlur?: number;
|
||||
} & TypeElemBoxDesc;
|
||||
} & DataElemBoxDesc;
|
||||
|
||||
type TypeElemDescCircle = {
|
||||
type DataElemDescCircle = {
|
||||
bgColor: string;
|
||||
} & TypeElemBoxDesc;
|
||||
} & DataElemBoxDesc;
|
||||
|
||||
type TypeElemDescImage = {
|
||||
type DataElemDescImage = {
|
||||
src: string;
|
||||
} & TypeElemDescBase;
|
||||
} & DataElemDescBase;
|
||||
|
||||
type TypeElemDescSVG = {
|
||||
type DataElemDescSVG = {
|
||||
svg: string;
|
||||
};
|
||||
|
||||
type TypeElemDescHTML = {
|
||||
type DataElemDescHTML = {
|
||||
html: string;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
// type TypeElemDescPaint = TypePaintData
|
||||
// type DataElemDescPaint = PaintData
|
||||
|
||||
export {
|
||||
TypeElementAttrs,
|
||||
TypeElemDescText,
|
||||
TypeElemDescRect,
|
||||
TypeElemDescCircle,
|
||||
TypeElemDescImage,
|
||||
TypeElemDescSVG,
|
||||
TypeElemDescHTML,
|
||||
TypeElemDesc,
|
||||
TypeElemType,
|
||||
TypeElement,
|
||||
TypeElementBase
|
||||
DataElementAttrs,
|
||||
DataElemDescText,
|
||||
DataElemDescRect,
|
||||
DataElemDescCircle,
|
||||
DataElemDescImage,
|
||||
DataElemDescSVG,
|
||||
DataElemDescHTML,
|
||||
DataElemDesc,
|
||||
DataElemType,
|
||||
DataElement,
|
||||
DataElementBase
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,56 +1,55 @@
|
|||
import { TypeData } from './data';
|
||||
import { TypePoint } from './board';
|
||||
import { IDrawData } from './data';
|
||||
import { Point } from './board';
|
||||
|
||||
// type test = {[uuid string]: TypeElement}
|
||||
// type test = {[uuid string]: DataElement}
|
||||
|
||||
type TypeController = TypePoint & {
|
||||
type HelperController = Point & {
|
||||
invisible?: boolean;
|
||||
};
|
||||
|
||||
type TypeHeplerSelectedElementWrapper = {
|
||||
type HeplerSelectedElementWrapper = {
|
||||
uuid: string;
|
||||
controllerSize: number;
|
||||
controllerOffset: number;
|
||||
lock: boolean;
|
||||
controllers: {
|
||||
topLeft: TypeController,
|
||||
top: TypeController,
|
||||
topRight: TypeController,
|
||||
right: TypeController,
|
||||
bottomRight: TypeController,
|
||||
bottom: TypeController,
|
||||
bottomLeft: TypeController,
|
||||
left: TypeController,
|
||||
rotate: TypeController,
|
||||
},
|
||||
topLeft: HelperController;
|
||||
top: HelperController;
|
||||
topRight: HelperController;
|
||||
right: HelperController;
|
||||
bottomRight: HelperController;
|
||||
bottom: HelperController;
|
||||
bottomLeft: HelperController;
|
||||
left: HelperController;
|
||||
rotate: HelperController;
|
||||
};
|
||||
lineDash: number[];
|
||||
lineWidth: number;
|
||||
color: string;
|
||||
radian?: number;
|
||||
translate?: TypePoint;
|
||||
}
|
||||
translate?: Point;
|
||||
};
|
||||
|
||||
type TypeHeplerSelectedAreaWrapper = {
|
||||
type HeplerSelectedAreaWrapper = {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
startPoint: TypePoint;
|
||||
endPoint: TypePoint;
|
||||
startPoint: Point;
|
||||
endPoint: Point;
|
||||
lineWidth: number;
|
||||
lineDash: number[];
|
||||
color: string;
|
||||
}
|
||||
};
|
||||
|
||||
type TypeHelperConfig = {
|
||||
elementIndexMap: {[key: string]: number},
|
||||
selectedAreaWrapper?: TypeHeplerSelectedAreaWrapper;
|
||||
selectedElementWrapper?: TypeHeplerSelectedElementWrapper,
|
||||
selectedElementListWrappers?: Array<TypeHeplerSelectedElementWrapper>;
|
||||
}
|
||||
type HelperConfig = {
|
||||
elementIndexMap: { [key: string]: number };
|
||||
selectedAreaWrapper?: HeplerSelectedAreaWrapper;
|
||||
selectedElementWrapper?: HeplerSelectedElementWrapper;
|
||||
selectedElementListWrappers?: Array<HeplerSelectedElementWrapper>;
|
||||
};
|
||||
|
||||
|
||||
type TypeHelperUpdateOpts = {
|
||||
type HelperUpdateOpts = {
|
||||
width: number;
|
||||
height: number;
|
||||
selectedUUID?: string | null;
|
||||
|
|
@ -60,26 +59,29 @@ type TypeHelperUpdateOpts = {
|
|||
canScroll: boolean;
|
||||
scrollX: number;
|
||||
scrollY: number;
|
||||
};
|
||||
|
||||
interface Helper {
|
||||
updateConfig(data: IDrawData, opts: HelperUpdateOpts): void;
|
||||
getConfig(): HelperConfig;
|
||||
}
|
||||
|
||||
interface TypeHelper {
|
||||
updateConfig(
|
||||
data: TypeData,
|
||||
opts: TypeHelperUpdateOpts
|
||||
): void;
|
||||
getConfig(): TypeHelperConfig;
|
||||
}
|
||||
|
||||
type TypeHelperWrapperControllerDirection
|
||||
= 'top-left' | 'top' | 'top-right' | 'right'
|
||||
| 'bottom-right' | 'bottom' | 'bottom-left' | 'left'
|
||||
| 'rotate';
|
||||
type HelperWrapperControllerDirection =
|
||||
| 'top-left'
|
||||
| 'top'
|
||||
| 'top-right'
|
||||
| 'right'
|
||||
| 'bottom-right'
|
||||
| 'bottom'
|
||||
| 'bottom-left'
|
||||
| 'left'
|
||||
| 'rotate';
|
||||
|
||||
export {
|
||||
TypeHelper,
|
||||
TypeHelperConfig,
|
||||
TypeHelperUpdateOpts,
|
||||
TypeHelperWrapperControllerDirection,
|
||||
TypeHeplerSelectedElementWrapper,
|
||||
TypeHeplerSelectedAreaWrapper,
|
||||
};
|
||||
Helper,
|
||||
HelperConfig,
|
||||
HelperUpdateOpts,
|
||||
HelperWrapperControllerDirection,
|
||||
HeplerSelectedElementWrapper,
|
||||
HeplerSelectedAreaWrapper
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
export type TypePaintData = {
|
||||
brushMap: {[name: string]: TypePaintBrush},
|
||||
paths: TypePaintPath[],
|
||||
}
|
||||
export type PaintData = {
|
||||
brushMap: { [name: string]: PaintBrush };
|
||||
paths: PaintPath[];
|
||||
};
|
||||
|
||||
export type TypePaintBrush = {
|
||||
export type PaintBrush = {
|
||||
name: string;
|
||||
src: string;
|
||||
}
|
||||
};
|
||||
|
||||
export type TypePaintPath = {
|
||||
brush: string,
|
||||
export type PaintPath = {
|
||||
brush: string;
|
||||
size: number;
|
||||
positions: TypePaintPosition[],
|
||||
positions: PaintPosition[];
|
||||
color: string;
|
||||
pressure: number;
|
||||
}
|
||||
};
|
||||
|
||||
export type TypePaintPosition = {
|
||||
x: number,
|
||||
y: number,
|
||||
t: number,
|
||||
}
|
||||
export type PaintPosition = {
|
||||
x: number;
|
||||
y: number;
|
||||
t: number;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,36 +1,39 @@
|
|||
import { TypeData } from './data';
|
||||
import { TypeElemDesc, TypeElement } from './element';
|
||||
import { TypeContext } from './context';
|
||||
import { TypePoint, TypePointCursor } from './board';
|
||||
import { IDrawData } from './data';
|
||||
import { DataElemDesc, DataElement } from './element';
|
||||
import { IDrawContext } from './context';
|
||||
import { Point, PointCursor } from './board';
|
||||
|
||||
export type TypeHelperPluginEventDetail = {
|
||||
controller: string | null,
|
||||
point: TypePoint,
|
||||
selectedElement: TypeElement<keyof TypeElemDesc> | null,
|
||||
data: TypeData,
|
||||
helperCtx:TypeContext,
|
||||
}
|
||||
export type HelperPluginEventDetail = {
|
||||
controller: string | null;
|
||||
point: Point;
|
||||
selectedElement: DataElement<keyof DataElemDesc> | null;
|
||||
data: IDrawData;
|
||||
helperCtx: IDrawContext;
|
||||
};
|
||||
|
||||
export type TypeHelperPluginEventResult = {
|
||||
cursor?: TypePointCursor,
|
||||
export type HelperPluginEventResult = {
|
||||
cursor?: PointCursor;
|
||||
beController?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export interface InterfaceHelperPlugin {
|
||||
|
||||
readonly name?: string;
|
||||
|
||||
readonly uuid?: string;
|
||||
|
||||
onHover?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
|
||||
onPoint?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
onHover?: (detail: HelperPluginEventDetail) => void | HelperPluginEventResult;
|
||||
|
||||
onClick?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
onPoint?: (detail: HelperPluginEventDetail) => void | HelperPluginEventResult;
|
||||
|
||||
onMoveStart?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
onClick?: (detail: HelperPluginEventDetail) => void | HelperPluginEventResult;
|
||||
|
||||
onMove?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
onMoveStart?: (
|
||||
detail: HelperPluginEventDetail
|
||||
) => void | HelperPluginEventResult;
|
||||
|
||||
onMoveEnd?: (detail: TypeHelperPluginEventDetail) => void | TypeHelperPluginEventResult;
|
||||
}
|
||||
onMove?: (detail: HelperPluginEventDetail) => void | HelperPluginEventResult;
|
||||
|
||||
onMoveEnd?: (
|
||||
detail: HelperPluginEventDetail
|
||||
) => void | HelperPluginEventResult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,27 @@
|
|||
type TypeScreenData = {
|
||||
type ScreenData = {
|
||||
scale: number;
|
||||
scrollLeft: number;
|
||||
scrollTop: number;
|
||||
// selectedElementUUID: string | null;
|
||||
}
|
||||
};
|
||||
|
||||
type TypeScreenPosition = {
|
||||
type ScreenPosition = {
|
||||
top: number;
|
||||
bottom: number;
|
||||
left: number;
|
||||
right: number;
|
||||
}
|
||||
};
|
||||
|
||||
type TypeScreenSize = {
|
||||
type ScreenSize = {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
}
|
||||
};
|
||||
|
||||
type TypeScreenContext = {
|
||||
size: TypeScreenSize,
|
||||
position: TypeScreenPosition
|
||||
}
|
||||
type ScreenContext = {
|
||||
size: ScreenSize;
|
||||
position: ScreenPosition;
|
||||
};
|
||||
|
||||
export {
|
||||
TypeScreenData,
|
||||
TypeScreenPosition,
|
||||
TypeScreenSize,
|
||||
TypeScreenContext,
|
||||
};
|
||||
export { ScreenData, ScreenPosition, ScreenSize, ScreenContext };
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
|
||||
// import { TypeElementAttrs } from '@idraw/types';
|
||||
// import { DataElementAttrs } from '@idraw/types';
|
||||
import is from './is';
|
||||
|
||||
function attrs(
|
||||
attrs: any
|
||||
): boolean {
|
||||
function attrs(attrs: any): boolean {
|
||||
const { x, y, w, h, angle } = attrs;
|
||||
if (!(is.x(x) && is.y(y) && is.w(w) && is.h(h) && is.angle(angle))) {
|
||||
return false;
|
||||
}
|
||||
if (!(angle >= -360 && angle <= 360 )) {
|
||||
if (!(angle >= -360 && angle <= 360)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function box(
|
||||
desc: any = {},
|
||||
): boolean {
|
||||
function box(desc: any = {}): boolean {
|
||||
const { borderColor, borderRadius, borderWidth } = desc;
|
||||
if (desc.hasOwnProperty('borderColor') && !is.color(borderColor)) {
|
||||
return false;
|
||||
|
|
@ -31,9 +26,7 @@ function box(
|
|||
return true;
|
||||
}
|
||||
|
||||
function rectDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function rectDesc(desc: any): boolean {
|
||||
const { bgColor } = desc;
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
|
|
@ -44,9 +37,7 @@ function rectDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function circleDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function circleDesc(desc: any): boolean {
|
||||
const { bgColor, borderColor, borderWidth } = desc;
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
|
|
@ -60,10 +51,7 @@ function circleDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
function imageDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function imageDesc(desc: any): boolean {
|
||||
const { src } = desc;
|
||||
if (!is.imageSrc(src)) {
|
||||
return false;
|
||||
|
|
@ -71,9 +59,7 @@ function imageDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function svgDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function svgDesc(desc: any): boolean {
|
||||
const { svg } = desc;
|
||||
if (!is.svg(svg)) {
|
||||
return false;
|
||||
|
|
@ -81,9 +67,7 @@ function svgDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function htmlDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function htmlDesc(desc: any): boolean {
|
||||
const { html } = desc;
|
||||
if (!is.html(html)) {
|
||||
return false;
|
||||
|
|
@ -91,44 +75,50 @@ function htmlDesc(
|
|||
return true;
|
||||
}
|
||||
|
||||
function textDesc(
|
||||
desc: any
|
||||
): boolean {
|
||||
function textDesc(desc: any): boolean {
|
||||
const {
|
||||
text, color, fontSize, lineHeight, fontFamily, textAlign,
|
||||
fontWeight, bgColor, strokeWidth, strokeColor
|
||||
text,
|
||||
color,
|
||||
fontSize,
|
||||
lineHeight,
|
||||
fontFamily,
|
||||
textAlign,
|
||||
fontWeight,
|
||||
bgColor,
|
||||
strokeWidth,
|
||||
strokeColor
|
||||
} = desc;
|
||||
if (!is.text(text)){
|
||||
if (!is.text(text)) {
|
||||
return false;
|
||||
}
|
||||
if (!is.color(color)){
|
||||
if (!is.color(color)) {
|
||||
return false;
|
||||
}
|
||||
if (!is.fontSize(fontSize)){
|
||||
if (!is.fontSize(fontSize)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)){
|
||||
if (desc.hasOwnProperty('bgColor') && !is.color(bgColor)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('fontWeight') && !is.fontWeight(fontWeight)){
|
||||
if (desc.hasOwnProperty('fontWeight') && !is.fontWeight(fontWeight)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('lineHeight') && !is.lineHeight(lineHeight)){
|
||||
if (desc.hasOwnProperty('lineHeight') && !is.lineHeight(lineHeight)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('fontFamily') && !is.fontFamily(fontFamily)){
|
||||
if (desc.hasOwnProperty('fontFamily') && !is.fontFamily(fontFamily)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('textAlign') && !is.textAlign(textAlign)){
|
||||
if (desc.hasOwnProperty('textAlign') && !is.textAlign(textAlign)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('strokeWidth') && !is.strokeWidth(strokeWidth)){
|
||||
if (desc.hasOwnProperty('strokeWidth') && !is.strokeWidth(strokeWidth)) {
|
||||
return false;
|
||||
}
|
||||
if (desc.hasOwnProperty('strokeColor') && !is.color(strokeColor)){
|
||||
if (desc.hasOwnProperty('strokeColor') && !is.color(strokeColor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!box(desc)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -142,8 +132,7 @@ const check = {
|
|||
circleDesc,
|
||||
imageDesc,
|
||||
svgDesc,
|
||||
htmlDesc,
|
||||
htmlDesc
|
||||
};
|
||||
|
||||
|
||||
export default check;
|
||||
export default check;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { TypeContext, TypeBoardSizeOptions } from '@idraw/types';
|
||||
import { IDrawContext, BoardSizeOptions } from '@idraw/types';
|
||||
|
||||
type Options = {
|
||||
width: number;
|
||||
|
|
@ -6,24 +6,24 @@ type Options = {
|
|||
contextWidth: number;
|
||||
contextHeight: number;
|
||||
devicePixelRatio: number;
|
||||
}
|
||||
};
|
||||
|
||||
type Transform = {
|
||||
scale?: number;
|
||||
scrollX?: number;
|
||||
scrollY?: number;
|
||||
}
|
||||
};
|
||||
|
||||
type PrivateTransform = {
|
||||
scale: number;
|
||||
scrollX: number;
|
||||
scrollY: number;
|
||||
}
|
||||
};
|
||||
|
||||
class Context implements TypeContext {
|
||||
class Context implements IDrawContext {
|
||||
private _opts: Options;
|
||||
private _ctx: CanvasRenderingContext2D;
|
||||
private _transform: PrivateTransform;
|
||||
private _transform: PrivateTransform;
|
||||
|
||||
// private _scale: number;
|
||||
// private _scrollX: number;
|
||||
|
|
@ -35,15 +35,15 @@ class Context implements TypeContext {
|
|||
this._transform = {
|
||||
scale: 1,
|
||||
scrollX: 0,
|
||||
scrollY: 0,
|
||||
scrollY: 0
|
||||
};
|
||||
}
|
||||
getContext(): CanvasRenderingContext2D {
|
||||
return this._ctx;
|
||||
}
|
||||
|
||||
resetSize(opts: TypeBoardSizeOptions) {
|
||||
this._opts = {...this._opts, ...opts};
|
||||
resetSize(opts: BoardSizeOptions) {
|
||||
this._opts = { ...this._opts, ...opts };
|
||||
}
|
||||
|
||||
calcDeviceNum(num: number): number {
|
||||
|
|
@ -55,24 +55,24 @@ class Context implements TypeContext {
|
|||
}
|
||||
|
||||
getSize() {
|
||||
return {
|
||||
return {
|
||||
width: this._opts.width,
|
||||
height: this._opts.height,
|
||||
contextWidth: this._opts.contextWidth,
|
||||
contextHeight: this._opts.contextHeight,
|
||||
devicePixelRatio: this._opts.devicePixelRatio,
|
||||
devicePixelRatio: this._opts.devicePixelRatio
|
||||
};
|
||||
}
|
||||
|
||||
setTransform(config: Transform) {
|
||||
this._transform = {...this._transform, ...config};
|
||||
this._transform = { ...this._transform, ...config };
|
||||
}
|
||||
|
||||
getTransform() {
|
||||
return {
|
||||
scale: this._transform.scale,
|
||||
scrollX: this._transform.scrollX,
|
||||
scrollY: this._transform.scrollY,
|
||||
scrollY: this._transform.scrollY
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -84,17 +84,36 @@ class Context implements TypeContext {
|
|||
return this._ctx.fill(fillRule || 'nonzero');
|
||||
}
|
||||
|
||||
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean | undefined): void {
|
||||
return this._ctx.arc(this._doSize(x), this._doSize(y), this._doSize(radius), startAngle, endAngle, anticlockwise);
|
||||
arc(
|
||||
x: number,
|
||||
y: number,
|
||||
radius: number,
|
||||
startAngle: number,
|
||||
endAngle: number,
|
||||
anticlockwise?: boolean | undefined
|
||||
): void {
|
||||
return this._ctx.arc(
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(radius),
|
||||
startAngle,
|
||||
endAngle,
|
||||
anticlockwise
|
||||
);
|
||||
}
|
||||
|
||||
rect(x: number, y: number, w: number, h: number) {
|
||||
return this._ctx.rect(this._doSize(x), this._doSize(y), this._doSize(w), this._doSize(h));
|
||||
return this._ctx.rect(
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(w),
|
||||
this._doSize(h)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
fillRect(x: number, y: number, w: number, h: number) {
|
||||
return this._ctx.fillRect(
|
||||
this._doSize(x),
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(w),
|
||||
this._doSize(h)
|
||||
|
|
@ -103,7 +122,7 @@ class Context implements TypeContext {
|
|||
|
||||
clearRect(x: number, y: number, w: number, h: number) {
|
||||
return this._ctx.clearRect(
|
||||
this._doSize(x),
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(w),
|
||||
this._doSize(h)
|
||||
|
|
@ -127,15 +146,21 @@ class Context implements TypeContext {
|
|||
}
|
||||
|
||||
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void {
|
||||
return this._ctx.arcTo(this._doSize(x1), this._doSize(y1), this._doSize(x2), this._doSize(y2), this._doSize(radius));
|
||||
return this._ctx.arcTo(
|
||||
this._doSize(x1),
|
||||
this._doSize(y1),
|
||||
this._doSize(x2),
|
||||
this._doSize(y2),
|
||||
this._doSize(radius)
|
||||
);
|
||||
}
|
||||
|
||||
setLineWidth(w: number) {
|
||||
return this._ctx.lineWidth = this._doSize(w);
|
||||
return (this._ctx.lineWidth = this._doSize(w));
|
||||
}
|
||||
|
||||
setLineDash(nums: number[]) {
|
||||
return this._ctx.setLineDash(nums.map(n => this._doSize(n)));
|
||||
return this._ctx.setLineDash(nums.map((n) => this._doSize(n)));
|
||||
}
|
||||
|
||||
isPointInPath(x: number, y: number) {
|
||||
|
|
@ -157,7 +182,7 @@ class Context implements TypeContext {
|
|||
translate(x: number, y: number) {
|
||||
return this._ctx.translate(this._doSize(x), this._doSize(y));
|
||||
}
|
||||
|
||||
|
||||
rotate(angle: number) {
|
||||
return this._ctx.rotate(angle);
|
||||
}
|
||||
|
|
@ -175,13 +200,32 @@ class Context implements TypeContext {
|
|||
const dh: number = args[args.length - 1];
|
||||
|
||||
if (args.length === 9) {
|
||||
return this._ctx.drawImage(image, this._doSize(sx), this._doSize(sy), this._doSize(sw), this._doSize(sh), this._doSize(dx), this._doSize(dy), this._doSize(dw), this._doSize(dh));
|
||||
return this._ctx.drawImage(
|
||||
image,
|
||||
this._doSize(sx),
|
||||
this._doSize(sy),
|
||||
this._doSize(sw),
|
||||
this._doSize(sh),
|
||||
this._doSize(dx),
|
||||
this._doSize(dy),
|
||||
this._doSize(dw),
|
||||
this._doSize(dh)
|
||||
);
|
||||
} else {
|
||||
return this._ctx.drawImage(image,this._doSize(dx), this._doSize(dy), this._doSize(dw), this._doSize(dh));
|
||||
return this._ctx.drawImage(
|
||||
image,
|
||||
this._doSize(dx),
|
||||
this._doSize(dy),
|
||||
this._doSize(dw),
|
||||
this._doSize(dh)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null {
|
||||
createPattern(
|
||||
image: CanvasImageSource,
|
||||
repetition: string | null
|
||||
): CanvasPattern | null {
|
||||
return this._ctx.createPattern(image, repetition);
|
||||
}
|
||||
|
||||
|
|
@ -193,23 +237,47 @@ class Context implements TypeContext {
|
|||
this._ctx.textAlign = align;
|
||||
}
|
||||
|
||||
fillText(text: string, x: number, y: number, maxWidth?: number | undefined): void {
|
||||
fillText(
|
||||
text: string,
|
||||
x: number,
|
||||
y: number,
|
||||
maxWidth?: number | undefined
|
||||
): void {
|
||||
if (maxWidth !== undefined) {
|
||||
return this._ctx.fillText(text, this._doSize(x), this._doSize(y), this._doSize(maxWidth));
|
||||
return this._ctx.fillText(
|
||||
text,
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(maxWidth)
|
||||
);
|
||||
} else {
|
||||
return this._ctx.fillText(text, this._doSize(x), this._doSize(y));
|
||||
}
|
||||
}
|
||||
|
||||
strokeText(text: string, x: number, y: number, maxWidth?: number | undefined): void {
|
||||
strokeText(
|
||||
text: string,
|
||||
x: number,
|
||||
y: number,
|
||||
maxWidth?: number | undefined
|
||||
): void {
|
||||
if (maxWidth !== undefined) {
|
||||
return this._ctx.strokeText(text, this._doSize(x), this._doSize(y), this._doSize(maxWidth));
|
||||
return this._ctx.strokeText(
|
||||
text,
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(maxWidth)
|
||||
);
|
||||
} else {
|
||||
return this._ctx.strokeText(text, this._doSize(x), this._doSize(y));
|
||||
}
|
||||
}
|
||||
|
||||
setFont(opts: { fontSize: number, fontFamily?: string, fontWeight?: 'bold' }): void {
|
||||
setFont(opts: {
|
||||
fontSize: number;
|
||||
fontFamily?: string;
|
||||
fontWeight?: 'bold';
|
||||
}): void {
|
||||
const strList: string[] = [];
|
||||
if (opts.fontWeight === 'bold') {
|
||||
strList.push(`${opts.fontWeight}`);
|
||||
|
|
@ -231,7 +299,7 @@ class Context implements TypeContext {
|
|||
save() {
|
||||
this._ctx.save();
|
||||
}
|
||||
|
||||
|
||||
restore() {
|
||||
this._ctx.restore();
|
||||
}
|
||||
|
|
@ -257,10 +325,25 @@ class Context implements TypeContext {
|
|||
}
|
||||
|
||||
ellipse(
|
||||
x: number,y: number, radiusX: number, radiusY: number,
|
||||
rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean | undefined
|
||||
x: number,
|
||||
y: number,
|
||||
radiusX: number,
|
||||
radiusY: number,
|
||||
rotation: number,
|
||||
startAngle: number,
|
||||
endAngle: number,
|
||||
counterclockwise?: boolean | undefined
|
||||
) {
|
||||
this._ctx.ellipse(this._doSize(x), this._doSize(y), this._doSize(radiusX), this._doSize(radiusY), rotation, startAngle, endAngle, counterclockwise)
|
||||
this._ctx.ellipse(
|
||||
this._doSize(x),
|
||||
this._doSize(y),
|
||||
this._doSize(radiusX),
|
||||
this._doSize(radiusY),
|
||||
rotation,
|
||||
startAngle,
|
||||
endAngle,
|
||||
counterclockwise
|
||||
);
|
||||
}
|
||||
|
||||
private _doSize(num: number) {
|
||||
|
|
@ -278,8 +361,6 @@ class Context implements TypeContext {
|
|||
const _y = (y - scrollY) / scale;
|
||||
return this._doSize(_y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default Context;
|
||||
export default Context;
|
||||
|
|
|
|||
Loading…
Reference in a new issue