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

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');
let hasInited = false;
export function onScale(board) {
export function doScale(board) {
if (hasInited === true) return;
input.addEventListener('change', () => {
const val = input.value * 1;

View file

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

View file

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

View file

@ -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<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() {
if (this._hasRendered === true) {
return;
@ -105,7 +115,6 @@ class Board {
return size;
}
}
export default Board;

View file

@ -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) {

View file

@ -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<T extends keyof TypeBoardEventArgMap >(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<T extends keyof TypeBoardEventArgMap >(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) {