chore: update board/example

This commit is contained in:
chenshenhai 2021-05-25 12:58:29 +08:00
parent dcf5fae055
commit 3494deec19
11 changed files with 192 additions and 77 deletions

View file

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

View file

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

View file

@ -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(); const ctx = board.getContext();
const data = getData();
ctx.setFillStyle('#f0f0f0'); board.clear();
ctx.fillRect(10, 10, 200, 120); ctx.clearRect(0, 0, opts.width, opts.height);
data.elements.forEach(ele => {
ctx.setFillStyle('#cccccc'); ctx.setFillStyle(ele.desc.color);
ctx.fillRect(80, 80, 200, 120); ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
});
ctx.setFillStyle('#c0c0c0');
ctx.fillRect(160, 160, 200, 120);
ctx.setFillStyle('#e0e0e0');
ctx.fillRect(400 - 10, 300 - 10, 200, 100);
board.draw(); board.draw();
} }

View file

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

View file

@ -0,0 +1,5 @@
export default {
width: 600,
height: 400,
devicePixelRatio: 4
}

View file

@ -1,7 +1,7 @@
const input = document.querySelector('#scale'); const input = document.querySelector('#scale');
let hasInited = false; let hasInited = false;
export function onScale(board) { export function doScale(board) {
if (hasInited === true) return; if (hasInited === true) return;
input.addEventListener('change', () => { input.addEventListener('change', () => {
const val = input.value * 1; const val = input.value * 1;

View file

@ -2,7 +2,7 @@ const inputX = document.querySelector('#scrollX');
const inputY = document.querySelector('#scrollY'); const inputY = document.querySelector('#scrollY');
let hasInited = false; let hasInited = false;
export function onScroll(board) { export function doScroll(board) {
if (hasInited === true) return; if (hasInited === true) return;
inputX.addEventListener('change', () => { inputX.addEventListener('change', () => {
const val = inputX.value * 1; const val = inputX.value * 1;

View file

@ -1,19 +1,20 @@
import { draw } from './lib/draw.js'; import opts from './lib/opts.js';
import { onScale } from './lib/scale.js'; import { drawData } from './lib/draw.js';
import { onScroll } from './lib/scroll.js'; import { doScale } from './lib/scale.js';
import { doScroll } from './lib/scroll.js';
import { initEvent } from './lib/event.js';
const { Board } = window.iDraw; const { Board } = window.iDraw;
const mount = document.querySelector('#mount'); const mount = document.querySelector('#mount');
const board = new Board(mount, { const board = new Board(mount, opts);
width: 600,
height: 400, drawData(board);
devicePixelRatio: 4
}); initEvent(board);
doScale(board);
doScroll(board);
draw(board);
onScale(board);
onScroll(board);
// board.scale(2); // board.scale(2);
// board.draw(); // board.draw();

View file

@ -1,7 +1,8 @@
// import { TypePoint } from '@idraw/types'; // import { TypePoint } from '@idraw/types';
// import { Watcher } from './util/watcher'; import { Watcher } from './util/watcher';
import { setStyle } from './util/style'; import { setStyle } from './util/style';
import Context from './util/context'; import Context from './util/context';
import { TypeBoardEventArgMap } from './util/event';
type Options = { type Options = {
width: number; width: number;
@ -24,7 +25,7 @@ class Board {
private _scaleRatio: number = 1; private _scaleRatio: number = 1;
private _scrollX: number = 0; private _scrollX: number = 0;
private _scrollY: number = 0; private _scrollY: number = 0;
// private _watcher: Watcher; private _watcher: Watcher;
constructor(mount: HTMLDivElement, opts: Options) { constructor(mount: HTMLDivElement, opts: Options) {
this._mount = mount; this._mount = mount;
@ -36,7 +37,8 @@ class Board {
const displayCtx = this._displayCanvas.getContext('2d') as CanvasRenderingContext2D; const displayCtx = this._displayCanvas.getContext('2d') as CanvasRenderingContext2D;
this._ctx = new Context(ctx, this._opts); this._ctx = new Context(ctx, this._opts);
this._displayCtx = displayCtx; this._displayCtx = displayCtx;
// this._watcher = new Watcher(this._canvas); this._watcher = new Watcher(this._displayCanvas);
this._render(); this._render();
} }
@ -66,6 +68,14 @@ class Board {
this._displayCtx.clearRect(0, 0, this._displayCanvas.width, this._displayCanvas.height) this._displayCtx.clearRect(0, 0, this._displayCanvas.width, this._displayCanvas.height)
} }
on<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
this._watcher.on(name, callback)
}
off<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
this._watcher.off(name, callback)
}
private _render() { private _render() {
if (this._hasRendered === true) { if (this._hasRendered === true) {
return; return;
@ -104,7 +114,6 @@ class Board {
size.h = height * pxRatio * _scaleRatio; size.h = height * pxRatio * _scaleRatio;
return size; return size;
} }
} }

View file

@ -52,7 +52,7 @@ class Context {
} }
isPointInPath(x: number, y: number) { 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) { private _doSize(num: number) {

View file

@ -1,94 +1,84 @@
import { TypePoint } from '@idraw/types'; import { TypePoint } from '@idraw/types';
import { BoardEvent, TypeBoardEventArgMap } from './event';
interface TypeWatcher {
onMove(callback: TypeWatchCallback): void,
onMoveEnd(callback: TypeWatchCallback): void,
onMoveEnd(callback: TypeWatchCallback): void,
}
type TypeWatchCallback = (p: TypePoint) => void export class Watcher {
export class Watcher implements TypeWatcher {
private _canvas: HTMLCanvasElement; private _canvas: HTMLCanvasElement;
private _isPainting: boolean = false; private _isMoving: boolean = false;
private _onMove?: TypeWatchCallback; // private _onMove?: TypeWatchCallback;
private _onMoveStart?: TypeWatchCallback; // private _onMoveStart?: TypeWatchCallback;
private _onMoveEnd?: TypeWatchCallback; // private _onMoveEnd?: TypeWatchCallback;
private _event: BoardEvent;
constructor(canvas: HTMLCanvasElement) { constructor(canvas: HTMLCanvasElement) {
this._canvas = canvas; this._canvas = canvas;
this._isPainting = false; this._isMoving = false;
this._initEvent(); this._initEvent();
this._event = new BoardEvent;
} }
onMove(callback: TypeWatchCallback) { on<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
this._onMove = callback; this._event.on(name, callback)
} }
onMoveEnd(callback: TypeWatchCallback) { off<T extends keyof TypeBoardEventArgMap >(name: T, callback: (p: TypeBoardEventArgMap[T]) => void) {
this._onMoveEnd = callback; this._event.off(name, callback)
}
onMoveStart(callback: TypeWatchCallback) {
this._onMoveStart = callback;
} }
_initEvent() { _initEvent() {
const canvas = this._canvas; 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('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('touchmove', this._listenMove.bind(this));
canvas.addEventListener('touchend', this._listenEnd.bind(this)); canvas.addEventListener('touchend', this._listenMoveEnd.bind(this));
const mouseupEvent = new MouseEvent('mouseup'); const mouseupEvent = new MouseEvent('mouseup');
document.querySelector('body')?.addEventListener('mousemove', (e) => { document.querySelector('body')?.addEventListener('mousemove', (e) => {
// @ts-ignore // @ts-ignore
if (e && e.path && e.path[0] !== canvas) { if (e && e.path && e.path[0] !== canvas) {
if (this._isPainting === true) { canvas.dispatchEvent(mouseupEvent);
canvas.dispatchEvent(mouseupEvent);
}
} }
}, false) }, false)
} }
_listenStart(e: MouseEvent|TouchEvent) { _listenMoveStart(e: MouseEvent|TouchEvent) {
e.preventDefault(); e.preventDefault();
this._isPainting = true; const p = this._getPosition(e);
if (typeof this._onMoveStart === 'function') { if (this._isVaildPoint(p)) {
const p = this._getPosition(e); if (this._event.has('point')) {
if (this._isVaildPoint(p)) { this._event.trigger('point', p);
this._onMoveStart(p); }
if (this._event.has('moveStart')) {
this._event.trigger('moveStart', p);
} }
} }
this._isMoving = true;
} }
_listenMove(e: MouseEvent|TouchEvent) { _listenMove(e: MouseEvent|TouchEvent) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (this._isPainting === true) { if (this._event.has('move') && this._isMoving === true) {
if (typeof this._onMove === 'function') { const p = this._getPosition(e);
const p = this._getPosition(e); if (this._isVaildPoint(p)) {
if (this._isVaildPoint(p)) { this._event.trigger('move', p);
this._onMove(p);
}
} }
} }
} }
_listenEnd(e: MouseEvent|TouchEvent) { _listenMoveEnd(e: MouseEvent|TouchEvent) {
e.preventDefault(); e.preventDefault();
this._isPainting = false; if (this._event.has('moveEnd')) {
if (typeof this._onMoveEnd === 'function') {
const p = this._getPosition(e); const p = this._getPosition(e);
if (this._isVaildPoint(p)) { if (this._isVaildPoint(p)) {
this._onMoveEnd(p); this._event.trigger('moveEnd', p);
} }
} }
this._isMoving = false;
} }
_getPosition(e: MouseEvent|TouchEvent) { _getPosition(e: MouseEvent|TouchEvent) {