diff --git a/src/pages/measure/components/MeasureAction.tsx b/src/pages/measure/components/MeasureAction.tsx
index 02f7638..efeea06 100644
--- a/src/pages/measure/components/MeasureAction.tsx
+++ b/src/pages/measure/components/MeasureAction.tsx
@@ -5,6 +5,7 @@ import { startMeasurement } from "../../../services/measure/analysis"
import { createWebSocket, sharedWsUrl } from "../../../services/socket";
import GridLayer from "./graph/GridLayer";
import StandardLayer from "./graph/StandardLayer";
+import RealtimeLayer from "./graph/RealtimeLayer";
export default function MeasureAction() {
const navigate = useNavigate();
@@ -40,12 +41,44 @@ export default function MeasureAction() {
}
return (
-
测量步骤
diff --git a/src/pages/measure/components/graph/RealtimeLayer.tsx b/src/pages/measure/components/graph/RealtimeLayer.tsx
index 4d4c794..7a34e57 100644
--- a/src/pages/measure/components/graph/RealtimeLayer.tsx
+++ b/src/pages/measure/components/graph/RealtimeLayer.tsx
@@ -1,31 +1,105 @@
-import { useCallback, useEffect, useRef } from "react";
+import { useCallback, useEffect, useRef, useState } from "react";
+import points from "../../../../utils/measure.json";
+import { createWebSocket, sharedWsUrl } from "../../../../services/socket";
+const wsClient = createWebSocket(sharedWsUrl);
+console.log(sharedWsUrl);
+
+const pointArr: { x: number; y: number }[] = [];
export default function RealtimeLayer(props: {
- width: number;
- height: number;
- leftPadding: number;
- rightPadding: number;
- topPadding: number;
- bottomPadding: number;
+ width: number;
+ height: number;
+ leftPadding: number;
+ rightPadding: number;
+ topPadding: number;
+ bottomPadding: number;
+ columns: number;
+ rows: number;
}) {
- const canvasRef = useRef(null);
- const draw = useCallback((ctx: CanvasRenderingContext2D) => {
- // 使用context对象进行绘图
- ctx.fillStyle = "skyblue"; // 设置填充颜色
- ctx.fillRect(50, 50, 150, 100); // 绘制一个矩形
- }, []);
- useEffect(() => {
- const canvas = canvasRef.current;
- if (!canvas) return;
-
- const context = canvas.getContext("2d");
- if (!context) return;
- draw(context);
- }, [draw]);
-
- return (
-
-
-
- );
+ const xStartPx = props.leftPadding;
+ const xEndPx = props.width - props.rightPadding;
+ const xStepPx = (props.width - props.leftPadding - props.rightPadding) / props.columns;
+ const yStartPx = props.topPadding;
+ // const yEndPx = props.height - props.bottomPadding;
+ const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows;
+
+ const unitPx = xStepPx / 10;
+ const pointsPx = points.map(p => ({ x: p.x * unitPx, y: p.y * unitPx + 4 })); // 特意偏移
+
+ const canvasRef = useRef(null);
+
+ const [rtPoints, setRtPoints] = useState<{ x: number; y: number }[]>([]);
+
+ // const draw = useCallback(
+ // (ctx: CanvasRenderingContext2D) => {
+ // for (let idx = 0; idx < pointsPx.length; idx++) {
+ // if (idx === 0) {
+ // ctx.moveTo(pointsPx[idx].x, pointsPx[idx].y);
+ // } else {
+ // ctx.lineTo(pointsPx[idx].x, pointsPx[idx].y);
+ // }
+ // }
+ // ctx.stroke();
+ // },
+ // [pointsPx, xEndPx, xStartPx, yStartPx, yStepPx]
+ // );
+
+ useEffect(() => {
+ const subscription = wsClient.dataOb.subscribe(data => {
+ if (data.path === "/measurement-task/get-task-state") {
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+
+ const ctx = canvas.getContext("2d");
+ if (!ctx) return;
+
+ if (data.data.event === "START_RECORD_SIG") {
+ // setRtPoints([]);
+ pointArr.length = 0;
+ console.log("-----------------------------------")
+ ctx.resetTransform();
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.strokeStyle = "blue";
+ const xOffset = (xEndPx - xStartPx) / 2;
+ const yOffset = yStepPx * 2;
+ ctx.translate(xStartPx + xOffset, yStartPx + yOffset);
+ } else if (data.data.event === "END_RECORD_SIG") {
+ //
+ }
+ } else if (data.path === "/measurement-task/profile-record-ctrl-sig") {
+ // console.log(data.data);
+ // setRtPoints(rtPoints.concat([data.data]));
+ pointArr.push(data.data);
+ console.log(pointArr.length);
+
+ const canvas = canvasRef.current;
+ if (!canvas) return;
+
+ const ctx = canvas.getContext("2d");
+ if (!ctx) return;
+
+ // ctx.clearRect(0, 0, canvas.width * 2, canvas.height * 2);
+ const pointsPx = pointArr.map(p => ({ x: p.x * unitPx, y: p.y * unitPx }));
+
+ for (let idx = 0; idx < pointsPx.length; idx++) {
+ if (idx === 0) {
+ ctx.moveTo(pointsPx[idx].x, pointsPx[idx].y);
+ } else {
+ ctx.lineTo(pointsPx[idx].x, pointsPx[idx].y);
+ }
+ }
+ // if (pointsPx.length > 1) {
+ ctx.stroke();
+ // }
+ }
+ });
+ wsClient.connect();
+ return () => subscription.unsubscribe();
+ }, [rtPoints, unitPx, xEndPx, xStartPx, yStartPx, yStepPx]);
+
+ return (
+
+
+
+ );
}
diff --git a/src/pages/measure/components/graph/StandardLayer.tsx b/src/pages/measure/components/graph/StandardLayer.tsx
index d6bed8f..ed243f0 100644
--- a/src/pages/measure/components/graph/StandardLayer.tsx
+++ b/src/pages/measure/components/graph/StandardLayer.tsx
@@ -1,8 +1,6 @@
import { useCallback, useEffect, useRef } from "react";
import { calculateCircleAbove, calculateCircleBelow } from "../../../../utils";
-const unitPx = 8;
-
const pointsR: [number, number][] = [
[0, 0],
[9.949007022412, 0.1650166186941],
@@ -21,8 +19,6 @@ const pointsL: [number, number][] = [
[-9.949007022412, 0.1650166186941],
[0, 0],
];
-const pointsRight = pointsR.map(p => [p[0] * unitPx, p[1] * unitPx]);
-const pointsLeft = pointsL.map(p => [p[0] * unitPx, p[1] * unitPx]);
export default function StandardLayer(props: {
width: number;
@@ -41,6 +37,10 @@ export default function StandardLayer(props: {
const yEndPx = props.height - props.bottomPadding;
const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows;
+ const unitPx = xStepPx / 10;
+ const pointsRight = pointsR.map(p => [p[0] * unitPx, p[1] * unitPx]);
+ const pointsLeft = pointsL.map(p => [p[0] * unitPx, p[1] * unitPx]);
+
const canvasRef = useRef(null);
const draw = useCallback(
@@ -190,7 +190,7 @@ export default function StandardLayer(props: {
ctx.stroke();
// ctx.fillRect(100, 100, 150, 100); // 绘制一个矩形
},
- [xEndPx, xStartPx, xStepPx, yEndPx, yStartPx, yStepPx]
+ [pointsLeft, pointsRight, unitPx, xEndPx, xStartPx, xStepPx, yEndPx, yStartPx, yStepPx]
);
useEffect(() => {
const canvas = canvasRef.current;
diff --git a/src/services/socket.ts b/src/services/socket.ts
index 82c1b3c..83f18d1 100644
--- a/src/services/socket.ts
+++ b/src/services/socket.ts
@@ -1,6 +1,7 @@
import { Subject } from "rxjs";
+import { Datagram } from "./wsTypes";
-export type SocketState = 'open' | 'close' | 'error'
+export type SocketState = "open" | "close" | "error";
class WebSocketClient {
private ws: WebSocket | null = null;
@@ -9,9 +10,14 @@ class WebSocketClient {
private maxReconnectAttempts: number = 5;
private reconnectInterval: number = 3000;
- readonly dataOb = new Subject()
- readonly stateOb = new Subject()
-
+ private dataSub = new Subject();
+ get dataOb() {
+ return this.dataSub.asObservable();
+ }
+ private stateSub = new Subject();
+ get stateOb() {
+ return this.stateSub.asObservable();
+ }
constructor(url: string) {
this.url = url;
}
@@ -41,28 +47,32 @@ class WebSocketClient {
this.ws.onopen = () => {
console.log("WebSocket 连接已建立");
this.reconnectAttempts = -1; // 重置重连次数
- this.stateOb.next('open')
+ this.stateSub.next("open");
};
// 接收消息的处理
this.ws.onmessage = (event: MessageEvent) => {
try {
- const data = JSON.parse(event.data);
- // console.log('🚀 ~ WebSocketClient ~ bindEvents ~ data:', data)
- this.dataOb.next(data)
+ const data = JSON.parse(event.data) as Datagram;
+ // console.log("🚀 ~ WebSocketClient ~ bindEvents ~ data:", data);
+ // if (data.type === "cmd") {
+ // this.dataSub.next({ type: data.type, data: { ...data.data, success: data.data.status === "D0000" } });
+ // } else {
+ this.dataSub.next(data);
+ // }
} catch (error) {
console.error("消息解析错误:", error);
}
};
this.ws.onclose = () => {
- this.stateOb.next('close')
+ this.stateSub.next("close");
console.log("WebSocket 连接已关闭");
this.reconnect();
};
this.ws.onerror = error => {
- this.stateOb.next('error')
+ this.stateSub.next("error");
console.error("WebSocket 错误:", error);
};
}
@@ -107,5 +117,4 @@ export const createWebSocket = (url: string): WebSocketClient => {
}
};
-
-export const sharedWsUrl = `ws://${process.env.REACT_APP_WS_URL}`;
\ No newline at end of file
+export const sharedWsUrl = `ws://${process.env.REACT_APP_WS_URL}`;
diff --git a/src/services/wsTypes.ts b/src/services/wsTypes.ts
new file mode 100644
index 0000000..7113fc9
--- /dev/null
+++ b/src/services/wsTypes.ts
@@ -0,0 +1,20 @@
+ // 开始、停止绘制
+export type TaskState = {
+ messageType: "EVENT";
+ data: {
+ event: "START_RECORD_SIG" | "END_RECORD_SIG";
+ };
+ path: "/measurement-task/get-task-state";
+};
+
+// 连接上报坐标点
+export type TrackRecordSig = {
+ messageType: "EVENT";
+ data: {
+ x: number;
+ y: number;
+ };
+ path: "/measurement-task/profile-record-ctrl-sig";
+};
+
+export type Datagram = TrackRecordSig | TaskState;