From 6d4d3151c6b877196885c3077b7b887e4eb3940d Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Sat, 13 Nov 2021 00:03:35 +0800 Subject: [PATCH] feat: prefect @idraw/renderer --- .../renderer/examples/features/lib/main.js | 9 + packages/renderer/src/constant/element.ts | 15 - packages/renderer/src/constant/static.ts | 12 - packages/renderer/src/index.ts | 23 +- packages/renderer/src/lib/config.ts | 27 -- packages/renderer/src/lib/core-event.ts | 94 ------ packages/renderer/src/lib/draw/base.ts | 8 +- packages/renderer/src/lib/draw/circle.ts | 2 - packages/renderer/src/lib/draw/text.ts | 7 +- .../renderer/src/lib/element/element-base.ts | 5 - .../src/lib/element/element-controller.ts | 6 - .../renderer/src/lib/element/element-hub.ts | 26 -- packages/renderer/src/lib/index.ts | 5 - packages/renderer/src/lib/loader-event.ts | 24 +- packages/renderer/src/lib/loader.ts | 11 + packages/renderer/src/lib/renderer-event.ts | 9 +- packages/renderer/src/mixins/element.ts | 182 ----------- packages/renderer/src/mixins/event.ts | 298 ------------------ packages/types/src/index.ts | 3 +- packages/types/src/lib/common.ts | 38 +++ packages/util/__tests__/index.test.ts | 3 + packages/util/src/index.ts | 4 + packages/{renderer => util}/src/lib/check.ts | 18 +- packages/{renderer => util}/src/lib/is.ts | 36 +-- 24 files changed, 113 insertions(+), 752 deletions(-) delete mode 100644 packages/renderer/src/constant/element.ts delete mode 100644 packages/renderer/src/constant/static.ts delete mode 100644 packages/renderer/src/lib/config.ts delete mode 100644 packages/renderer/src/lib/core-event.ts delete mode 100644 packages/renderer/src/lib/element/element-base.ts delete mode 100644 packages/renderer/src/lib/element/element-controller.ts delete mode 100644 packages/renderer/src/lib/element/element-hub.ts delete mode 100644 packages/renderer/src/mixins/element.ts delete mode 100644 packages/renderer/src/mixins/event.ts create mode 100644 packages/types/src/lib/common.ts rename packages/{renderer => util}/src/lib/check.ts (88%) rename packages/{renderer => util}/src/lib/is.ts (71%) diff --git a/packages/renderer/examples/features/lib/main.js b/packages/renderer/examples/features/lib/main.js index 20aeea5..986c5f2 100644 --- a/packages/renderer/examples/features/lib/main.js +++ b/packages/renderer/examples/features/lib/main.js @@ -15,6 +15,13 @@ const renderer = new Renderer({ // onlyRender: true, }); +renderer.on('load', (e) => { + console.log('load =', e) +}) +renderer.on('loadComplete', (e) => { + console.log('loadComplete =', e) +}) + renderer.on('drawFrame', (e) => { console.log('drawFrame =', e) }) @@ -25,6 +32,8 @@ renderer.on('drawFrameComplete', (e) => { renderer.render(canvas, data) renderer.render(canvas, { elements: data.elements.splice(1, 2) }, { forceUpdate: false }) +console.log(renderer.getContext()) + // setTimeout(() => { // renderer.render(canvas, { elements: data.elements.splice(1, 2) }, { forceUpdate: false }) // }, 2000); \ No newline at end of file diff --git a/packages/renderer/src/constant/element.ts b/packages/renderer/src/constant/element.ts deleted file mode 100644 index b2bbcdb..0000000 --- a/packages/renderer/src/constant/element.ts +++ /dev/null @@ -1,15 +0,0 @@ - -const elementTypes = { - 'text': {}, // TODO - 'rect': {}, // TODO - 'image': {}, // TODO - 'svg': {}, // TODO - 'circle': {}, // TODO - 'html': {}, // TODO -}; - -export const elementNames = Object.keys(elementTypes); - - -// limitQbliqueAngle -export const LIMIT_QBLIQUE_ANGLE = 15; \ No newline at end of file diff --git a/packages/renderer/src/constant/static.ts b/packages/renderer/src/constant/static.ts deleted file mode 100644 index 80815e8..0000000 --- a/packages/renderer/src/constant/static.ts +++ /dev/null @@ -1,12 +0,0 @@ -export enum Mode { - NULL = 'null', - SELECT_ELEMENT = 'select-element', - SELECT_ELEMENT_LIST = 'select-element-list', - SELECT_ELEMENT_WRAPPER_CONTROLLER = 'select-element-wrapper-controller', - SELECT_AREA = 'select-area', -} - -export enum CursorStatus { - DRAGGING = 'dragging', - NULL = 'null', -} diff --git a/packages/renderer/src/index.ts b/packages/renderer/src/index.ts index 6edf1f8..dec9d98 100644 --- a/packages/renderer/src/index.ts +++ b/packages/renderer/src/index.ts @@ -1,6 +1,7 @@ import { TypeData, TypeContext, TypeElement, TypeElemDesc } from '@idraw/types'; import util from '@idraw/util'; import { drawContext } from './lib/draw'; +import { TypeLoadDataItem } from './lib/loader-event'; import Loader from './lib/loader'; import { RendererEvent } from './lib/renderer-event'; import { @@ -8,10 +9,10 @@ import { _drawFrame, _retainQueueOneItem } from './names'; -const { Context } = util; const { requestAnimationFrame } = window; const { createUUID } = util.uuid; const { deepClone } = util.data; +const { Context } = util; type QueueItem = { data: TypeData }; enum DrawStatus { @@ -44,15 +45,15 @@ export default class Renderer extends RendererEvent { this[_loader] = new Loader({ maxParallelNum: 6 }); - this[_loader].on('load', (res) => { + this[_loader].on('load', (res: TypeLoadDataItem) => { this[_drawFrame](); - // console.log('Load: ', res); + this.trigger('load', { element: res.element }); }); - this[_loader].on('error', (res) => { - console.log('Loader Error: ', res); + this[_loader].on('error', (res: TypeLoadDataItem) => { + this.trigger('error', { element: res.element, error: res.error }); }); - this[_loader].on('complete', (res) => { - // console.log('complete: ', res); + this[_loader].on('complete', () => { + this.trigger('loadComplete', { t: Date.now() }) }); } @@ -104,6 +105,10 @@ export default class Renderer extends RendererEvent { this[_loader].load(data, changeResourceUUIDs || []); } + getContext(): TypeContext | null { + return this[_ctx] + } + private [_freeze]() { this[_status] = DrawStatus.FREEZE; } @@ -147,10 +152,10 @@ export default class Renderer extends RendererEvent { } else { this[_status] = DrawStatus.FREE; } - this.trigger('drawFrame', undefined) + this.trigger('drawFrame', { t: Date.now() }) if (this[_loader].isComplete() === true && this[_queue].length === 1 && this[_status] === DrawStatus.FREE) { - this.trigger('drawFrameComplete', undefined); + this.trigger('drawFrameComplete', { t: Date.now() }); this[_freeze](); } }); diff --git a/packages/renderer/src/lib/config.ts b/packages/renderer/src/lib/config.ts deleted file mode 100644 index 26fd21e..0000000 --- a/packages/renderer/src/lib/config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { TypeConfig, TypeConfigStrict } from '@idraw/types'; -import util from '@idraw/util'; - -const defaultConfig: TypeConfigStrict = { - elementWrapper: { - color: '#2ab6f1', - lockColor: '#aaaaaa', - controllerSize: 6, - lineWidth: 1, - lineDash: [4, 3], - } -}; - -function mergeConfig(config?: TypeConfig): TypeConfigStrict { - const result = util.data.deepClone(defaultConfig); - if (config) { - if (config.elementWrapper) { - result.elementWrapper = {...result.elementWrapper, ...config.elementWrapper}; - } - } - return result; -} - -export { - mergeConfig, -}; - diff --git a/packages/renderer/src/lib/core-event.ts b/packages/renderer/src/lib/core-event.ts deleted file mode 100644 index 50031d0..0000000 --- a/packages/renderer/src/lib/core-event.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { - TypeElement, - TypeElemDesc, - TypePoint, - TypeData, - TypeScreenData, -} from '@idraw/types'; - -export type TypeCoreEventSelectBaseArg = { - index: number | null; - uuid: string | null; -} - -export type TypeCoreEventArgMap = { - 'error': any; - 'mouseOverScreen': TypePoint, - 'mouseLeaveScreen': void, - 'mouseOverElement': TypeCoreEventSelectBaseArg & { element: TypeElement } - 'mouseLeaveElement': TypeCoreEventSelectBaseArg & { element: TypeElement } - 'screenClickElement': TypeCoreEventSelectBaseArg & { element: TypeElement } - 'screenDoubleClickElement': TypeCoreEventSelectBaseArg & { element: TypeElement } - 'screenSelectElement': TypeCoreEventSelectBaseArg & { element: TypeElement } - '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(key: T, callback: (p: TypeCoreEventArgMap[T]) => void): void - off(key: T, callback: (p: TypeCoreEventArgMap[T]) => void): void - trigger(key: T, p: TypeCoreEventArgMap[T]): void -} - - -export class CoreEvent implements TypeCoreEvent { - - private _listeners: Map void)[]>; - - constructor() { - this._listeners = new Map(); - } - - on(eventKey: T, callback: (p: TypeCoreEventArgMap[T]) => void) { - if (this._listeners.has(eventKey)) { - const callbacks = this._listeners.get(eventKey); - callbacks?.push(callback); - this._listeners.set(eventKey, callbacks || []); - } else { - this._listeners.set(eventKey, [callback]); - } - } - - off(eventKey: T, callback: (p: TypeCoreEventArgMap[T]) => void) { - if (this._listeners.has(eventKey)) { - const callbacks = this._listeners.get(eventKey); - if (Array.isArray(callbacks)) { - for (let i = 0; i < callbacks?.length; i++) { - if (callbacks[i] === callback) { - callbacks.splice(i, 1); - break; - } - } - } - this._listeners.set(eventKey, callbacks || []); - } - } - - trigger(eventKey: T, arg: TypeCoreEventArgMap[T]) { - const callbacks = this._listeners.get(eventKey); - if (Array.isArray(callbacks)) { - callbacks.forEach((cb) => { - cb(arg); - }); - return true; - } else { - return false; - } - } - - has (name: string) { - if (this._listeners.has(name)) { - const list: ((p: TypeCoreEventArgMap[T]) => void)[] | undefined = this._listeners.get(name); - if (Array.isArray(list) && list.length > 0) { - return true; - } - } - return false; - } - -} \ No newline at end of file diff --git a/packages/renderer/src/lib/draw/base.ts b/packages/renderer/src/lib/draw/base.ts index a537777..ee66aab 100644 --- a/packages/renderer/src/lib/draw/base.ts +++ b/packages/renderer/src/lib/draw/base.ts @@ -3,11 +3,9 @@ import { // TypeElemDesc, TypeElement, } from '@idraw/types'; -import util from '@idraw/util'; +import util from '@idraw/util'; import { rotateElement } from './../transform'; -import is from './../is'; - -const { istype, color } = util; +const { is, istype, color } = util; export function clearContext(ctx: TypeContext) { // ctx.setFillStyle('rgb(0 0 0 / 100%)'); @@ -85,7 +83,7 @@ export function drawBoxBorder( r = r + bw / 2; } const { desc } = elem; - if (desc.shadowColor !== undefined && util.color.isColorStr(desc.shadowColor)) { + if (desc.shadowColor !== undefined && color.isColorStr(desc.shadowColor)) { ctx.setShadowColor(desc.shadowColor); } if (desc.shadowOffsetX !== undefined && is.number(desc.shadowOffsetX)) { diff --git a/packages/renderer/src/lib/draw/circle.ts b/packages/renderer/src/lib/draw/circle.ts index 729212b..1de1896 100644 --- a/packages/renderer/src/lib/draw/circle.ts +++ b/packages/renderer/src/lib/draw/circle.ts @@ -1,7 +1,5 @@ import { TypeContext, TypeElement, } from '@idraw/types'; -// import util from '@idraw/util' import { rotateElement } from './../transform'; -// import is from './../is'; import { clearContext } from './base'; export function drawCircle(ctx: TypeContext, elem: TypeElement<'circle'>) { diff --git a/packages/renderer/src/lib/draw/text.ts b/packages/renderer/src/lib/draw/text.ts index 780a81b..dbbb0ce 100644 --- a/packages/renderer/src/lib/draw/text.ts +++ b/packages/renderer/src/lib/draw/text.ts @@ -7,7 +7,8 @@ import util from '@idraw/util'; import Loader from '../loader'; import { clearContext, drawBox } from './base'; import { rotateElement } from './../transform'; -import is from './../is'; + +const { is, color } = util; export function drawText( ctx: TypeContext, @@ -73,7 +74,7 @@ export function drawText( if (lines.length * fontHeight < elem.h) { _y += ((elem.h - lines.length * fontHeight) / 2); } - if (desc.textShadowColor !== undefined && util.color.isColorStr(desc.textShadowColor)) { + if (desc.textShadowColor !== undefined && color.isColorStr(desc.textShadowColor)) { ctx.setShadowColor(desc.textShadowColor); } if (desc.textShadowOffsetX !== undefined && is.number(desc.textShadowOffsetX)) { @@ -98,7 +99,7 @@ export function drawText( } // draw text stroke - if (util.color.isColorStr(desc.strokeColor) && desc.strokeWidth !== undefined && desc.strokeWidth > 0) { + if (color.isColorStr(desc.strokeColor) && desc.strokeWidth !== undefined && desc.strokeWidth > 0) { let _y = elem.y; if (lines.length * fontHeight < elem.h) { _y += ((elem.h - lines.length * fontHeight) / 2); diff --git a/packages/renderer/src/lib/element/element-base.ts b/packages/renderer/src/lib/element/element-base.ts deleted file mode 100644 index 296c6ce..0000000 --- a/packages/renderer/src/lib/element/element-base.ts +++ /dev/null @@ -1,5 +0,0 @@ -class ElementBase { - constructor() { - - } -} \ No newline at end of file diff --git a/packages/renderer/src/lib/element/element-controller.ts b/packages/renderer/src/lib/element/element-controller.ts deleted file mode 100644 index fca9be0..0000000 --- a/packages/renderer/src/lib/element/element-controller.ts +++ /dev/null @@ -1,6 +0,0 @@ - -class ElementController { - // TODO -} - -export default ElementController; \ No newline at end of file diff --git a/packages/renderer/src/lib/element/element-hub.ts b/packages/renderer/src/lib/element/element-hub.ts deleted file mode 100644 index 96237ff..0000000 --- a/packages/renderer/src/lib/element/element-hub.ts +++ /dev/null @@ -1,26 +0,0 @@ -import ElementController from './element-controller'; - -class ElementHub { - - private _controllerMap: Map = new Map(); - - constructor() { - // TODO - } - - register(type: string, controller: ElementController) { - if (this._controllerMap.has(type) !== true) { - this._controllerMap.set(type, controller) - } - } - - clear() { - this._controllerMap.clear(); - } - - getDrawActions() { - // TODO - } -} - -export default ElementHub; \ No newline at end of file diff --git a/packages/renderer/src/lib/index.ts b/packages/renderer/src/lib/index.ts index 08ecfb1..f044d38 100644 --- a/packages/renderer/src/lib/index.ts +++ b/packages/renderer/src/lib/index.ts @@ -1,12 +1,7 @@ export * from './draw/index'; -export * from './check'; -export * from './config'; -export * from './core-event'; export * from './diff'; -export * from './is'; export * from './loader-event'; export * from './loader'; export * from './parse'; export * from './temp'; -export * from './transform'; export * from './value'; diff --git a/packages/renderer/src/lib/loader-event.ts b/packages/renderer/src/lib/loader-event.ts index c472aa8..22f3de3 100644 --- a/packages/renderer/src/lib/loader-event.ts +++ b/packages/renderer/src/lib/loader-event.ts @@ -1,19 +1,23 @@ +import { TypeElement, TypeElemDesc } from '@idraw/types'; +export type TypeLoadDataItem = { + uuid: string, + type: 'image' | 'svg' | 'html', + status: 'null' | 'loaded' | 'fail', + content: null | HTMLImageElement | HTMLCanvasElement, + elemW: number; + elemH: number; + source: string, + element: TypeElement + error?: any, +} export type TypeLoadData = { - [uuid: string]: { - type: 'image' | 'svg' | 'html', - status: 'null' | 'loaded' | 'fail', - content: null | HTMLImageElement | HTMLCanvasElement, - elemW: number; - elemH: number; - source: string, - error?: any, - } + [uuid: string]: TypeLoadDataItem } export type TypeLoaderEventArgMap = { - 'complete': undefined; + 'complete': void; 'load': TypeLoadData[string]; 'error': TypeLoadData[string]; } diff --git a/packages/renderer/src/lib/loader.ts b/packages/renderer/src/lib/loader.ts index b0e3137..d100060 100644 --- a/packages/renderer/src/lib/loader.ts +++ b/packages/renderer/src/lib/loader.ts @@ -4,6 +4,7 @@ import { LoaderEvent, TypeLoadData, TypeLoaderEventArgMap } from './loader-event import { filterScript } from './../util/filter'; const { loadImage, loadSVG, loadHTML } = util.loader; +const { deepClone } = util.data; type Options = { maxParallelNum: number @@ -175,12 +176,14 @@ export default class Loader { elemH = _elem.desc.height || elem.h; } return { + uuid: elem.uuid, type: type, status: 'null', content: null, source, elemW, elemH, + element: deepClone(elem), }; } @@ -234,12 +237,14 @@ export default class Loader { 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) { @@ -247,12 +252,14 @@ export default class Loader { 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); @@ -262,6 +269,7 @@ export default class Loader { if (this._currentLoadData[uuid]) { this._storageLoadData[uuid] = { + uuid, type: this._currentLoadData[uuid]?.type, status: 'fail', content: null, @@ -269,6 +277,7 @@ export default class Loader { source: this._currentLoadData[uuid]?.source, elemW: this._currentLoadData[uuid]?.elemW, elemH: this._currentLoadData[uuid]?.elemH, + element: this._currentLoadData[uuid]?.element, }; } @@ -279,12 +288,14 @@ export default class Loader { 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, }); } diff --git a/packages/renderer/src/lib/renderer-event.ts b/packages/renderer/src/lib/renderer-event.ts index b858265..b00326d 100644 --- a/packages/renderer/src/lib/renderer-event.ts +++ b/packages/renderer/src/lib/renderer-event.ts @@ -1,7 +1,12 @@ +import { TypeElement, TypeElemDesc } from '@idraw/types'; + export type TypeRendererEventArgMap = { - 'drawFrame': void; - 'drawFrameComplete': void; + 'drawFrame': { t: number }; + 'drawFrameComplete': { t: number }; + 'load': { element: TypeElement }, + 'loadComplete': { t: number }, + 'error': { element: TypeElement, error: any } } export interface TypeRendererEvent { diff --git a/packages/renderer/src/mixins/element.ts b/packages/renderer/src/mixins/element.ts deleted file mode 100644 index 731ee53..0000000 --- a/packages/renderer/src/mixins/element.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { - TypeElement, TypeElemDesc, TypeElementBase, -} from '@idraw/types'; -import util from '@idraw/util'; -import { - _board, _data, _opts, _config, _renderer, _element, _helper, - _tempData, _draw, _coreEvent, _emitChangeScreen, _emitChangeData, -} from './../names'; -import { diffElementResourceChange } from './../lib/diff'; -import Core from './../index'; -import { Mode } from './../constant/static'; - -// const { time } = util; -const { deepClone } = util.data; -const { createUUID } = util.uuid; - -export function getSelectedElements(core: Core): TypeElement[] { - const elems: TypeElement[] = []; - let list: string[] = []; - const uuid = core[_tempData].get('selectedUUID'); - if (typeof uuid === 'string' && uuid) { - list.push(uuid); - } else { - list = core[_tempData].get('selectedUUIDList'); - } - list.forEach((uuid) => { - const index = core[_helper].getElementIndexByUUID(uuid); - if (index !== null && index >= 0) { - const elem = core[_data]?.elements[index]; - if (elem) elems.push(elem); - } - }); - return deepClone(elems); -} - -export function getElement(core: Core, uuid: string): TypeElement|null { - let elem: TypeElement|null = null; - const index = core[_helper].getElementIndexByUUID(uuid); - if (index !== null && core[_data].elements[index]) { - elem = deepClone(core[_data].elements[index]); - } - return elem; -} - -export function getElementByIndex(core: Core, index: number): TypeElement|null { - let elem: TypeElement|null = null; - if (index >=0 && core[_data].elements[index]) { - elem = deepClone(core[_data].elements[index]); - } - return elem; -} - -export function updateElement(core: Core, elem: TypeElement) { - const _elem = deepClone(elem) as TypeElement; - const data = core[_data]; - const resourceChangeUUIDs: string[] = []; - for (let i = 0; i < data.elements.length; i++) { - if (_elem.uuid === data.elements[i]?.uuid) { - const result = diffElementResourceChange(data.elements[i], _elem); - if (typeof result === 'string') { - resourceChangeUUIDs.push(result); - } - data.elements[i] = _elem; - break; - } - } - core[_emitChangeData](); - core[_draw]({ resourceChangeUUIDs }); -} - -export function selectElementByIndex(core: Core, index: number, opts?: { useMode?: boolean }): void { - if (core[_tempData].get('onlyRender') === true) return; - if (core[_data].elements[index]) { - const uuid = core[_data].elements[index].uuid; - if (opts?.useMode === true) { - core[_tempData].set('mode', Mode.SELECT_ELEMENT); - } else { - core[_tempData].set('mode', Mode.NULL); - } - if (typeof uuid === 'string') { - core[_tempData].set('selectedUUID', uuid); - core[_tempData].set('selectedUUIDList', []); - } - core[_draw](); - } -} - - -export function selectElement(core: Core, uuid: string, opts?: { useMode?: boolean }): void { - if (core[_tempData].get('onlyRender') === true) return; - const index = core[_helper].getElementIndexByUUID(uuid); - if (typeof index === 'number' && index >= 0) { - core.selectElementByIndex(index, opts); - } -} - -export function moveUpElement(core: Core, uuid: string): void { - // if (this[_onlyRender] === true) return; - const index = core[_helper].getElementIndexByUUID(uuid); - if (typeof index === 'number' && index >= 0 && index < core[_data].elements.length - 1) { - const temp = core[_data].elements[index]; - core[_data].elements[index] = core[_data].elements[index + 1]; - core[_data].elements[index + 1] = temp; - } - core[_emitChangeData](); - core[_draw](); -} - -export function moveDownElement(core: Core, uuid: string): void { - // if (this[_onlyRender] === true) return; - const index = core[_helper].getElementIndexByUUID(uuid); - if (typeof index === 'number' && index > 0 && index < core[_data].elements.length) { - const temp = core[_data].elements[index]; - core[_data].elements[index] = core[_data].elements[index - 1]; - core[_data].elements[index - 1] = temp; - } - core[_emitChangeData](); - core[_draw](); -} - - -export function addElement(core: Core, elem: TypeElementBase): string | null { - // if (this[_onlyRender] === true) return null; - const _elem = deepClone(elem); - _elem.uuid = createUUID(); - core[_data].elements.push(_elem); - core[_emitChangeData](); - core[_draw](); - return _elem.uuid; -} - -export function deleteElement(core: Core, uuid: string) { - // if (this[_onlyRender] === true) return; - const index = core[_element].getElementIndex(core[_data], uuid); - if (index >= 0) { - core[_data].elements.splice(index, 1); - core[_emitChangeData](); - core[_draw](); - } -} - -export function insertElementBefore(core: Core, elem: TypeElementBase, beforeUUID: string) { - const index = core[_helper].getElementIndexByUUID(beforeUUID); - if (index !== null) { - return core.insertElementBeforeIndex(elem, index); - } - return null; -} - - -export function insertElementBeforeIndex(core: Core, elem: TypeElementBase, index: number) { - const _elem = deepClone(elem); - _elem.uuid = createUUID(); - if (index >= 0) { - core[_data].elements.splice(index, 0, _elem); - core[_emitChangeData](); - core[_draw](); - return _elem.uuid; - } - return null; -} - - -export function insertElementAfter(core: Core, elem: TypeElementBase, beforeUUID: string) { - const index = core[_helper].getElementIndexByUUID(beforeUUID); - if (index !== null) { - return core.insertElementAfterIndex(elem, index); - } - return null; -} - -export function insertElementAfterIndex(core: Core, elem: TypeElementBase, index: number) { - const _elem = deepClone(elem); - _elem.uuid = createUUID(); - if (index >= 0) { - core[_data].elements.splice(index + 1, 0, _elem); - core[_emitChangeData](); - core[_draw](); - return _elem.uuid; - } - return null; -} \ No newline at end of file diff --git a/packages/renderer/src/mixins/event.ts b/packages/renderer/src/mixins/event.ts deleted file mode 100644 index 209a9e3..0000000 --- a/packages/renderer/src/mixins/event.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { TypePoint, TypeHelperWrapperControllerDirection } from '@idraw/types'; -import util from '@idraw/util'; -import Core from './../index'; -import { - _board, _data, _opts, _config, _renderer, _element, _helper, - _tempData, _draw, _coreEvent, _mapper, - _emitChangeScreen, _emitChangeData, -} from './../names'; -import { Mode, CursorStatus } from './../constant/static'; - -const { time } = util; -const { deepClone } = util.data; - -export function initEvent(core: Core): void { - - if (core[_tempData].get('hasInited') === true) { - return; - } - - core[_board].on('hover', time.throttle(handleHover(core), 32)); - core[_board].on('leave', time.throttle(handleLeave(core), 32)); - core[_board].on('point', time.throttle(handleClick(core), 16)); - core[_board].on('doubleClick', handleDoubleClick(core)); - if (core[_tempData].get('onlyRender') === true) { - return; - } - core[_board].on('point', handlePoint(core)); - core[_board].on('moveStart', handleMoveStart(core)); - core[_board].on('move', time.throttle(handleMove(core), 16)); - core[_board].on('moveEnd', handleMoveEnd(core)); - - core[_renderer].on('drawFrame', () => { - core[_coreEvent].trigger('drawFrame', undefined); - }); - core[_renderer].on('drawFrameComplete', () => { - core[_coreEvent].trigger('drawFrameComplete', undefined); - }) - - core[_tempData].set('hasInited', true); -} - - -function handleDoubleClick(core: Core) { - return function ( point: TypePoint) { - const [index, uuid] = core[_element].isPointInElement(point, core[_data]); - if (index >= 0 && uuid) { - const elem = deepClone(core[_data].elements?.[index]); - if (elem?.operation?.invisible !== true) { - core[_coreEvent].trigger( - 'screenDoubleClickElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} - ); - } - } - core[_draw](); - } -} - - -function handlePoint(core: Core) { - return function(point: TypePoint): void { - if (!core[_mapper].isEffectivePoint(point)) { - return; - } - if (core[_helper].isPointInElementList(point, core[_data])) { - // Coontroll Element-List - core[_tempData].set('mode', Mode.SELECT_ELEMENT_LIST); - } else { - const { - uuid, selectedControllerDirection - } = core[_helper].isPointInElementWrapperController(point, core[_data]); - if (uuid && selectedControllerDirection) { - // Controll Element-Wrapper - core[_tempData].set('mode', Mode.SELECT_ELEMENT_WRAPPER_CONTROLLER); - core[_tempData].set('selectedControllerDirection', selectedControllerDirection); - core[_tempData].set('selectedUUID', uuid); - } else { - const [index, uuid] = core[_element].isPointInElement(point, core[_data]); - if (index >= 0 && core[_data].elements[index]?.operation?.invisible !== true) { - // Controll Element - core.selectElementByIndex(index, { useMode: true }); - if (typeof uuid === 'string' && core[_coreEvent].has('screenSelectElement')) { - core[_coreEvent].trigger( - 'screenSelectElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} - ); - core[_emitChangeScreen](); - } - core[_tempData].set('mode', Mode.SELECT_ELEMENT); - } else { - // Controll Area - core[_tempData].set('selectedUUIDList', []); - core[_tempData].set('selectedUUID', null); - core[_tempData].set('mode', Mode.SELECT_AREA); - } - } - } - - core[_draw](); - } -} - - -function handleClick(core: Core) { - return function(point: TypePoint): void { - const [index, uuid] = core[_element].isPointInElement(point, core[_data]); - if (index >= 0 && uuid) { - core[_coreEvent].trigger( - 'screenClickElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} - ); - } - core[_draw](); - } -} - -function handleMoveStart(core: Core) { - return function(point: TypePoint): void { - core[_tempData].set('prevPoint', point); - const uuid = core[_tempData].get('selectedUUID'); - - if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT_LIST) { - // TODO - } else if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT) { - if (typeof uuid === 'string' && core[_coreEvent].has('screenMoveElementStart')) { - core[_coreEvent].trigger('screenMoveElementStart', { - index: core[_element].getElementIndex(core[_data], uuid), - uuid, - x: point.x, - y: point.y - }); - } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - core[_helper].startSelectArea(point); - } - } -} - - -function handleMove(core: Core) { - return function(point: TypePoint): void { - if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT_LIST) { - dragElements(core, core[_tempData].get('selectedUUIDList'), point, core[_tempData].get('prevPoint')); - core[_draw](); - core[_tempData].set('cursorStatus', CursorStatus.DRAGGING); - } else if (typeof core[_tempData].get('selectedUUID') === 'string') { - if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT) { - dragElements(core, [core[_tempData].get('selectedUUID') as string], point, core[_tempData].get('prevPoint')); - core[_draw](); - core[_tempData].set('cursorStatus', CursorStatus.DRAGGING); - } else if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT_WRAPPER_CONTROLLER && core[_tempData].get('selectedControllerDirection')) { - transfromElement( - core, - core[_tempData].get('selectedUUID') as string, - point, - core[_tempData].get('prevPoint'), - core[_tempData].get('selectedControllerDirection') as TypeHelperWrapperControllerDirection - ); - core[_tempData].set('cursorStatus', CursorStatus.DRAGGING) - } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - core[_helper].changeSelectArea(point); - core[_draw](); - } - core[_tempData].set('prevPoint', point) - } -} - -function dragElements(core: Core, uuids: string[], point: TypePoint, prevPoint: TypePoint|null): void { - if (!prevPoint) { - return; - } - uuids.forEach((uuid) => { - const idx = core[_helper].getElementIndexByUUID(uuid); - if (idx === null) return; - const elem = core[_data].elements[idx]; - if (elem?.operation?.lock !== true && elem?.operation?.invisible !== true) { - core[_element].dragElement(core[_data], uuid, point, prevPoint, core[_board].getContext().getTransform().scale); - } - }); - core[_draw](); -} - - -function handleMoveEnd(core: Core) { - return function (point: TypePoint): void { - const uuid = core[_tempData].get('selectedUUID'); - if (typeof uuid === 'string') { - const index = core[_element].getElementIndex(core[_data], uuid); - const elem = core[_data].elements[index]; - if (elem) { - if (core[_coreEvent].has('screenMoveElementEnd')) { - core[_coreEvent].trigger('screenMoveElementEnd', { - index, - uuid, - x: point.x, - y: point.y - }); - } - if (core[_coreEvent].has('screenChangeElement')) { - core[_coreEvent].trigger('screenChangeElement', { - index, - uuid, - width: elem.w, - height: elem.h, - angle: elem.angle || 0 - }); - } - core[_emitChangeData](); - } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - const uuids = core[_helper].calcSelectedElements(core[_data]); - if (uuids.length > 0) { - core[_tempData].set('selectedUUIDList', uuids); - core[_tempData].set('selectedUUID', null); - } else { - core[_tempData].set('mode', Mode.NULL); - } - core[_helper].clearSelectedArea(); - core[_draw](); - } - - if (core[_tempData].get('mode') !== Mode.SELECT_ELEMENT) { - core[_tempData].set('selectedUUID', null); - } - core[_tempData].set('cursorStatus', CursorStatus.NULL); - core[_tempData].set('mode', Mode.NULL); - } -} - -function handleHover(core: Core) { - return function (point: TypePoint): void { - let isMouseOverElement: boolean = false; - - if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - if (core[_tempData].get('onlyRender') !== true) core[_board].resetCursor(); - } else if (core[_tempData].get('cursorStatus') === CursorStatus.NULL) { - const { cursor, elementUUID } = core[_mapper].judgePointCursor(point, core[_data]); - if (core[_tempData].get('onlyRender') !== true) core[_board].setCursor(cursor); - if (elementUUID) { - const index: number | null = core[_helper].getElementIndexByUUID(elementUUID); - if (index !== null && index >= 0) { - const elem = core[_data].elements[index]; - if (elem?.operation?.lock === true || elem?.operation?.invisible === true) { - core[_board].resetCursor(); - return; - } - if (core[_tempData].get('hoverUUID') !== elem.uuid) { - const preIndex = core[_helper].getElementIndexByUUID(core[_tempData].get('hoverUUID') || ''); - if (preIndex !== null && core[_data].elements[preIndex]) { - core[_coreEvent].trigger('mouseLeaveElement', { - uuid: core[_tempData].get('hoverUUID'), - index: preIndex, - element: core[_data].elements[preIndex] - }); - } - } - if (elem) { - core[_coreEvent].trigger('mouseOverElement', { uuid: elem.uuid, index, element: elem, }); - core[_tempData].set('hoverUUID', elem.uuid); - isMouseOverElement = true; - } - } - } - } - if (isMouseOverElement !== true && core[_tempData].get('hoverUUID') !== null) { - const uuid = core[_tempData].get('hoverUUID'); - const index: number | null = core[_helper].getElementIndexByUUID(uuid || ''); - if (index !== null) core[_coreEvent].trigger('mouseLeaveElement', { uuid, index, element: core[_data].elements[index] }) - core[_tempData].set('hoverUUID', null); - } - if (core[_coreEvent].has('mouseOverScreen')) core[_coreEvent].trigger('mouseOverScreen', point); - } -} - -function handleLeave(core: Core) { - return function(): void { - if (core[_coreEvent].has('mouseLeaveScreen')) { - core[_coreEvent].trigger('mouseLeaveScreen', undefined); - } - } -} - -function transfromElement( - core: Core, - uuid: string, point: TypePoint, prevPoint: TypePoint|null, direction: TypeHelperWrapperControllerDirection -): null | { - width: number, - height: number, - angle: number, -} { - if (!prevPoint) { - return null; - } - const result = core[_element].transformElement(core[_data], uuid, point, prevPoint, core[_board].getContext().getTransform().scale, direction); - core[_draw](); - return result; -} \ No newline at end of file diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index b1182e2..48ba450 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -8,4 +8,5 @@ export * from './lib/config'; export * from './lib/core'; export * from './lib/screen'; export * from './lib/device'; -export * from './lib/plugin'; \ No newline at end of file +export * from './lib/plugin'; +export * from './lib/common'; \ No newline at end of file diff --git a/packages/types/src/lib/common.ts b/packages/types/src/lib/common.ts new file mode 100644 index 0000000..f70fe5a --- /dev/null +++ b/packages/types/src/lib/common.ts @@ -0,0 +1,38 @@ +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 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 { + TypeIs, + TypeCheck, +} \ No newline at end of file diff --git a/packages/util/__tests__/index.test.ts b/packages/util/__tests__/index.test.ts index cbe1c6d..f3b31d7 100644 --- a/packages/util/__tests__/index.test.ts +++ b/packages/util/__tests__/index.test.ts @@ -8,6 +8,9 @@ const types = { uuid: 'Object', istype: 'Object', data: 'Object', + is: 'Object', + check: 'Object', + Context: 'Function', } function getType (data: any): string { diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 268159d..77f0e04 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -6,8 +6,12 @@ import { deepClone } from './lib/data'; import istype from './lib/istype'; import { loadImage, loadSVG, loadHTML } from './lib/loader'; import Context from './lib/context'; +import is from './lib/is'; +import check from './lib/check'; export default { + is, + check, time: { delay, compose, diff --git a/packages/renderer/src/lib/check.ts b/packages/util/src/lib/check.ts similarity index 88% rename from packages/renderer/src/lib/check.ts rename to packages/util/src/lib/check.ts index 6dcd510..54f02dd 100644 --- a/packages/renderer/src/lib/check.ts +++ b/packages/util/src/lib/check.ts @@ -1,10 +1,9 @@ -import { TypeElementAttrs } from '@idraw/types'; +// import { TypeElementAttrs } from '@idraw/types'; import is from './is'; - function attrs( - attrs: TypeElementAttrs + 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))) { @@ -146,18 +145,5 @@ const check = { 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 -}; export default check; \ No newline at end of file diff --git a/packages/renderer/src/lib/is.ts b/packages/util/src/lib/is.ts similarity index 71% rename from packages/renderer/src/lib/is.ts rename to packages/util/src/lib/is.ts index 17d3ea0..1f4228a 100644 --- a/packages/renderer/src/lib/is.ts +++ b/packages/util/src/lib/is.ts @@ -1,8 +1,4 @@ -import util from "@idraw/util"; - -const { isColorStr } = util.color; - - +import { isColorStr } from './color'; function number(value: any) { return (typeof value === 'number' && (value > 0 || value <= 0)); @@ -97,7 +93,7 @@ function fontWeight(value: any) { return ['bold'].includes(value); } -const is: TypeIs = { +const is = { x, y, w, h, angle, number, borderWidth, borderRadius, color, imageSrc, imageURL, imageBase64, svg, html, @@ -105,33 +101,5 @@ const is: TypeIs = { strokeWidth, }; -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, -} export default is; - - -export { - TypeIs, -}; \ No newline at end of file