refactor: rename ts type name

This commit is contained in:
chenshenhai 2023-04-01 11:21:55 +08:00
parent 59f1280f3c
commit 7b2f00f047
63 changed files with 1326 additions and 1249 deletions

View file

@ -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;
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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) {

View file

@ -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;
}
}
}

View file

@ -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;
}
}

View file

@ -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();
});
}
}

View file

@ -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;

View file

@ -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) {

View file

@ -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;
};

View file

@ -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();

View file

@ -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,

View file

@ -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 };

View file

@ -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 };

View file

@ -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;
}

View file

@ -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 };

View file

@ -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);

View file

@ -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 {}
}

View file

@ -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: [
{

View file

@ -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();

View file

@ -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();
}
}
}

View file

@ -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();
}
}

View file

@ -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
};
}
}

View file

@ -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;
}
};

View file

@ -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];
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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, () => {

View file

@ -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();
// }
})
}
});
}

View file

@ -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, () => {

View file

@ -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);
// }

View file

@ -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(
}
}
}
}

View file

@ -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);
}

View file

@ -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);
// }

View file

@ -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%">

View file

@ -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;
}
}
}

View file

@ -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!");
}
}

View file

@ -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) &&

View file

@ -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;
}
}
}

View file

@ -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();
}
}
}

View file

@ -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 };

View file

@ -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
};

View file

@ -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 };

View file

@ -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 };

View file

@ -1,4 +1,4 @@
interface TypeContext {
interface IDrawContext {
getContext(): CanvasRenderingContext2D;
setTransform(config: {
scale?: number;
@ -67,5 +67,5 @@ interface TypeContext {
}
export {
TypeContext
IDrawContext
};

View file

@ -1,13 +1,10 @@
type TypeCoreOptions = {
type CoreOptions = {
width: number;
height: number;
devicePixelRatio: number;
contextWidth: number;
contextHeight: number;
onlyRender?: boolean;
}
};
export {
TypeCoreOptions
};
export { CoreOptions };

View file

@ -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 };

View file

@ -1,10 +1,8 @@
type TypeDeviceSize = {
type DeviceSize = {
x: number;
y: number;
w: number;
h: number;
}
};
export {
TypeDeviceSize,
};
export { DeviceSize };

View file

@ -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
};

View file

@ -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
};

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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 };

View file

@ -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;

View file

@ -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;