diff --git a/docs/todo/core.md b/docs/todo/core.md index 05122a3..4e14f4d 100644 --- a/docs/todo/core.md +++ b/docs/todo/core.md @@ -1,11 +1,13 @@ # @idraw/core +* [] Area select +* [] Keep all num two decimals +* [x] Cursor style * [x] Can't controll element at scroll-area * [x] Disable controll element * [x] static check/is type declare * [x] Force update image/svg image when element change * [x] Reset board's size -* [] Keep all num two decimals * [x] Limit element's angle between -360~360 deg * [x] Check if the element and elements' attribute of desc is supported * [x] Suport elements'desc and attribute check method diff --git a/packages/board/src/index.ts b/packages/board/src/index.ts index 1163f45..e15335a 100644 --- a/packages/board/src/index.ts +++ b/packages/board/src/index.ts @@ -1,4 +1,6 @@ -import { TypeScreenPosition, TypeScreenSize, TypeScreenContext, TypePoint, TypeBoardOptions, TypeBoardSizeOptions, } from '@idraw/types'; +import { + TypeScreenPosition, TypeScreenSize, TypeScreenContext, TypePoint, TypePointCursor, + TypeBoardOptions, TypeBoardSizeOptions, } from '@idraw/types'; import util from '@idraw/util'; import { Watcher } from './lib/watcher'; import { setStyle } from './lib/style'; @@ -17,9 +19,6 @@ type PrivateOptions = TypeBoardOptions & { devicePixelRatio: number } -type TypeCursor = 'auto' | 'move' | 'n-resize' | 'e-resize' | 's-resize' | 'w-resize' -| 'ne-resize' | 'nw-resize' | 'se-resize' | 'sw-resize' | 'grab'; - class Board { private [_canvas]: HTMLCanvasElement; private [_displayCanvas]: HTMLCanvasElement; @@ -138,7 +137,7 @@ class Board { return this[_calcScreen](); } - setCursor(cursor: TypeCursor) { + setCursor(cursor: TypePointCursor) { this[_displayCanvas].style.cursor = cursor; } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 26642aa..0c4b551 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -18,8 +18,8 @@ import { _board, _data, _opts, _config, _renderer, _element, _helper, _hasInited, _hasInitedData, _mode, _selectedUUID, _prevPoint, _selectedDotDirection, _coreEvent, _mapper, _initEvent, _handlePoint, _handleMoveStart, _handleMove, - _handleMoveEnd, _dragElement, _transfromElement, _emitChangeScreen, _emitChangeData, - _onlyRender, + _handleMoveEnd, _handleHover, _dragElement, _transfromElement, _emitChangeScreen, + _emitChangeData, _onlyRender, _cursorStatus, } from './names'; const { time } = util; @@ -30,7 +30,11 @@ enum Mode { NULL = 'null', SELECT_ELEMENT = 'select-element', SELECT_ELEMENT_WRAPPER_DOT = 'select-element-wrapper-dot', - PAINTING = 'painting', +} + +enum CursorStatus { + DRAGGING = 'dragging', + NULL = 'null' } class Core { @@ -51,6 +55,7 @@ class Core { private [_prevPoint]: TypePoint | null = null; private [_selectedDotDirection]: TypeHelperWrapperDotDirection | null = null; private [_onlyRender]: boolean = false; + private [_cursorStatus]: CursorStatus = CursorStatus.NULL; static is: TypeIs = is; static check: TypeCheck = check; @@ -72,7 +77,11 @@ class Core { this[_renderer] = new Renderer(this[_board]); this[_element] = new Element(this[_board].getContext()); this[_helper] = new Helper(this[_board], this[_config]); - this[_mapper] = new Mapper(this[_board]); + this[_mapper] = new Mapper({ + board: this[_board], + helper: this[_helper], + element: this[_element] + }); this[_initEvent](); this[_hasInited] = true; } @@ -244,6 +253,7 @@ class Core { this[_board].on('moveStart', this[_handleMoveStart].bind(this)); this[_board].on('move', time.throttle(this[_handleMove].bind(this), 16)); this[_board].on('moveEnd', this[_handleMoveEnd].bind(this)); + this[_board].on('hover', time.throttle(this[_handleHover].bind(this), 32)); } private [_handlePoint](point: TypePoint): void { @@ -284,12 +294,15 @@ class Core { } private [_handleMove](point: TypePoint): void { + if (typeof this[_selectedUUID] === 'string') { if (this[_mode] === Mode.SELECT_ELEMENT) { this[_dragElement](this[_selectedUUID] as string, point, this[_prevPoint]); this.draw(); + this[_cursorStatus] = CursorStatus.DRAGGING; } else if (this[_mode] === Mode.SELECT_ELEMENT_WRAPPER_DOT && this[_selectedDotDirection]) { this[_transfromElement](this[_selectedUUID] as string, point, this[_prevPoint], this[_selectedDotDirection] as TypeHelperWrapperDotDirection); + this[_cursorStatus] = CursorStatus.DRAGGING; } } this[_prevPoint] = point; @@ -323,6 +336,14 @@ class Core { } this[_selectedUUID] = null; this[_prevPoint] = null; + this[_cursorStatus] = CursorStatus.NULL; + } + + private [_handleHover](point: TypePoint): void { + if (this[_cursorStatus] === CursorStatus.NULL) { + const cursor = this[_mapper].judgePointCursor(point, this[_data]); + this[_board].setCursor(cursor); + } } private [_dragElement](uuid: string, point: TypePoint, prevPoint: TypePoint|null): void { diff --git a/packages/core/src/lib/mapper.ts b/packages/core/src/lib/mapper.ts index 01ddc97..b15a2ec 100644 --- a/packages/core/src/lib/mapper.ts +++ b/packages/core/src/lib/mapper.ts @@ -1,14 +1,31 @@ -import { TypePoint } from '@idraw/types'; +import { TypeData, TypePoint, TypePointCursor } from '@idraw/types'; import Board from '@idraw/board'; +import { Helper } from './helper'; +import { Element } from './element'; const _board = Symbol('_displayCtx'); +const _helper = Symbol('_helper'); +const _element = Symbol('_element'); +const _opts = Symbol('_opts'); + +type Options = { + board: Board; + element: Element; + helper: Helper +} export class Mapper { - private [_board]: Board + private [_opts]: Options; + private [_board]: Board; + private [_helper]: Helper; + private [_element]: Element; - constructor(board: Board) { - this[_board] = board; + constructor(opts: Options) { + this[_opts] = opts; + this[_board] = this[_opts].board; + this[_element] = this[_opts].element; + this[_helper] = this[_opts].helper; } isEffectivePoint(p: TypePoint): boolean { @@ -19,4 +36,62 @@ export class Mapper { } return false; } + + judgePointCursor(p: TypePoint, data: TypeData): TypePointCursor { + let cursor: TypePointCursor = 'auto'; + if (!this.isEffectivePoint(p)) { + return cursor; + } + const [uuid, direction] = this[_helper].isPointInElementWrapperDot(p); + if (uuid && direction) { + switch (direction) { + case 'top-left' : { + cursor = 'nw-resize'; + break; + } + case 'top' : { + cursor = 'n-resize'; + break; + } + case 'top-right' : { + cursor = 'ne-resize'; + break; + } + case 'right' : { + cursor = 'e-resize'; + break; + } + case 'bottom-right' : { + cursor = 'se-resize'; + break; + } + case 'bottom' : { + cursor = 's-resize'; + break; + } + case 'bottom-left' : { + cursor = 'sw-resize'; + break; + } + case 'left' : { + cursor = 'w-resize'; + break; + } + case 'rotate' : { + cursor = 'grab'; + break; + } + default: { + break; + } + } + } else { + const [index] = this[_element].isPointInElement(p, data); + if (index >= 0) { + cursor = 'move'; + } + } + return cursor; + } + } diff --git a/packages/core/src/names.ts b/packages/core/src/names.ts index 96b973b..98c92f7 100644 --- a/packages/core/src/names.ts +++ b/packages/core/src/names.ts @@ -18,16 +18,18 @@ const _handlePoint = Symbol('_handlePoint'); const _handleMoveStart = Symbol('_handleMoveStart'); const _handleMove = Symbol('_handleMove'); const _handleMoveEnd = Symbol('_handleMoveEnd'); +const _handleHover = Symbol('_handleHover'); const _dragElement = Symbol('_dragElement'); const _transfromElement = Symbol('_transfromElement'); const _emitChangeScreen = Symbol('_emitChangeScreen'); const _emitChangeData = Symbol('_emitChangeData'); -const _onlyRender = Symbol('onlyRender'); +const _onlyRender = Symbol('_onlyRender'); +const _cursorStatus = Symbol('_cursorStatus'); export { _board, _data, _opts, _config, _renderer, _element, _helper, _hasInited, _hasInitedData, _mode, _selectedUUID, _prevPoint, _selectedDotDirection, _coreEvent, _mapper, _initEvent, _handlePoint, _handleMoveStart, _handleMove, - _handleMoveEnd, _dragElement, _transfromElement, _emitChangeScreen, _emitChangeData, - _onlyRender, + _handleMoveEnd, _handleHover, _dragElement, _transfromElement, _emitChangeScreen, + _emitChangeData, _onlyRender, _cursorStatus, } \ No newline at end of file diff --git a/packages/types/src/lib/board.ts b/packages/types/src/lib/board.ts index d0401e1..2c81524 100644 --- a/packages/types/src/lib/board.ts +++ b/packages/types/src/lib/board.ts @@ -25,8 +25,12 @@ type TypeBoardOptions = TypeBoardSizeOptions & { scrollConfig?: TypeBoardScrollConfig } +type TypePointCursor = 'auto' | 'move' | 'n-resize' | 'e-resize' | 's-resize' | 'w-resize' +| 'ne-resize' | 'nw-resize' | 'se-resize' | 'sw-resize' | 'grab'; + export { TypePoint, + TypePointCursor, TypeBoardSizeOptions, TypeBoardOptions, TypeBoardScrollConfig,