import { Transform } from "konva/lib/Util"; import mitt from 'mitt' import { alignPortMat, Pos } from "./math"; import { MathUtils } from "three"; export type ViewerProps = { size?: number[]; bound?: number[]; padding: number | number[]; retain: boolean; }; export class Viewer { props: ViewerProps; viewMat: Transform; partMat: Transform = new Transform(); bus = mitt<{ transformChange: Transform }>() constructor(props: Partial = {}) { this.props = { padding: 0, retain: true, ...props, } this.viewMat = new Transform(); } get bound() { return this.props.bound } setBound(bound: number[], size?: number[], padding?: number | number[], retain?: boolean) { this.props.bound = bound if (padding) { this.props.padding = padding } if (retain) { this.props.retain = retain } if (size) { this.props.size = size } padding = this.props.padding retain = this.props.retain size = this.props.size if (!size) { throw '缺少视窗size' } this.partMat = alignPortMat( [ {x: bound[0], y: bound[1]}, {x: bound[2], y: bound[3]}, ], [ {x: 0, y: 0}, {x: size[0], y: size[1]}, ], retain, typeof padding === "number" ? padding : {x: padding[0], y: padding[1]} ); } move(position: Pos, initMat = this.viewMat) { this.mutMat(new Transform().translate(position.x, position.y), initMat); } movePixel(position: Pos, initMat = this.viewMat) { if (isNaN(position.x) || isNaN(position.y)) { console.error(`无效移动位置${position.x} ${position.y}`) return; } const offsetX = position.x const currentX = this.viewMat.decompose().x const finX = currentX + offsetX const x = finX - currentX const mat = initMat.copy().invert() const p1 = mat.point({x: 0, y: 0}) const p2 = mat.point({x, y: position.y}) this.move({x: p2.x - p1.x, y: p2.y - p1.y}) // const info = initMat.decompose() // const tf = new Transform() // tf.rotate(info.rotation) // tf.scale(info.scaleX, info.scaleY) // this.move(tf.invert().point(position), this.viewMat) } scale(center: Pos, scale: Pos, initMat = this.viewMat) { const base = initMat.decompose().scaleX if (base * scale.x < 0.001 || base * scale.x > 1000) { console.error('缩放范围0.001~1000 已超过范围无法缩放') return; } if (isNaN(center.x) || isNaN(center.y)) { console.error(`无效中心点${center.x} ${center.y}`) return; } this.mutMat( new Transform() .translate(center.x, center.y) .multiply( new Transform() .scale(scale.x, scale.y) .multiply(new Transform().translate(-center.x, -center.y)) ), initMat ); } scalePixel(center: Pos, scale: Pos, initMat = this.viewMat) { const pos = initMat.copy().invert().point(center) this.scale(pos, scale, initMat) } rotate(center: Pos, angleRad: number, initMat = this.viewMat) { this.mutMat( new Transform() .translate(center.x, center.y) .multiply( new Transform() .rotate(angleRad) .multiply(new Transform().translate(-center.x, -center.y)) ), initMat ); } rotatePixel(center: Pos, angleRad: number, initMat = this.viewMat) { const pos = initMat.copy().invert().point(center) this.rotate(pos, angleRad, initMat) } mutMat(mat: Transform, initMat = this.viewMat) { // this.setViewMat(mat.copy().multiply(initMat)) this.setViewMat(initMat.copy().multiply(mat)) } setViewMat(mat: number[] | Transform) { if (mat instanceof Transform) { this.viewMat = mat.copy(); } else { this.viewMat = new Transform(mat) } let dec = this.viewMat.decompose() if (dec.x > 10) { dec.x = 10 this.viewMat = new Transform() .translate(dec.x, dec.y) .scale(dec.scaleX, dec.scaleY) .rotate(MathUtils.degToRad(dec.rotation)) } // while(dec.x > 0.01) { // console.log(dec.x) // this.viewMat = this.viewMat.copy().translate(-dec.x, 0) // dec = this.viewMat.decompose() // } this.bus.emit('transformChange', this.transform) } get transform() { return this.partMat.copy().multiply(this.viewMat); } get current() { return this.viewMat.decompose() } }