refactor: @idraw/core add screen

This commit is contained in:
chenshenhai 2021-06-27 13:22:56 +08:00
parent 1c6986acb6
commit 83ecc22a7e
5 changed files with 245 additions and 115 deletions

View file

@ -1,9 +1,9 @@
# @idraw/core
* [] FireFox's Compatibility Question (And Safair Browser)
* [x] FireFox's Compatibility Question (And Safair Browser)
* [] Area select
* [] Listen keyboard action
* [] Hover element style
* [x] Hover element style
* [] Keep all num two decimals
* [] Get center point at screen
* [x] Cursor style

View file

@ -0,0 +1,94 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<style>
html,body { margin: 0; padding: 0; }
#mount canvas {
margin-top: 40px;
margin-left: 50px;
border: 1px solid #aaaaaa40;
/* border-right: 1px solid #aaaaaa40;
border-bottom: 1px solid #aaaaaa40; */
background-image:
linear-gradient(#aaaaaa40 1px, transparent 0),
linear-gradient(90deg, #aaaaaa40 1px, transparent 0),
linear-gradient(#aaa 1px, transparent 0),
linear-gradient(90deg, #aaa 1px, transparent 0);
background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px;
}
</style>
</head>
<body>
<div id="mount"></div>
<script src="./../../dist/index.global.js"></script>
<script>
const { Board } = window.iDraw;
const mount = document.querySelector('#mount');
const opts = {
width: 600,
height: 400,
contextWidth: 1000,
contextHeight: 900,
devicePixelRatio: 4,
canScroll: true,
scrollConfig: {
color: '#666666',
lineWidth: 16
}
}
const board = new Board(mount, opts);
// board.on('wheelX', (deltaX) => {
// console.log('deltaX =', deltaX);
// })
// board.on('wheelY', (deltaY) => {
// console.log('deltaY =', deltaY);
// })
const ctx = board.getContext();
// ctx.setFillStyle('#ffffff');
// ctx.fillRect(0, 0, opts.contextWidth, opts.contextHeight);
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(260, 260, 200, 100);
ctx.setFillStyle('#e0e0e0');
ctx.fillRect(500 - 10, 500 - 10, 200, 100);
ctx.setFillStyle('#c0c0c0');
ctx.fillRect(600, 600, 200, 100);
ctx.setFillStyle('#cccccc');
ctx.fillRect(790, 790, 200, 100);
ctx.setFillStyle('#000');
ctx.fillRect(390, 340, 20, 20);
// board.scale(1.5);
board.scrollX(-100);
board.scrollY(-150);
// board.scale(1);
// const result = board.scale(1);
const result = board.scale(1);
console.log('result =', result);
board.draw();
console.log('scrollLineWidth = ', board.getScrollLineWidth())
</script>
</body>
</html>

View file

@ -7,10 +7,12 @@ import { setStyle } from './lib/style';
import Context from './lib/context';
import { TypeBoardEventArgMap } from './lib/event';
import { Scroller } from './lib/scroller';
import { Screen } from './lib/screen';
import {
_canvas, _displayCanvas, _mount, _opts, _hasRendered, _ctx, _displayCtx,
_originCtx, _watcher, _render, _calcScreen, _parsePrivateOptions, _scroller,
_initEvent, _calcScreenScroll, _doScrollX, _doScrollY, _doMoveScroll, _resetContext,
_originCtx, _watcher, _render, _parsePrivateOptions, _scroller,
_initEvent, _doScrollX, _doScrollY, _doMoveScroll, _resetContext,
_screen,
} from './names';
const { throttle } = util.time;
@ -30,6 +32,7 @@ class Board {
private [_originCtx]: CanvasRenderingContext2D;
private [_watcher]: Watcher;
private [_scroller]: Scroller;
private [_screen]: Screen;
constructor(mount: HTMLDivElement, opts: TypeBoardOptions) {
this[_mount] = mount;
@ -40,6 +43,7 @@ class Board {
this[_originCtx] = this[_canvas].getContext('2d') as CanvasRenderingContext2D;
this[_displayCtx] = this[_displayCanvas].getContext('2d') as CanvasRenderingContext2D;
this[_ctx] = new Context(this[_originCtx], this[_opts]);
this[_screen] = new Screen(this[_ctx], this[_opts]);
this[_watcher] = new Watcher(this[_displayCanvas]);
this[_scroller] = new Scroller(
this[_displayCtx], {
@ -82,7 +86,7 @@ class Board {
if (scaleRatio > 0) {
this[_ctx].setTransform({ scale: scaleRatio });
}
const { position, size } = this[_calcScreen]();
const { position, size } = this[_screen].calcScreen();
return { position, size};
}
@ -90,7 +94,7 @@ class Board {
if (x >= 0 || x < 0) {
this[_ctx].setTransform({ scrollX: x });
}
const { position, size } = this[_calcScreen]();
const { position, size } = this[_screen].calcScreen();
return { position, size};
}
@ -98,7 +102,7 @@ class Board {
if (y >= 0 || y < 0) {
this[_ctx].setTransform({ scrollY: y });
}
const { position, size } = this[_calcScreen]();
const { position, size } = this[_screen].calcScreen();
return { position, size};
}
@ -108,7 +112,7 @@ class Board {
draw(): TypeScreenContext {
this.clear();
const { position, deviceSize, size } = this[_calcScreen]();
const { position, deviceSize, size } = this[_screen].calcScreen();
this[_displayCtx].drawImage(
this[_canvas], deviceSize.x, deviceSize.y, deviceSize.w, deviceSize.h
);
@ -134,7 +138,7 @@ class Board {
size: TypeScreenSize, position: TypeScreenPosition, deviceSize: TypeScreenSize,
width: number, height: number, devicePixelRatio: number
} {
return this[_calcScreen]();
return this[_screen].calcScreen();
}
setCursor(cursor: TypePointCursor) {
@ -148,7 +152,8 @@ class Board {
resetSize(opts: TypeBoardSizeOptions) {
this[_opts] = { ...this[_opts], ...opts };
this[_resetContext]();
this[_ctx].resetSize(opts)
this[_ctx].resetSize(opts);
this[_screen].resetSize(opts);
this[_scroller].resetSize({
width: this[_opts].width,
height: this[_opts].height,
@ -194,87 +199,6 @@ class Board {
};
return { ...defaultOpts, ...opts };
}
private [_calcScreen](): {
size: TypeScreenSize, position: TypeScreenPosition, deviceSize: TypeScreenSize,
width: number, height: number, devicePixelRatio: number
} {
const scaleRatio = this[_ctx].getTransform().scale;
const {
width, height, contextWidth, contextHeight,
devicePixelRatio: pxRatio,
} = this[_opts];
// init scroll
if (contextWidth * scaleRatio <= width) {
// make context center
this[_ctx].setTransform({
scrollX: (width - contextWidth * scaleRatio) / 2,
})
}
if (contextHeight * scaleRatio <= height) {
// make context center
this[_ctx].setTransform({
scrollY: (height - contextHeight * scaleRatio) / 2,
})
}
if (contextWidth * scaleRatio >= width && this[_ctx].getTransform().scrollX > 0) {
this[_ctx].setTransform({
scrollX: 0,
})
}
if (contextHeight * scaleRatio >= height && this[_ctx].getTransform().scrollY > 0) {
this[_ctx].setTransform({
scrollY: 0,
})
}
const { scrollX: _scrollX, scrollY: _scrollY } = this[_ctx].getTransform();
// reset scroll
if (_scrollX < 0 && Math.abs(_scrollX) > Math.abs(contextWidth * scaleRatio - width)) {
this[_ctx].setTransform({
scrollX: 0 - Math.abs(contextWidth * scaleRatio - width)
})
}
if (_scrollY < 0 && Math.abs(_scrollY) > Math.abs(contextHeight * scaleRatio - height)) {
this[_ctx].setTransform({
scrollY: 0 - Math.abs(contextHeight * scaleRatio - height)
})
}
// result size
const { scrollX, scrollY } = this[_ctx].getTransform();
const size = {
x: scrollX * scaleRatio,
y: scrollY * scaleRatio,
w: contextWidth * scaleRatio,
h: contextHeight * scaleRatio,
};
const deviceSize = {
x: scrollX * pxRatio,
y: scrollY * pxRatio,
w: contextWidth * pxRatio * scaleRatio,
h: contextHeight * pxRatio * scaleRatio,
};
const position = {
top: scrollY,
bottom: height - (contextHeight * scaleRatio + scrollY),
left: scrollX,
right: width - (contextWidth * scaleRatio + scrollX),
};
return {
size,
position,
deviceSize,
width: this[_opts].width,
height: this[_opts].height,
devicePixelRatio: this[_opts].devicePixelRatio,
};
}
private [_initEvent]() {
if (this[_hasRendered] === true) {
@ -313,30 +237,15 @@ class Board {
}
}
private [_calcScreenScroll]( start: number, end: number, sliderSize: number, limitLen: number, moveDistance: number
): number {
let scrollDistance = start;
let scrollLen = limitLen - sliderSize;
if (start <= 0 && end <= 0) {
scrollLen = Math.abs(start) + Math.abs(end);
}
let unit = 1;
if (scrollLen > 0) {
unit = scrollLen / (limitLen - sliderSize);
}
scrollDistance = 0 - unit * moveDistance;
return scrollDistance;
}
private [_doScrollX](dx: number, prevScrollX?: number) {
const { width } = this[_opts];
let scrollX = prevScrollX;
if (!(typeof scrollX === 'number' && (scrollX > 0 || scrollX <= 0))) {
scrollX = this[_ctx].getTransform().scrollX
}
const { position } = this[_calcScreen]();
const { position } = this[_screen].calcScreen();
const { xSize } = this[_scroller].calc(position);
const moveX = this[_calcScreenScroll](position.left, position.right, xSize, width, dx);
const moveX = this[_screen].calcScreenScroll(position.left, position.right, xSize, width, dx);
this.scrollX(scrollX + moveX);
this.draw();
}
@ -347,9 +256,9 @@ class Board {
if (!(typeof scrollY === 'number' && (scrollY > 0 || scrollY <= 0))) {
scrollY = this[_ctx].getTransform().scrollY
}
const { position } = this[_calcScreen]();
const { position } = this[_screen].calcScreen();
const { ySize } = this[_scroller].calc(position);
const moveY = this[_calcScreenScroll](position.top, position.bottom, ySize, height, dy);
const moveY = this[_screen].calcScreenScroll(position.top, position.bottom, ySize, height, dy);
this.scrollY(scrollY + moveY);
this.draw();
}
@ -358,7 +267,7 @@ class Board {
if (!scrollType) {
return;
}
const { position } = this[_calcScreen]();
const { position } = this[_screen].calcScreen();
const { xSize, ySize } = this[_scroller].calc(position);
if (scrollType === 'x') {
this[_doScrollX](point.x - xSize / 2, 0);

View file

@ -0,0 +1,127 @@
import {
TypeBoardSizeOptions, TypeScreenPosition,
TypeContext, TypeScreenSize,
} from '@idraw/types';
type Options = {
width: number;
height: number;
contextWidth: number;
contextHeight: number;
devicePixelRatio: number;
}
const _opts = Symbol('_opts');
const _ctx = Symbol('_ctx')
export class Screen {
private [_opts]: Options;
private [_ctx]: TypeContext;
constructor(ctx: TypeContext, opts: Options) {
this[_opts] = opts;
this[_ctx] = ctx;
}
resetSize(opts: TypeBoardSizeOptions) {
this[_opts] = {...this[_opts], ...opts}
}
calcScreen(): {
size: TypeScreenSize, position: TypeScreenPosition, deviceSize: TypeScreenSize,
width: number, height: number, devicePixelRatio: number
} {
const scaleRatio = this[_ctx].getTransform().scale;
const {
width, height, contextWidth, contextHeight,
devicePixelRatio: pxRatio,
} = this[_opts];
// init scroll
if (contextWidth * scaleRatio <= width) {
// make context center
this[_ctx].setTransform({
scrollX: (width - contextWidth * scaleRatio) / 2,
})
}
if (contextHeight * scaleRatio <= height) {
// make context center
this[_ctx].setTransform({
scrollY: (height - contextHeight * scaleRatio) / 2,
})
}
if (contextWidth * scaleRatio >= width && this[_ctx].getTransform().scrollX > 0) {
this[_ctx].setTransform({
scrollX: 0,
})
}
if (contextHeight * scaleRatio >= height && this[_ctx].getTransform().scrollY > 0) {
this[_ctx].setTransform({
scrollY: 0,
})
}
const { scrollX: _scrollX, scrollY: _scrollY } = this[_ctx].getTransform();
// reset scroll
if (_scrollX < 0 && Math.abs(_scrollX) > Math.abs(contextWidth * scaleRatio - width)) {
this[_ctx].setTransform({
scrollX: 0 - Math.abs(contextWidth * scaleRatio - width)
})
}
if (_scrollY < 0 && Math.abs(_scrollY) > Math.abs(contextHeight * scaleRatio - height)) {
this[_ctx].setTransform({
scrollY: 0 - Math.abs(contextHeight * scaleRatio - height)
})
}
// result size
const { scrollX, scrollY } = this[_ctx].getTransform();
const size = {
x: scrollX * scaleRatio,
y: scrollY * scaleRatio,
w: contextWidth * scaleRatio,
h: contextHeight * scaleRatio,
};
const deviceSize = {
x: scrollX * pxRatio,
y: scrollY * pxRatio,
w: contextWidth * pxRatio * scaleRatio,
h: contextHeight * pxRatio * scaleRatio,
};
const position = {
top: scrollY,
bottom: height - (contextHeight * scaleRatio + scrollY),
left: scrollX,
right: width - (contextWidth * scaleRatio + scrollX),
};
return {
size,
position,
deviceSize,
width: this[_opts].width,
height: this[_opts].height,
devicePixelRatio: this[_opts].devicePixelRatio,
};
}
calcScreenScroll( start: number, end: number, sliderSize: number, limitLen: number, moveDistance: number
): number {
let scrollDistance = start;
let scrollLen = limitLen - sliderSize;
if (start <= 0 && end <= 0) {
scrollLen = Math.abs(start) + Math.abs(end);
}
let unit = 1;
if (scrollLen > 0) {
unit = scrollLen / (limitLen - sliderSize);
}
scrollDistance = 0 - unit * moveDistance;
return scrollDistance;
}
}

View file

@ -8,18 +8,18 @@ const _displayCtx = Symbol('_displayCtx');
const _originCtx = Symbol('_originCtx');
const _watcher = Symbol('_watcher');
const _render = Symbol('_render');
const _calcScreen = Symbol('_calcScreen');
const _parsePrivateOptions = Symbol('_parsePrivateOptions');
const _scroller = Symbol('_scroller');
const _initEvent = Symbol('_initEvent');
const _calcScreenScroll = Symbol('_calcScreenScroll');
const _doScrollX = Symbol('_doScrollX');
const _doScrollY = Symbol('_doScrollY');
const _doMoveScroll = Symbol('_doMoveScroll');
const _resetContext = Symbol('_resetContext');
const _screen = Symbol('_screen');
export {
_canvas, _displayCanvas, _mount, _opts, _hasRendered, _ctx, _displayCtx,
_originCtx, _watcher, _render, _calcScreen, _parsePrivateOptions, _scroller,
_initEvent, _calcScreenScroll, _doScrollX, _doScrollY, _doMoveScroll, _resetContext,
_originCtx, _watcher, _render, _parsePrivateOptions, _scroller,
_initEvent, _doScrollX, _doScrollY, _doMoveScroll, _resetContext,
_screen,
}