From e17195ee5e9ce9caaf8e7db0bf5ff475d3682416 Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Fri, 26 Nov 2021 20:48:31 +0800 Subject: [PATCH] refactor: split engine from mixin/event for @idraw/core --- .../core/examples/features/lib/data/rect.js | 4 +- packages/core/src/index.ts | 74 +-- packages/core/src/lib/engine-temp.ts | 49 ++ packages/core/src/lib/engine.ts | 443 ++++++++++-------- packages/core/src/lib/helper.ts | 4 +- packages/core/src/lib/mapper.ts | 1 - packages/core/src/lib/temp.ts | 21 - packages/core/src/mixins/element.ts | 34 +- packages/core/src/mixins/event.ts | 298 ------------ packages/core/src/names.ts | 4 +- 10 files changed, 339 insertions(+), 593 deletions(-) create mode 100644 packages/core/src/lib/engine-temp.ts delete mode 100644 packages/core/src/mixins/event.ts diff --git a/packages/core/examples/features/lib/data/rect.js b/packages/core/examples/features/lib/data/rect.js index de3a42f..2f839c4 100644 --- a/packages/core/examples/features/lib/data/rect.js +++ b/packages/core/examples/features/lib/data/rect.js @@ -62,8 +62,8 @@ const data = { borderColor: "#bd0b64", }, operation: { - disbaleScale: true, - disbaleRotate: true, + // disbaleScale: true, + // disbaleRotate: true, } }, ], diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7b403ab..6337ced 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -9,12 +9,12 @@ import Renderer from '@idraw/renderer'; import is, { TypeIs } from './lib/is'; import check, { TypeCheck } from './lib/check'; import { - Element, Helper, Mapper, mergeConfig, CoreEvent, + Element, mergeConfig, CoreEvent, TypeCoreEventArgMap, parseData, TempData, diffElementResourceChangeList, } from './lib'; import { - _board, _data, _opts, _config, _renderer, _element, _helper, _tempData, _draw, _coreEvent, - _mapper, _emitChangeScreen, _emitChangeData, _todo + _board, _data, _opts, _config, _renderer, _element, _tempData, _draw, _coreEvent, + _mapper, _emitChangeScreen, _emitChangeData, _engine, } from './names'; import { getSelectedElements, updateElement, selectElementByIndex, getElement, getElementByIndex, selectElement, moveUpElement, moveDownElement, addElement, deleteElement, @@ -33,10 +33,9 @@ class Core { private [_config]: TypeConfigStrict; private [_renderer]: Renderer; private [_element]: Element; - private [_helper]: Helper; - private [_mapper]: Mapper; private [_coreEvent]: CoreEvent = new CoreEvent(); private [_tempData]: TempData = new TempData(); + private [_engine]: Engine; static is: TypeIs = is; static check: TypeCheck = check; @@ -44,7 +43,6 @@ class Core { constructor(mount: HTMLDivElement, opts: TypeCoreOptions, config?: TypeConfig) { this[_data] = { elements: [] }; this[_opts] = opts; - this[_tempData].set('onlyRender', opts.onlyRender === true) this[_config] = mergeConfig(config || {}); this[_board] = new Board(mount, { ...this[_opts], @@ -57,7 +55,7 @@ class Core { this[_renderer] = new Renderer(); const drawFrame = () => { const helperCtx = this[_board].getHelperContext(); - const helperConfig = this[_helper].getConfig(); + const helperConfig = this[_engine].getHelperConfig(); this[_board].clear(); const { contextWidth, contextHeight, devicePixelRatio } = this[_opts]; helperCtx.clearRect(0, 0, contextWidth * devicePixelRatio, contextHeight * devicePixelRatio) @@ -73,15 +71,27 @@ class Core { drawFrame(); }) this[_element] = new Element(this[_board].getContext()); - this[_helper] = new Helper(this[_board], this[_config]); - this[_mapper] = new Mapper({ + this[_engine] = new Engine({ + coreEvent: this[_coreEvent], board: this[_board], - helper: this[_helper], - element: this[_element] + element: this[_element], + config: this[_config], + drawFeekback: this[_draw].bind(this), + getDataFeekback: () => this[_data], + selectElementByIndex: this.selectElementByIndex.bind(this), + emitChangeScreen: this[_emitChangeScreen].bind(this), + emitChangeData: this[_emitChangeData].bind(this), }); - // initEvent(this); - const engine = new Engine(this); - engine.init(); + this[_engine].init(); + + this[_renderer].on('drawFrame', () => { + this[_coreEvent].trigger('drawFrame', undefined); + }); + this[_renderer].on('drawFrameComplete', () => { + this[_coreEvent].trigger('drawFrameComplete', undefined); + }) + + this[_tempData].set('hasInited', true); } [_draw]( @@ -89,18 +99,12 @@ class Core { resourceChangeUUIDs?: string[], } ): void { - const transfrom = this[_board].getTransform(); - this[_helper].updateConfig(this[_data], { + this[_engine].updateHelperConfig({ width: this[_opts].width, height: this[_opts].height, - canScroll: this[_config]?.scrollWrapper?.use === true, - selectedUUID: this[_tempData].get('selectedUUID'), - selectedUUIDList: this[_tempData].get('selectedUUIDList'), devicePixelRatio: this[_opts].devicePixelRatio, - scale: transfrom.scale, - scrollX: transfrom.scrollX, - scrollY: transfrom.scrollY, }); + this[_renderer].thaw(); this[_renderer].render(this[_board].getContext(), this[_data], { changeResourceUUIDs: opts?.resourceChangeUUIDs || [] @@ -214,7 +218,6 @@ class Core { clearOperation() { this[_tempData].clear(); - this[_tempData].set('onlyRender', this[_opts].onlyRender === true) this[_draw](); } @@ -234,22 +237,6 @@ class Core { return this[_board].pointContextToScreen(p); } - setOnlyRender() { - this[_tempData].set('onlyRender', true); - } - - cancelOnlyRender() { - this[_tempData].set('onlyRender', false); - } - - // stopRender() { - // this[_renderer].stop(); - // } - - // restartRender() { - // this[_renderer].restart(); - // } - __getBoardContext(): TypeContext { return this[_board].getContext(); } @@ -267,9 +254,6 @@ class Core { if (this[_coreEvent].has('changeScreen')) { this[_coreEvent].trigger('changeScreen', { ...this.getScreenTransform(), - // ...{ - // selectedElementUUID: this[_tempData].get('selectedUUID') - // } }); } } @@ -279,12 +263,6 @@ class Core { this[_coreEvent].trigger('changeData', deepClone(this[_data])); } } - - [_todo]() { - // TODO - // To avoid TS error - console.log(this[_mapper]); - } } export default Core; \ No newline at end of file diff --git a/packages/core/src/lib/engine-temp.ts b/packages/core/src/lib/engine-temp.ts new file mode 100644 index 0000000..4144451 --- /dev/null +++ b/packages/core/src/lib/engine-temp.ts @@ -0,0 +1,49 @@ +import { TypeHelperWrapperControllerDirection, TypePoint } from '@idraw/types'; +import { Mode, CursorStatus } from '../constant/static'; + +type TempDataDesc = { + hasInited: boolean; + mode: Mode, + cursorStatus: CursorStatus + selectedUUID: string | null, + selectedUUIDList: string[], + hoverUUID: string | null, + selectedControllerDirection: TypeHelperWrapperControllerDirection | null, + hoverControllerDirection: TypeHelperWrapperControllerDirection | null, + prevPoint: TypePoint | null, +} + +function createData(): TempDataDesc { + return { + hasInited: false, + mode: Mode.NULL, + cursorStatus: CursorStatus.NULL, + selectedUUID: null, + selectedUUIDList: [], + hoverUUID: null, + selectedControllerDirection: null, + hoverControllerDirection: null, + prevPoint: null, + } +} + +export class TempData { + + private _temp: TempDataDesc + + constructor() { + this._temp = createData(); + } + + set(name: T, value: TempDataDesc[T]) { + this._temp[name] = value; + } + + get(name: T): TempDataDesc[T] { + return this._temp[name]; + } + + clear() { + this._temp = createData(); + } +} \ No newline at end of file diff --git a/packages/core/src/lib/engine.ts b/packages/core/src/lib/engine.ts index 20d5df2..c35952d 100644 --- a/packages/core/src/lib/engine.ts +++ b/packages/core/src/lib/engine.ts @@ -1,229 +1,283 @@ import { - TypePoint, TypeHelperWrapperControllerDirection,InterfaceHelperPlugin + TypePoint, TypeHelperWrapperControllerDirection,InterfaceHelperPlugin, + TypeConfigStrict, TypeData, TypeHelperConfig, } from '@idraw/types'; import util from '@idraw/util'; -import { - _board, _data, _opts, _config, _renderer, _element, _helper, - _tempData, _draw, _coreEvent, _mapper, - _emitChangeScreen, _emitChangeData, -} from './../names'; +import Board from '@idraw/board'; import { Mode, CursorStatus } from './../constant/static'; -import Core from './../index'; +import { TempData } from './engine-temp'; +import { Helper } from './helper'; +import { Mapper } from './mapper'; +import { Element } from './element'; +import { CoreEvent } from './core-event'; const { time } = util; const { deepClone } = util.data; -// type Options = { -// ctx: TypeContext, -// helperCtx: TypeContext, -// } - +type Options = { + coreEvent: CoreEvent, + board: Board, + element: Element, + config: TypeConfigStrict, + drawFeekback: () => void, + getDataFeekback: () => TypeData; + selectElementByIndex: (index: number, opts?: { useMode?: boolean }) => void, + emitChangeScreen: () => void, + emitChangeData: () => void, +} export class Engine { private _plugins: InterfaceHelperPlugin[] = []; - private _core: Core; + private _opts: Options; + private _mapper: Mapper; - constructor(core: Core) { - this._core = core; + public temp: TempData; + public helper: Helper; + + constructor(opts: Options) { + const { board, config, element } = opts; + const helper = new Helper(board, config); + this._opts = opts; + this.temp = new TempData(); + this.helper = helper; + this._mapper = new Mapper({ board, helper, element }); } addPlugin(plugin: InterfaceHelperPlugin) { this._plugins.push(plugin); } + getHelperConfig(): TypeHelperConfig { + return this.helper.getConfig(); + } + + updateHelperConfig(opts: { + width: number, height: number, devicePixelRatio: number + }) { + const { board, getDataFeekback, config } = this._opts; + const data = getDataFeekback(); + const transform = board.getTransform(); + this.helper.updateConfig(data,{ + width: opts.width, + height: opts.height, + devicePixelRatio: opts.devicePixelRatio, + canScroll: config?.scrollWrapper?.use === true, + selectedUUID: this.temp.get('selectedUUID'), + selectedUUIDList: this.temp.get('selectedUUIDList'), + scale: transform.scale, + scrollX: transform.scrollX, + scrollY: transform.scrollY, + }) + } + init() { - initEvent(this._core); + this._initEvent(); } -} -function initEvent(core: Core): void { - - if (core[_tempData].get('hasInited') === true) { - return; + private _initEvent(): void { + if (this.temp.get('hasInited') === true) { + return; + } + const { board } = this._opts; + + board.on('hover', time.throttle(this._handleHover.bind(this), 32)); + board.on('leave', time.throttle(this._handleLeave.bind(this), 32)); + board.on('point', time.throttle(this._handleClick.bind(this), 16)); + board.on('doubleClick', this._handleDoubleClick.bind(this)); + board.on('point', this._handlePoint.bind(this)); + board.on('moveStart', this._handleMoveStart.bind(this)); + board.on('move', time.throttle(this._handleMove.bind(this), 16)); + board.on('moveEnd', this._handleMoveEnd.bind(this)); } - - 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]); + private _handleDoubleClick (point: TypePoint) { + const { element, getDataFeekback, drawFeekback, coreEvent } = this._opts; + const data = getDataFeekback(); + const [index, uuid] = element.isPointInElement(point, data); if (index >= 0 && uuid) { - const elem = deepClone(core[_data].elements?.[index]); + const elem = deepClone(data.elements?.[index]); if (elem?.operation?.invisible !== true) { - core[_coreEvent].trigger( + coreEvent.trigger( 'screenDoubleClickElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} + { index, uuid, element: deepClone(data.elements?.[index])} ); } } - core[_draw](); + drawFeekback(); } -} - -function handlePoint(core: Core) { - return function(point: TypePoint): void { - if (!core[_mapper].isEffectivePoint(point)) { + _handlePoint(point: TypePoint): void { + if (!this._mapper.isEffectivePoint(point)) { return; } - if (core[_helper].isPointInElementList(point, core[_data])) { + const { + element, getDataFeekback, selectElementByIndex, coreEvent, + emitChangeScreen, drawFeekback + } = this._opts; + const helper = this.helper; + const data = getDataFeekback(); + if (helper.isPointInElementList(point, data)) { // Coontroll Element-List - core[_tempData].set('mode', Mode.SELECT_ELEMENT_LIST); + this.temp.set('mode', Mode.SELECT_ELEMENT_LIST); } else { const { uuid, selectedControllerDirection - } = core[_helper].isPointInElementWrapperController(point, core[_data]); + } = helper.isPointInElementWrapperController(point, 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); + this.temp.set('mode', Mode.SELECT_ELEMENT_WRAPPER_CONTROLLER); + this.temp.set('selectedControllerDirection', selectedControllerDirection); + this.temp.set('selectedUUID', uuid); } else { - const [index, uuid] = core[_element].isPointInElement(point, core[_data]); - if (index >= 0 && core[_data].elements[index]?.operation?.invisible !== true) { + const [index, uuid] = element.isPointInElement(point, data); + if (index >= 0 && data.elements[index]?.operation?.invisible !== true) { // Controll Element - core.selectElementByIndex(index, { useMode: true }); - if (typeof uuid === 'string' && core[_coreEvent].has('screenSelectElement')) { - core[_coreEvent].trigger( + selectElementByIndex(index, { useMode: true }); + if (typeof uuid === 'string' && coreEvent.has('screenSelectElement')) { + coreEvent.trigger( 'screenSelectElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} + { index, uuid, element: deepClone(data.elements?.[index])} ); - core[_emitChangeScreen](); + emitChangeScreen(); } - core[_tempData].set('mode', Mode.SELECT_ELEMENT); + this.temp.set('mode', Mode.SELECT_ELEMENT); } else { // Controll Area - core[_tempData].set('selectedUUIDList', []); - core[_tempData].set('selectedUUID', null); - core[_tempData].set('mode', Mode.SELECT_AREA); + this.temp.set('selectedUUIDList', []); + this.temp.set('selectedUUID', null); + this.temp.set('mode', Mode.SELECT_AREA); } } } - - core[_draw](); + drawFeekback(); } -} - -function handleClick(core: Core) { - return function(point: TypePoint): void { - const [index, uuid] = core[_element].isPointInElement(point, core[_data]); + private _handleClick(point: TypePoint): void { + const { + element, getDataFeekback, coreEvent, drawFeekback + } = this._opts; + const data = getDataFeekback(); + const [index, uuid] = element.isPointInElement(point, data); if (index >= 0 && uuid) { - core[_coreEvent].trigger( + coreEvent.trigger( 'screenClickElement', - { index, uuid, element: deepClone(core[_data].elements?.[index])} + { index, uuid, element: deepClone(data.elements?.[index])} ); } - core[_draw](); + drawFeekback(); } -} -function handleMoveStart(core: Core) { - return function(point: TypePoint): void { - core[_tempData].set('prevPoint', point); - const uuid = core[_tempData].get('selectedUUID'); + private _handleMoveStart(point: TypePoint): void { + const { + element, getDataFeekback, coreEvent + } = this._opts; + const data = getDataFeekback(); + const helper = this.helper; + + this.temp.set('prevPoint', point); + const uuid = this.temp.get('selectedUUID'); - if (core[_tempData].get('mode') === Mode.SELECT_ELEMENT_LIST) { + if (this.temp.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), + } else if (this.temp.get('mode') === Mode.SELECT_ELEMENT) { + if (typeof uuid === 'string' && coreEvent.has('screenMoveElementStart')) { + coreEvent.trigger('screenMoveElementStart', { + index: element.getElementIndex(data, uuid), uuid, x: point.x, y: point.y }); } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - core[_helper].startSelectArea(point); + } else if (this.temp.get('mode') === Mode.SELECT_AREA) { + 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, + private _handleMove(point: TypePoint): void { + const { drawFeekback } = this._opts; + const helper = this.helper; + if (this.temp.get('mode') === Mode.SELECT_ELEMENT_LIST) { + this._dragElements(this.temp.get('selectedUUIDList'), point, this.temp.get('prevPoint')); + drawFeekback(); + this.temp.set('cursorStatus', CursorStatus.DRAGGING); + } else if (typeof this.temp.get('selectedUUID') === 'string') { + if (this.temp.get('mode') === Mode.SELECT_ELEMENT) { + this._dragElements([this.temp.get('selectedUUID') as string], point, this.temp.get('prevPoint')); + drawFeekback(); + this.temp.set('cursorStatus', CursorStatus.DRAGGING); + } else if (this.temp.get('mode') === Mode.SELECT_ELEMENT_WRAPPER_CONTROLLER && this.temp.get('selectedControllerDirection')) { + this._transfromElement( + this.temp.get('selectedUUID') as string, point, - core[_tempData].get('prevPoint'), - core[_tempData].get('selectedControllerDirection') as TypeHelperWrapperControllerDirection + this.temp.get('prevPoint'), + this.temp.get('selectedControllerDirection') as TypeHelperWrapperControllerDirection ); - core[_tempData].set('cursorStatus', CursorStatus.DRAGGING) + this.temp.set('cursorStatus', CursorStatus.DRAGGING) } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - core[_helper].changeSelectArea(point); - core[_draw](); + } else if (this.temp.get('mode') === Mode.SELECT_AREA) { + helper.changeSelectArea(point); + drawFeekback(); } - core[_tempData].set('prevPoint', point) + this.temp.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); + private _dragElements(uuids: string[], point: TypePoint, prevPoint: TypePoint|null): void { + if (!prevPoint) { + return; } - }); - core[_draw](); -} + const { + board, element, getDataFeekback, drawFeekback + } = this._opts; + const data = getDataFeekback(); + const helper = this.helper; + uuids.forEach((uuid) => { + const idx = helper.getElementIndexByUUID(uuid); + if (idx === null) return; + const elem = data.elements[idx]; + if (elem?.operation?.lock !== true && elem?.operation?.invisible !== true) { + element.dragElement(data, uuid, point, prevPoint, board.getContext().getTransform().scale); + } + }); + drawFeekback(); + } + private _transfromElement( + uuid: string, point: TypePoint, prevPoint: TypePoint|null, direction: TypeHelperWrapperControllerDirection + ): null | { width: number, height: number, angle: number, } { + if (!prevPoint) { + return null; + } + const { + board, element, getDataFeekback, drawFeekback + } = this._opts; + const data = getDataFeekback(); + const result = element.transformElement(data, uuid, point, prevPoint, board.getContext().getTransform().scale, direction); + drawFeekback(); + return result; + } -function handleMoveEnd(core: Core) { - return function (point: TypePoint): void { - const uuid = core[_tempData].get('selectedUUID'); + private _handleMoveEnd(point: TypePoint): void { + const { + element, getDataFeekback, coreEvent, drawFeekback, emitChangeData + } = this._opts; + const data = getDataFeekback(); + const helper = this.helper; + + const uuid = this.temp.get('selectedUUID'); if (typeof uuid === 'string') { - const index = core[_element].getElementIndex(core[_data], uuid); - const elem = core[_data].elements[index]; + const index = element.getElementIndex(data, uuid); + const elem = data.elements[index]; if (elem) { - if (core[_coreEvent].has('screenMoveElementEnd')) { - core[_coreEvent].trigger('screenMoveElementEnd', { + if (coreEvent.has('screenMoveElementEnd')) { + coreEvent.trigger('screenMoveElementEnd', { index, uuid, x: point.x, y: point.y }); } - if (core[_coreEvent].has('screenChangeElement')) { - core[_coreEvent].trigger('screenChangeElement', { + if (coreEvent.has('screenChangeElement')) { + coreEvent.trigger('screenChangeElement', { index, uuid, width: elem.w, @@ -231,93 +285,82 @@ function handleMoveEnd(core: Core) { angle: elem.angle || 0 }); } - core[_emitChangeData](); + emitChangeData(); } - } else if (core[_tempData].get('mode') === Mode.SELECT_AREA) { - const uuids = core[_helper].calcSelectedElements(core[_data]); + } else if (this.temp.get('mode') === Mode.SELECT_AREA) { + const uuids = helper.calcSelectedElements(data); if (uuids.length > 0) { - core[_tempData].set('selectedUUIDList', uuids); - core[_tempData].set('selectedUUID', null); + this.temp.set('selectedUUIDList', uuids); + this.temp.set('selectedUUID', null); } else { - core[_tempData].set('mode', Mode.NULL); + this.temp.set('mode', Mode.NULL); } - core[_helper].clearSelectedArea(); - core[_draw](); + helper.clearSelectedArea(); + drawFeekback(); } - if (core[_tempData].get('mode') !== Mode.SELECT_ELEMENT) { - core[_tempData].set('selectedUUID', null); + if (this.temp.get('mode') !== Mode.SELECT_ELEMENT) { + this.temp.set('selectedUUID', null); } - core[_tempData].set('cursorStatus', CursorStatus.NULL); - core[_tempData].set('mode', Mode.NULL); + this.temp.set('cursorStatus', CursorStatus.NULL); + this.temp.set('mode', Mode.NULL); } -} -function handleHover(core: Core) { - return function (point: TypePoint): void { + private _handleHover(point: TypePoint): void { let isMouseOverElement: boolean = false; + const { board, getDataFeekback, coreEvent, } = this._opts; + const data = getDataFeekback(); + const helper = this.helper; + const mapper = this._mapper; - 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 (this.temp.get('mode') === Mode.SELECT_AREA) { + board.resetCursor(); + } else if (this.temp.get('cursorStatus') === CursorStatus.NULL) { + const { cursor, elementUUID } = mapper.judgePointCursor(point, data); + board.setCursor(cursor); if (elementUUID) { - const index: number | null = core[_helper].getElementIndexByUUID(elementUUID); + const index: number | null = helper.getElementIndexByUUID(elementUUID); if (index !== null && index >= 0) { - const elem = core[_data].elements[index]; + const elem = data.elements[index]; if (elem?.operation?.lock === true || elem?.operation?.invisible === true) { - core[_board].resetCursor(); + 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'), + if (this.temp.get('hoverUUID') !== elem.uuid) { + const preIndex = helper.getElementIndexByUUID(this.temp.get('hoverUUID') || ''); + if (preIndex !== null && data.elements[preIndex]) { + coreEvent.trigger('mouseLeaveElement', { + uuid: this.temp.get('hoverUUID'), index: preIndex, - element: core[_data].elements[preIndex] + element: data.elements[preIndex] }); } } if (elem) { - core[_coreEvent].trigger('mouseOverElement', { uuid: elem.uuid, index, element: elem, }); - core[_tempData].set('hoverUUID', elem.uuid); + coreEvent.trigger('mouseOverElement', { uuid: elem.uuid, index, element: elem, }); + this.temp.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 (isMouseOverElement !== true && this.temp.get('hoverUUID') !== null) { + const uuid = this.temp.get('hoverUUID'); + const index: number | null = helper.getElementIndexByUUID(uuid || ''); + if (index !== null) coreEvent.trigger('mouseLeaveElement', { uuid, index, element: data.elements[index] }) + this.temp.set('hoverUUID', null); } - if (core[_coreEvent].has('mouseOverScreen')) core[_coreEvent].trigger('mouseOverScreen', point); + if (coreEvent.has('mouseOverScreen')) coreEvent.trigger('mouseOverScreen', point); } -} -function handleLeave(core: Core) { - return function(): void { - if (core[_coreEvent].has('mouseLeaveScreen')) { - core[_coreEvent].trigger('mouseLeaveScreen', undefined); + private _handleLeave(): void { + const { coreEvent } = this._opts; + if (coreEvent.has('mouseLeaveScreen')) { + 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/core/src/lib/helper.ts b/packages/core/src/lib/helper.ts index 4a5cd11..9b30d77 100644 --- a/packages/core/src/lib/helper.ts +++ b/packages/core/src/lib/helper.ts @@ -121,13 +121,13 @@ export class Helper implements TypeHelper { hoverDirectionNames = hoverDirectionNames.slice(-angleMoveNum).concat(hoverDirectionNames.slice(0, -angleMoveNum)) } - rotateContext(ctx, wrapper.translate, wrapper.radian || 0, () => { for (let i = 0; i < controllers.length; i ++) { const controller = controllers[i]; if (controller.invisible === true) { continue; } + ctx.beginPath(); ctx.arc(controller.x, controller.y, wrapper.controllerSize, 0, Math.PI * 2); ctx.closePath(); @@ -141,6 +141,7 @@ export class Helper implements TypeHelper { } } }); + if (selectedControllerDirection === null) { const controller = wrapper.controllers.rotate; if (controller.invisible !== true) { @@ -155,6 +156,7 @@ export class Helper implements TypeHelper { }); } } + return {uuid, selectedControllerDirection, hoverControllerDirection, directIndex}; } diff --git a/packages/core/src/lib/mapper.ts b/packages/core/src/lib/mapper.ts index 6b78f81..34e56c2 100644 --- a/packages/core/src/lib/mapper.ts +++ b/packages/core/src/lib/mapper.ts @@ -47,7 +47,6 @@ export class Mapper { return { cursor, elementUUID}; } const { uuid, hoverControllerDirection } = this[_helper].isPointInElementWrapperController(p, data); - const direction = hoverControllerDirection; if (uuid && direction) { switch (direction) { diff --git a/packages/core/src/lib/temp.ts b/packages/core/src/lib/temp.ts index e95992d..9da158b 100644 --- a/packages/core/src/lib/temp.ts +++ b/packages/core/src/lib/temp.ts @@ -1,31 +1,10 @@ -import { TypeHelperWrapperControllerDirection, TypePoint } 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, } function createData(): TempDataDesc { return { - onlyRender: false, hasInited: false, - mode: Mode.NULL, - cursorStatus: CursorStatus.NULL, - selectedUUID: null, - selectedUUIDList: [], - hoverUUID: null, - selectedControllerDirection: null, - hoverControllerDirection: null, - prevPoint: null, } } diff --git a/packages/core/src/mixins/element.ts b/packages/core/src/mixins/element.ts index 731ee53..f6b16d4 100644 --- a/packages/core/src/mixins/element.ts +++ b/packages/core/src/mixins/element.ts @@ -3,7 +3,7 @@ import { } from '@idraw/types'; import util from '@idraw/util'; import { - _board, _data, _opts, _config, _renderer, _element, _helper, + _board, _data, _opts, _config, _renderer, _element, _engine, _tempData, _draw, _coreEvent, _emitChangeScreen, _emitChangeData, } from './../names'; import { diffElementResourceChange } from './../lib/diff'; @@ -17,14 +17,14 @@ const { createUUID } = util.uuid; export function getSelectedElements(core: Core): TypeElement[] { const elems: TypeElement[] = []; let list: string[] = []; - const uuid = core[_tempData].get('selectedUUID'); + const uuid = core[_engine].temp.get('selectedUUID'); if (typeof uuid === 'string' && uuid) { list.push(uuid); } else { - list = core[_tempData].get('selectedUUIDList'); + list = core[_engine].temp.get('selectedUUIDList'); } list.forEach((uuid) => { - const index = core[_helper].getElementIndexByUUID(uuid); + const index = core[_engine].helper.getElementIndexByUUID(uuid); if (index !== null && index >= 0) { const elem = core[_data]?.elements[index]; if (elem) elems.push(elem); @@ -35,7 +35,7 @@ export function getSelectedElements(core: Core): TypeElement export function getElement(core: Core, uuid: string): TypeElement|null { let elem: TypeElement|null = null; - const index = core[_helper].getElementIndexByUUID(uuid); + const index = core[_engine].helper.getElementIndexByUUID(uuid); if (index !== null && core[_data].elements[index]) { elem = deepClone(core[_data].elements[index]); } @@ -69,17 +69,16 @@ export function updateElement(core: Core, elem: TypeElement) } 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); + core[_engine].temp.set('mode', Mode.SELECT_ELEMENT); } else { - core[_tempData].set('mode', Mode.NULL); + core[_engine].temp.set('mode', Mode.NULL); } if (typeof uuid === 'string') { - core[_tempData].set('selectedUUID', uuid); - core[_tempData].set('selectedUUIDList', []); + core[_engine].temp.set('selectedUUID', uuid); + core[_engine].temp.set('selectedUUIDList', []); } core[_draw](); } @@ -87,16 +86,14 @@ export function selectElementByIndex(core: Core, index: number, opts?: { useMode export function selectElement(core: Core, uuid: string, opts?: { useMode?: boolean }): void { - if (core[_tempData].get('onlyRender') === true) return; - const index = core[_helper].getElementIndexByUUID(uuid); + const index = core[_engine].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); + const index = core[_engine].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]; @@ -107,8 +104,7 @@ export function moveUpElement(core: Core, uuid: string): void { } export function moveDownElement(core: Core, uuid: string): void { - // if (this[_onlyRender] === true) return; - const index = core[_helper].getElementIndexByUUID(uuid); + const index = core[_engine].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]; @@ -120,7 +116,6 @@ export function moveDownElement(core: Core, uuid: string): void { 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); @@ -130,7 +125,6 @@ export function addElement(core: Core, elem: TypeElementBase } 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); @@ -140,7 +134,7 @@ export function deleteElement(core: Core, uuid: string) { } export function insertElementBefore(core: Core, elem: TypeElementBase, beforeUUID: string) { - const index = core[_helper].getElementIndexByUUID(beforeUUID); + const index = core[_engine].helper.getElementIndexByUUID(beforeUUID); if (index !== null) { return core.insertElementBeforeIndex(elem, index); } @@ -162,7 +156,7 @@ export function insertElementBeforeIndex(core: Core, elem: TypeElementBase, beforeUUID: string) { - const index = core[_helper].getElementIndexByUUID(beforeUUID); + const index = core[_engine].helper.getElementIndexByUUID(beforeUUID); if (index !== null) { return core.insertElementAfterIndex(elem, index); } diff --git a/packages/core/src/mixins/event.ts b/packages/core/src/mixins/event.ts deleted file mode 100644 index 209a9e3..0000000 --- a/packages/core/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/core/src/names.ts b/packages/core/src/names.ts index 0bca47e..f007760 100644 --- a/packages/core/src/names.ts +++ b/packages/core/src/names.ts @@ -11,10 +11,10 @@ const _coreEvent = Symbol('_coreEvent'); const _mapper = Symbol('_mapper'); const _emitChangeScreen = Symbol('_emitChangeScreen'); const _emitChangeData = Symbol('_emitChangeData'); -const _todo = Symbol('_todo'); +const _engine = Symbol('_engine'); export { _board, _data, _opts, _config, _renderer, _element, _helper, _tempData, _draw, _coreEvent, _mapper, - _emitChangeScreen, _emitChangeData, _todo, + _emitChangeScreen, _emitChangeData, _engine, }; \ No newline at end of file