mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 10:08:34 +00:00
refactor: refactor calculator
This commit is contained in:
parent
7fdd24a765
commit
f4ebe720a4
4 changed files with 32 additions and 149 deletions
|
|
@ -1,14 +1,5 @@
|
|||
import type { Data, Point, Element, ElementType, ViewCalculator, ViewCalculatorOptions, ViewScaleInfo, ElementSize, ViewSizeInfo } from '@idraw/types';
|
||||
import {
|
||||
rotateElementVertexes,
|
||||
checkRectIntersect,
|
||||
viewScale,
|
||||
viewScroll,
|
||||
calcElementSize,
|
||||
isViewPointInElement,
|
||||
getViewPointAtElement,
|
||||
isElementInView
|
||||
} from '@idraw/util';
|
||||
import { calcElementSize, isViewPointInElement, getViewPointAtElement, isElementInView } from '@idraw/util';
|
||||
|
||||
export class Calculator implements ViewCalculator {
|
||||
private _opts: ViewCalculatorOptions;
|
||||
|
|
@ -17,135 +8,31 @@ export class Calculator implements ViewCalculator {
|
|||
this._opts = opts;
|
||||
}
|
||||
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
const scale = viewScaleInfo.scale;
|
||||
const { moveX, moveY } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = viewScaleInfo.offsetLeft;
|
||||
let offsetRight = viewScaleInfo.offsetRight;
|
||||
let offsetTop = viewScaleInfo.offsetTop;
|
||||
let offsetBottom = viewScaleInfo.offsetBottom;
|
||||
if (moveX !== undefined && (moveX > 0 || moveX <= 0)) {
|
||||
if (contextWidth * scale < width) {
|
||||
offsetLeft = offsetRight = (width - contextWidth * scale) / 2;
|
||||
} else if (contextWidth * scale > width) {
|
||||
if (offsetLeft + moveX >= 0) {
|
||||
offsetLeft = 0;
|
||||
offsetRight = width - contextWidth * scale;
|
||||
} else if (offsetLeft + moveX < width - contextWidth * scale) {
|
||||
offsetLeft = width - contextWidth * scale;
|
||||
offsetRight = 0;
|
||||
} else {
|
||||
offsetLeft += moveX;
|
||||
offsetRight = width - contextWidth * scale - offsetLeft;
|
||||
}
|
||||
} else {
|
||||
offsetLeft = offsetRight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (moveY !== undefined && (moveY > 0 || moveY <= 0)) {
|
||||
if (contextHeight * scale < height) {
|
||||
offsetTop = offsetBottom = (height - contextHeight * scale) / 2;
|
||||
} else if (contextHeight * scale > height) {
|
||||
if (offsetTop + moveY >= 0) {
|
||||
offsetTop = 0;
|
||||
offsetBottom = height - contextHeight * scale;
|
||||
} else if (offsetTop + moveY < height - contextHeight * scale) {
|
||||
offsetTop = height - contextHeight * scale;
|
||||
offsetBottom = 0;
|
||||
} else {
|
||||
offsetTop += moveY;
|
||||
offsetBottom = height - contextHeight * scale - offsetTop;
|
||||
}
|
||||
} else {
|
||||
offsetTop = offsetBottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
scale,
|
||||
offsetTop,
|
||||
offsetLeft,
|
||||
offsetRight,
|
||||
offsetBottom
|
||||
};
|
||||
}
|
||||
|
||||
elementSize(size: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize {
|
||||
const { x, y, w, h, angle } = size;
|
||||
const { contextX = 0, contextY = 0 } = viewSizeInfo;
|
||||
const { scale, offsetTop, offsetLeft } = viewScaleInfo;
|
||||
|
||||
const newSize = {
|
||||
x: x * scale + offsetLeft - contextX,
|
||||
y: y * scale + offsetTop - contextY,
|
||||
w: w * scale,
|
||||
h: h * scale,
|
||||
angle
|
||||
};
|
||||
|
||||
return newSize;
|
||||
return calcElementSize(size, { viewScaleInfo, viewSizeInfo });
|
||||
}
|
||||
|
||||
isElementInView(elem: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean {
|
||||
const { width, height } = viewSizeInfo;
|
||||
const { angle } = elem;
|
||||
const { x, y, w, h } = this.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
const ves = rotateElementVertexes({ x, y, w, h, angle });
|
||||
const viewSize = { x: 0, y: 0, w: width, h: height };
|
||||
|
||||
const elemStartX = Math.min(ves[0].x, ves[1].x, ves[2].x, ves[3].x);
|
||||
const elemStartY = Math.min(ves[0].y, ves[1].y, ves[2].y, ves[3].y);
|
||||
const elemEndX = Math.max(ves[0].x, ves[1].x, ves[2].x, ves[3].x);
|
||||
const elemEndY = Math.max(ves[0].y, ves[1].y, ves[2].y, ves[3].y);
|
||||
const elemSize = { x: elemStartX, y: elemStartY, w: elemEndX - elemStartX, h: elemEndY - elemStartY };
|
||||
return checkRectIntersect(viewSize, elemSize);
|
||||
return isElementInView(elem, { viewScaleInfo, viewSizeInfo });
|
||||
}
|
||||
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean {
|
||||
const ctx = this._opts.viewContent.boardContext;
|
||||
const { angle = 0 } = elem;
|
||||
const { x, y, w, h } = this.elementSize(elem, viewScaleInfo, viewSize);
|
||||
const vertexes = rotateElementVertexes({ x, y, w, h, angle });
|
||||
if (vertexes.length >= 2) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vertexes[0].x, vertexes[0].y);
|
||||
for (let i = 1; i < vertexes.length; i++) {
|
||||
ctx.lineTo(vertexes[i].x, vertexes[i].y);
|
||||
}
|
||||
ctx.closePath();
|
||||
}
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean {
|
||||
const context2d = this._opts.viewContent.boardContext;
|
||||
return isViewPointInElement(p, {
|
||||
context2d,
|
||||
element: elem,
|
||||
viewScaleInfo,
|
||||
viewSizeInfo
|
||||
});
|
||||
}
|
||||
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> } {
|
||||
const result: { index: number; element: null | Element<ElementType> } = {
|
||||
index: -1,
|
||||
element: null
|
||||
};
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const elem = data.elements[i];
|
||||
if (this.isPointInElement(p, elem, viewScaleInfo, viewSize)) {
|
||||
result.index = i;
|
||||
result.element = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): { index: number; element: null | Element<ElementType> } {
|
||||
const context2d = this._opts.viewContent.boardContext;
|
||||
return getViewPointAtElement(p, {
|
||||
data,
|
||||
context2d,
|
||||
viewScaleInfo,
|
||||
viewSizeInfo
|
||||
});
|
||||
}
|
||||
|
||||
// rotateElementSize(elemSize: ElementSize): PointSize[] {
|
||||
// // const { x, y, w, h, angle = 0 } = elemSize;
|
||||
// // const pointSizes: PointSize[] = [];
|
||||
// return [];
|
||||
// }
|
||||
|
||||
// pointToViewPoint(p: Point): Point {
|
||||
// // TODO
|
||||
// return {};
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EventEmitter, viewScale } from '@idraw/util';
|
||||
import { EventEmitter, viewScale, viewScroll } from '@idraw/util';
|
||||
import type { BoardViewer, BoardViewerEventMap, BoardViewerOptions, ActiveStore, BoardViewerFrameSnapshot, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
|
||||
|
||||
const { requestAnimationFrame } = window;
|
||||
|
|
@ -93,26 +93,26 @@ export class Viewer extends EventEmitter<BoardViewerEventMap> implements BoardVi
|
|||
const { sharer, renderer } = this._opts;
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const viewScaleInfo = viewScale(num, { prevViewScaleInfo, viewSizeInfo });
|
||||
const viewScaleInfo = viewScale({ num, prevViewScaleInfo, viewSizeInfo });
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
renderer.scale(num);
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
scrollX(num: number): ViewScaleInfo {
|
||||
const { sharer, calculator } = this._opts;
|
||||
const { sharer } = this._opts;
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const viewScaleInfo = calculator.viewScroll({ moveX: num - (prevViewScaleInfo.offsetLeft || 0) }, prevViewScaleInfo, viewSizeInfo);
|
||||
const viewScaleInfo = viewScroll({ moveX: num - (prevViewScaleInfo.offsetLeft || 0), viewScaleInfo: prevViewScaleInfo, viewSizeInfo });
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
scrollY(num: number): ViewScaleInfo {
|
||||
const { sharer, calculator } = this._opts;
|
||||
const { sharer } = this._opts;
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const viewScaleInfo = calculator.viewScroll({ moveY: num - (prevViewScaleInfo.offsetTop || 0) }, prevViewScaleInfo, viewSizeInfo);
|
||||
const viewScaleInfo = viewScroll({ moveY: num - (prevViewScaleInfo.offsetTop || 0), viewScaleInfo: prevViewScaleInfo, viewSizeInfo });
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,8 @@ export interface ViewCalculatorOptions {
|
|||
}
|
||||
|
||||
export interface ViewCalculator {
|
||||
// viewScale(num: number, prevScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): ViewScaleInfo;
|
||||
isElementInView(elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean;
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean;
|
||||
elementSize(size: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize;
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo;
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { Point, Data, ViewScaleInfo, ViewSizeInfo, Element, ElementType, ElementSize } from '@idraw/types';
|
||||
import { Point, Data, ViewScaleInfo, ViewSizeInfo, Element, ElementType, ElementSize, ViewContext2D } from '@idraw/types';
|
||||
import { rotateElementVertexes } from './rotate';
|
||||
import { Context2D } from './context2d';
|
||||
import { checkRectIntersect } from './rect';
|
||||
|
||||
export function viewScale(num: number, opts: { prevViewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ViewScaleInfo {
|
||||
const scale = num;
|
||||
const { prevViewScaleInfo, viewSizeInfo } = opts;
|
||||
export function viewScale(opts: { num: number; prevViewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ViewScaleInfo {
|
||||
const { num: scale, prevViewScaleInfo, viewSizeInfo } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = 0;
|
||||
let offsetRight = 0;
|
||||
|
|
@ -39,9 +37,9 @@ export function viewScale(num: number, opts: { prevViewScaleInfo: ViewScaleInfo;
|
|||
};
|
||||
}
|
||||
|
||||
export function viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
export function viewScroll(opts: { moveX?: number; moveY?: number; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ViewScaleInfo {
|
||||
const { moveX, moveY, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const scale = viewScaleInfo.scale;
|
||||
const { moveX, moveY } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = viewScaleInfo.offsetLeft;
|
||||
let offsetRight = viewScaleInfo.offsetRight;
|
||||
|
|
@ -113,7 +111,7 @@ export function calcElementSize(size: ElementSize, opts: { viewScaleInfo: ViewSc
|
|||
|
||||
export function isViewPointInElement(
|
||||
p: Point,
|
||||
opts: { context2d: Context2D; element: Element<ElementType>; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
opts: { context2d: ViewContext2D; element: Element<ElementType>; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
): boolean {
|
||||
const { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo } = opts;
|
||||
|
||||
|
|
@ -137,7 +135,7 @@ export function isViewPointInElement(
|
|||
export function getViewPointAtElement(
|
||||
p: Point,
|
||||
opts: {
|
||||
context2d: Context2D;
|
||||
context2d: ViewContext2D;
|
||||
data: Data;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
|
|
|
|||
Loading…
Reference in a new issue