mirror of
https://github.com/idrawjs/idraw
synced 2026-05-23 17:48:23 +00:00
refactor: @idraw/core add screen
This commit is contained in:
parent
1c6986acb6
commit
83ecc22a7e
5 changed files with 245 additions and 115 deletions
|
|
@ -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
|
||||
|
|
|
|||
94
packages/board/examples/test/get-screen-center.html
Normal file
94
packages/board/examples/test/get-screen-center.html
Normal 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>
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
127
packages/board/src/lib/screen.ts
Normal file
127
packages/board/src/lib/screen.ts
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
Loading…
Reference in a new issue