|
@@ -1,156 +1,138 @@
|
|
|
import { Transform } from "konva/lib/Util";
|
|
|
-import { Pos } from "../utils/math.ts";
|
|
|
+import { Pos, Size } from "../utils/math.ts";
|
|
|
import { alignPortMat } from "@/utils/align-port.ts";
|
|
|
-import mitt from 'mitt'
|
|
|
-
|
|
|
-export type ViewerProps = {
|
|
|
- size?: number[];
|
|
|
- bound?: number[];
|
|
|
- padding: number | number[];
|
|
|
- retain: boolean;
|
|
|
-};
|
|
|
+import mitt from "mitt";
|
|
|
+import { IRect } from "konva/lib/types";
|
|
|
+import { MathUtils } from "three";
|
|
|
|
|
|
export class Viewer {
|
|
|
- props: ViewerProps;
|
|
|
- viewMat: Transform;
|
|
|
- partMat: Transform = new Transform();
|
|
|
- bus = mitt<{ transformChange: Transform }>()
|
|
|
-
|
|
|
- constructor(props: Partial<ViewerProps> = {}) {
|
|
|
- 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 mat = initMat.copy().invert()
|
|
|
- const p1 = mat.point({x: 0, y: 0})
|
|
|
- const p2 = mat.point(position)
|
|
|
- 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: number, initMat = this.viewMat) {
|
|
|
- const base = initMat.decompose().scaleX
|
|
|
- if (base * scale < 0.001 || base * scale > 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, scale)
|
|
|
- .multiply(new Transform().translate(-center.x, -center.y))
|
|
|
- ),
|
|
|
- initMat
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- scalePixel(center: Pos, scale: number, 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)
|
|
|
- }
|
|
|
- this.bus.emit('transformChange', this.transform)
|
|
|
- }
|
|
|
-
|
|
|
- get transform() {
|
|
|
- return this.partMat.copy().multiply(this.viewMat);
|
|
|
- }
|
|
|
- get current() {
|
|
|
- return this.viewMat.decompose()
|
|
|
- }
|
|
|
-}
|
|
|
+ size?: Size;
|
|
|
+ viewMat: Transform;
|
|
|
+ bus = mitt<{ transformChange: Transform }>();
|
|
|
+
|
|
|
+ constructor() {
|
|
|
+ this.viewMat = new Transform();
|
|
|
+ }
|
|
|
+
|
|
|
+ setSize(size: Size) {
|
|
|
+ this.size = size;
|
|
|
+ }
|
|
|
+
|
|
|
+ setBound({
|
|
|
+ targetBound,
|
|
|
+ size,
|
|
|
+ padding = 0,
|
|
|
+ }: {
|
|
|
+ targetBound: IRect;
|
|
|
+ size?: Size;
|
|
|
+ padding?: number;
|
|
|
+ }) {
|
|
|
+ size = size || this.size;
|
|
|
+ if (!size) {
|
|
|
+ throw "size属性未设置";
|
|
|
+ }
|
|
|
+
|
|
|
+ const selfBound = {
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ width: size.width - padding * 2,
|
|
|
+ height: size.height - padding * 2,
|
|
|
+ };
|
|
|
+ const mat = new Transform()
|
|
|
+ .translate(padding, padding)
|
|
|
+ .multiply(alignPortMat(selfBound, targetBound, true));
|
|
|
+
|
|
|
+ const rotate = this.viewMat.decompose().rotation
|
|
|
+ this.setViewMat(mat);
|
|
|
+ this.rotatePixel({x: size.width / 2, y: size.height / 2}, MathUtils.degToRad(rotate))
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 mat = initMat.copy().invert();
|
|
|
+ const p1 = mat.point({ x: 0, y: 0 });
|
|
|
+ const p2 = mat.point(position);
|
|
|
+ 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: number, initMat = this.viewMat) {
|
|
|
+ const base = initMat.decompose().scaleX;
|
|
|
+ if (base * scale < 0.001 || base * scale > 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, scale)
|
|
|
+ .multiply(new Transform().translate(-center.x, -center.y))
|
|
|
+ ),
|
|
|
+ initMat
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ scalePixel(center: Pos, scale: number, 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);
|
|
|
+ }
|
|
|
+ this.bus.emit("transformChange", this.transform);
|
|
|
+ }
|
|
|
+
|
|
|
+ get transform() {
|
|
|
+ return this.viewMat.copy();
|
|
|
+ }
|
|
|
+ get current() {
|
|
|
+ return this.viewMat.decompose();
|
|
|
+ }
|
|
|
+}
|