From 3494deec191481d03079cbb748384e466802c246 Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Tue, 25 May 2021 12:58:29 +0800 Subject: [PATCH] chore: update board/example --- packages/board/example/features/lib/action.js | 36 +++++++++ packages/board/example/features/lib/data.js | 53 ++++++++++++ packages/board/example/features/lib/draw.js | 25 +++--- packages/board/example/features/lib/event.js | 24 ++++++ packages/board/example/features/lib/opts.js | 5 ++ packages/board/example/features/lib/scale.js | 2 +- packages/board/example/features/lib/scroll.js | 2 +- packages/board/example/features/main.js | 23 +++--- packages/board/src/index.ts | 17 +++- packages/board/src/util/context.ts | 2 +- packages/board/src/util/watcher.ts | 80 ++++++++----------- 11 files changed, 192 insertions(+), 77 deletions(-) create mode 100644 packages/board/example/features/lib/action.js create mode 100644 packages/board/example/features/lib/data.js create mode 100644 packages/board/example/features/lib/event.js create mode 100644 packages/board/example/features/lib/opts.js diff --git a/packages/board/example/features/lib/action.js b/packages/board/example/features/lib/action.js new file mode 100644 index 0000000..473a0af --- /dev/null +++ b/packages/board/example/features/lib/action.js @@ -0,0 +1,36 @@ +import { getData } from "./data.js"; +import { drawData } from './draw.js'; + +function isPointInElement(board, p = {x, y}) { + const ctx = board.getContext(); + const data = getData(); + let idx = -1; + for (let i = data.elements.length - 1; i >= 0; i--) { + const ele = data.elements[i]; + ctx.beginPath(); + ctx.lineTo(ele.x, ele.y); + ctx.lineTo(ele.x + ele.w, ele.y); + ctx.lineTo(ele.x + ele.w, ele.y + ele.h); + ctx.lineTo(ele.x, ele.y + ele.h); + ctx.closePath(); + if (ctx.isPointInPath(p.x, p.y)) { + idx = i; + break; + } + } + return idx; +} + +function moveElement(board, idx, moveX, moveY) { + const data = getData(); + if (data.elements[idx]) { + data.elements[idx].x += moveX; + data.elements[idx].y += moveY; + } + drawData(board) +} + +export { + isPointInElement, + moveElement, +} \ No newline at end of file diff --git a/packages/board/example/features/lib/data.js b/packages/board/example/features/lib/data.js new file mode 100644 index 0000000..fef0559 --- /dev/null +++ b/packages/board/example/features/lib/data.js @@ -0,0 +1,53 @@ + +const data = { + elements: [ + { + x: 10, + y: 10, + w: 200, + h: 120, + type: 'rect', + desc: { + color: '#f0f0f0', + } + }, + { + x: 80, + y: 80, + w: 200, + h: 120, + type: 'rect', + desc: { + color: '#cccccc', + } + }, + { + x: 160, + y: 160, + w: 200, + h: 120, + type: 'rect', + desc: { + color: '#c0c0c0', + } + }, + { + x: 400 - 10, + y: 300 - 10, + w: 200, + h: 100, + type: 'rect', + desc: { + color: '#e0e0e0', + } + } + ] +} + +function getData() { + return data; +} + +export { + getData +}; \ No newline at end of file diff --git a/packages/board/example/features/lib/draw.js b/packages/board/example/features/lib/draw.js index d16f7fa..8488196 100644 --- a/packages/board/example/features/lib/draw.js +++ b/packages/board/example/features/lib/draw.js @@ -1,17 +1,14 @@ -export function draw(board) { +import opts from './opts.js'; +import { getData } from './data.js'; + +export function drawData(board) { const ctx = board.getContext(); - - ctx.setFillStyle('#f0f0f0'); - ctx.fillRect(10, 10, 200, 120); - - ctx.setFillStyle('#cccccc'); - ctx.fillRect(80, 80, 200, 120); - - ctx.setFillStyle('#c0c0c0'); - ctx.fillRect(160, 160, 200, 120); - - ctx.setFillStyle('#e0e0e0'); - ctx.fillRect(400 - 10, 300 - 10, 200, 100); - + const data = getData(); + board.clear(); + ctx.clearRect(0, 0, opts.width, opts.height); + data.elements.forEach(ele => { + ctx.setFillStyle(ele.desc.color); + ctx.fillRect(ele.x, ele.y, ele.w, ele.h); + }); board.draw(); } \ No newline at end of file diff --git a/packages/board/example/features/lib/event.js b/packages/board/example/features/lib/event.js new file mode 100644 index 0000000..4ffe21e --- /dev/null +++ b/packages/board/example/features/lib/event.js @@ -0,0 +1,24 @@ +import { isPointInElement, moveElement } from './action.js'; + +let selectIdx = -1; +let prevPoint = { x: null, y: null }; + +export function initEvent(board) { + + board.on('point', (p) => { + selectIdx = isPointInElement(board, p); + }); + + board.on('move', (p) => { + moveElement(board, selectIdx, p.x - prevPoint.x, p.y - prevPoint.y); + prevPoint = p; + }); + + board.on('moveStart', (p) => { + prevPoint = p; + }); + + board.on('moveEnd', (p) => { + selectIdx = false; + }); +} \ No newline at end of file diff --git a/packages/board/example/features/lib/opts.js b/packages/board/example/features/lib/opts.js new file mode 100644 index 0000000..748f45b --- /dev/null +++ b/packages/board/example/features/lib/opts.js @@ -0,0 +1,5 @@ +export default { + width: 600, + height: 400, + devicePixelRatio: 4 +} \ No newline at end of file diff --git a/packages/board/example/features/lib/scale.js b/packages/board/example/features/lib/scale.js index 589d168..fa5bd66 100644 --- a/packages/board/example/features/lib/scale.js +++ b/packages/board/example/features/lib/scale.js @@ -1,7 +1,7 @@ const input = document.querySelector('#scale'); let hasInited = false; -export function onScale(board) { +export function doScale(board) { if (hasInited === true) return; input.addEventListener('change', () => { const val = input.value * 1; diff --git a/packages/board/example/features/lib/scroll.js b/packages/board/example/features/lib/scroll.js index b52b7c5..4b9d810 100644 --- a/packages/board/example/features/lib/scroll.js +++ b/packages/board/example/features/lib/scroll.js @@ -2,7 +2,7 @@ const inputX = document.querySelector('#scrollX'); const inputY = document.querySelector('#scrollY'); let hasInited = false; -export function onScroll(board) { +export function doScroll(board) { if (hasInited === true) return; inputX.addEventListener('change', () => { const val = inputX.value * 1; diff --git a/packages/board/example/features/main.js b/packages/board/example/features/main.js index 1d9fbc1..fc25e1c 100644 --- a/packages/board/example/features/main.js +++ b/packages/board/example/features/main.js @@ -1,19 +1,20 @@ -import { draw } from './lib/draw.js'; -import { onScale } from './lib/scale.js'; -import { onScroll } from './lib/scroll.js'; +import opts from './lib/opts.js'; +import { drawData } from './lib/draw.js'; +import { doScale } from './lib/scale.js'; +import { doScroll } from './lib/scroll.js'; +import { initEvent } from './lib/event.js'; const { Board } = window.iDraw; const mount = document.querySelector('#mount'); -const board = new Board(mount, { - width: 600, - height: 400, - devicePixelRatio: 4 -}); +const board = new Board(mount, opts); + +drawData(board); + +initEvent(board); +doScale(board); +doScroll(board); -draw(board); -onScale(board); -onScroll(board); // board.scale(2); // board.draw(); \ No newline at end of file diff --git a/packages/board/src/index.ts b/packages/board/src/index.ts index 275dff3..ac2ec57 100644 --- a/packages/board/src/index.ts +++ b/packages/board/src/index.ts @@ -1,7 +1,8 @@ // import { TypePoint } from '@idraw/types'; -// import { Watcher } from './util/watcher'; +import { Watcher } from './util/watcher'; import { setStyle } from './util/style'; import Context from './util/context'; +import { TypeBoardEventArgMap } from './util/event'; type Options = { width: number; @@ -24,7 +25,7 @@ class Board { private _scaleRatio: number = 1; private _scrollX: number = 0; private _scrollY: number = 0; - // private _watcher: Watcher; + private _watcher: Watcher; constructor(mount: HTMLDivElement, opts: Options) { this._mount = mount; @@ -36,7 +37,8 @@ class Board { const displayCtx = this._displayCanvas.getContext('2d') as CanvasRenderingContext2D; this._ctx = new Context(ctx, this._opts); this._displayCtx = displayCtx; - // this._watcher = new Watcher(this._canvas); + this._watcher = new Watcher(this._displayCanvas); + this._render(); } @@ -66,6 +68,14 @@ class Board { this._displayCtx.clearRect(0, 0, this._displayCanvas.width, this._displayCanvas.height) } + on(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) { + this._watcher.on(name, callback) + } + + off(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) { + this._watcher.off(name, callback) + } + private _render() { if (this._hasRendered === true) { return; @@ -104,7 +114,6 @@ class Board { size.h = height * pxRatio * _scaleRatio; return size; } - } diff --git a/packages/board/src/util/context.ts b/packages/board/src/util/context.ts index 78dfc1d..bea8e05 100644 --- a/packages/board/src/util/context.ts +++ b/packages/board/src/util/context.ts @@ -52,7 +52,7 @@ class Context { } isPointInPath(x: number, y: number) { - return this._ctx.lineTo(this._doSize(x), this._doSize(y)); + return this._ctx.isPointInPath(this._doSize(x), this._doSize(y)); } private _doSize(num: number) { diff --git a/packages/board/src/util/watcher.ts b/packages/board/src/util/watcher.ts index b565c84..21f4258 100644 --- a/packages/board/src/util/watcher.ts +++ b/packages/board/src/util/watcher.ts @@ -1,94 +1,84 @@ import { TypePoint } from '@idraw/types'; - -interface TypeWatcher { - onMove(callback: TypeWatchCallback): void, - onMoveEnd(callback: TypeWatchCallback): void, - onMoveEnd(callback: TypeWatchCallback): void, -} +import { BoardEvent, TypeBoardEventArgMap } from './event'; -type TypeWatchCallback = (p: TypePoint) => void - -export class Watcher implements TypeWatcher { +export class Watcher { private _canvas: HTMLCanvasElement; - private _isPainting: boolean = false; - private _onMove?: TypeWatchCallback; - private _onMoveStart?: TypeWatchCallback; - private _onMoveEnd?: TypeWatchCallback; + private _isMoving: boolean = false; + // private _onMove?: TypeWatchCallback; + // private _onMoveStart?: TypeWatchCallback; + // private _onMoveEnd?: TypeWatchCallback; + private _event: BoardEvent; constructor(canvas: HTMLCanvasElement) { this._canvas = canvas; - this._isPainting = false; + this._isMoving = false; this._initEvent(); + this._event = new BoardEvent; } - onMove(callback: TypeWatchCallback) { - this._onMove = callback; + on(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) { + this._event.on(name, callback) } - onMoveEnd(callback: TypeWatchCallback) { - this._onMoveEnd = callback; - } - - onMoveStart(callback: TypeWatchCallback) { - this._onMoveStart = callback; + off(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) { + this._event.off(name, callback) } _initEvent() { const canvas = this._canvas; - canvas.addEventListener('mousedown', this._listenStart.bind(this)); + canvas.addEventListener('mousedown', this._listenMoveStart.bind(this)); canvas.addEventListener('mousemove', this._listenMove.bind(this)); - canvas.addEventListener('mouseup', this._listenEnd.bind(this)); + canvas.addEventListener('mouseup', this._listenMoveEnd.bind(this)); - canvas.addEventListener('touchstart', this._listenStart.bind(this)); + canvas.addEventListener('touchstart', this._listenMoveStart.bind(this)); canvas.addEventListener('touchmove', this._listenMove.bind(this)); - canvas.addEventListener('touchend', this._listenEnd.bind(this)); + canvas.addEventListener('touchend', this._listenMoveEnd.bind(this)); const mouseupEvent = new MouseEvent('mouseup'); document.querySelector('body')?.addEventListener('mousemove', (e) => { // @ts-ignore if (e && e.path && e.path[0] !== canvas) { - if (this._isPainting === true) { - canvas.dispatchEvent(mouseupEvent); - } + canvas.dispatchEvent(mouseupEvent); } }, false) } - _listenStart(e: MouseEvent|TouchEvent) { + _listenMoveStart(e: MouseEvent|TouchEvent) { e.preventDefault(); - this._isPainting = true; - if (typeof this._onMoveStart === 'function') { - const p = this._getPosition(e); - if (this._isVaildPoint(p)) { - this._onMoveStart(p); + const p = this._getPosition(e); + if (this._isVaildPoint(p)) { + if (this._event.has('point')) { + this._event.trigger('point', p); + } + if (this._event.has('moveStart')) { + this._event.trigger('moveStart', p); } } + this._isMoving = true; } _listenMove(e: MouseEvent|TouchEvent) { e.preventDefault(); e.stopPropagation(); - if (this._isPainting === true) { - if (typeof this._onMove === 'function') { - const p = this._getPosition(e); - if (this._isVaildPoint(p)) { - this._onMove(p); - } + if (this._event.has('move') && this._isMoving === true) { + const p = this._getPosition(e); + if (this._isVaildPoint(p)) { + this._event.trigger('move', p); } } } - _listenEnd(e: MouseEvent|TouchEvent) { + _listenMoveEnd(e: MouseEvent|TouchEvent) { e.preventDefault(); - this._isPainting = false; - if (typeof this._onMoveEnd === 'function') { + if (this._event.has('moveEnd')) { const p = this._getPosition(e); if (this._isVaildPoint(p)) { - this._onMoveEnd(p); + this._event.trigger('moveEnd', p); } } + this._isMoving = false; } _getPosition(e: MouseEvent|TouchEvent) {