import { Matrix, matrixMutiply, getTranslateMatrix, getScaleMatrix, getMirrorMatrix, pointMultiplyMatrix, getInverseMatrix, } from '../utils/matrix'; interface Point { x: number; y: number; } interface Area { height: number; width: number; } interface CanvasRect { x: number; y: number; width: number; height: number; } // eslint-disable-next-line import/no-mutable-exports export class Coordinate { public origin: Point; // 坐标原点 private pointMatrix: Matrix; private scaleMatrix: Matrix; private coreArea: Area; // 核心绘图区域 private inverseMatrix: Matrix; constructor( private source: CanvasRect, private target: CanvasRect, ) { this.source = source; this.target = target; this.setupMappingMatrix(); } /** * 坐标映射 * @param point 待映射(直角坐标系) * @returns 映射后(画布坐标系) */ public pointMapping(point: Point) { return pointMultiplyMatrix(point, this.pointMatrix); } public inverseMapping(point: Point) { return pointMultiplyMatrix(point, this.inverseMatrix); } /** * 计算坐标映射矩阵 * w3c坐标系 -> 直角坐标系 */ private setupMappingMatrix() { const { source, target } = this; // y轴翻转 const rotateMatrix = getMirrorMatrix('y'); // 平移 const xDiff = target.x - source.x; const yDiff = target.y - source.y; const translateMatrix = getTranslateMatrix(xDiff, yDiff); // 缩放[暂时不用] const yScale = target.height / source.height; const xScale = target.width / source.width; const scaleMatrix = getScaleMatrix(xScale, yScale); this.pointMatrix = matrixMutiply( translateMatrix, rotateMatrix, // scaleMatrix, ); this.inverseMatrix = getInverseMatrix(this.pointMatrix); this.scaleMatrix = scaleMatrix; } /** *【暂时不用】 * 常量缩放 * @param length 待缩放常量 * * @param axis 直角坐标方向(x:x轴,y:y轴) * @returns 缩放后常量 */ private constantScale(length: number | number[], axis: 'x' | 'y') { if (Array.isArray(length)) { return length.map(item => this.constantScale(item, axis)); } if (axis === 'x') { return length * this.scaleMatrix.data[0][0]; } return length * this.scaleMatrix.data[1][1]; // y轴翻转 } /** * 【暂时不用】 * 向量缩放 * @param length 待缩放向量长度 * @param axis 直角坐标方向(x:x轴,y:y轴) * @returns 缩放后向量 向量的方向使用+/-表示 */ private vectorScale(length: number | number[], axis: 'x' | 'y') { // 递归 if (Array.isArray(length)) { return length.map(item => this.vectorScale(item, axis)); } // 单向量缩放 if (axis === 'x') { return length * this.scaleMatrix.data[0][0]; } return length * (- this.scaleMatrix.data[1][1]); // y轴翻转 } }