From 6546ed84364eacccf10351f0c671dffb545900a0 Mon Sep 17 00:00:00 2001
From: luxiaotao1123 <t1341870251@163.com>
Date: 星期三, 24 四月 2024 16:02:52 +0800
Subject: [PATCH] #

---
 src/components/text.jsx |   40 +++++++++++++
 src/assets/data/area.js |   15 +++++
 src/components/area.jsx |  115 ++++++++++++++++++++++++++++++++++++++
 src/core/warehouse.jsx  |    7 ++
 4 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/src/assets/data/area.js b/src/assets/data/area.js
new file mode 100644
index 0000000..0071c41
--- /dev/null
+++ b/src/assets/data/area.js
@@ -0,0 +1,15 @@
+const areaData = [
+  {
+    x: -500,
+    y: -400,
+    width: 700,
+    height: 800,
+    name: 'selected-rect1684723196047',
+    type: 'area',
+    strokeColor: 'rgb(255, 0, 14)',
+    areaNumber: 'A1',
+    textHeight: 400,
+  },
+];
+
+export default areaData;
diff --git a/src/components/area.jsx b/src/components/area.jsx
new file mode 100644
index 0000000..3505595
--- /dev/null
+++ b/src/components/area.jsx
@@ -0,0 +1,115 @@
+import React, { useRef, useState } from 'react';
+import { useFrame, useThree } from '@react-three/fiber';
+import * as THREE from 'three';
+import { CameraControls } from '@react-three/drei';
+import Text2 from './text';
+// import Annotation, { IAnnotationDataItem, IAnnotationRef } from './annotation';
+
+const Y = 1;
+const Area = ({
+  x,
+  y,
+  width,
+  height,
+  areaNumber,
+  textHeight,
+  strokeColor,
+}) => {
+  const [hovered, setHover] = useState(false);
+  const [clicked, setClicked] = useState(false);
+  const meshRef = useRef(null);
+  const { controls } = useThree((state) => ({
+    controls: state.controls,
+  }));
+
+  // 杞崲涓簒杞村拰z杞寸粍鎴愮殑鍧愭爣绯讳腑鐨勪綅缃�
+  const position = new THREE.Vector3(x + width / 2, Y, y + height / 2);
+  const size = [width, 1, height];
+  textHeight ||= Y + 50;
+
+  // 鐩告満绉诲姩鍒板尯鍩熺殑浣嶇疆
+  const handleClick = () => {
+    if (clicked) return;
+    setClicked(true);
+    // controls.fitToBox(meshRef.current!, true);
+    const mesh = meshRef.current;
+    const { x, y, z } = mesh.position;
+
+    const box = new THREE.Box3().setFromCenterAndSize(
+      new THREE.Vector3(x, (y + textHeight) / 2, z),
+      new THREE.Vector3(width, textHeight, height)
+    );
+    controls.fitToBox(box, true);
+
+    // annotationRef.current?.show();
+  };
+
+  // 鐩告満绉诲姩鍥炲師鏉ョ殑浣嶇疆
+  const handleDoubleClick = () => {
+    setClicked(false);
+  };
+
+  // 鐩戝惉榧犳爣绉诲叆鍜岀Щ鍑轰簨浠讹紝鏀瑰彉hover鐘舵��
+  const handlePointerOver = () => setHover(true);
+  const handlePointerOut = () => setHover(false);
+
+  // 姣忓抚鏇存柊杈规鐨勯鑹插拰绮楃粏
+  useFrame(() => {
+    const box = meshRef.current;
+    if (box) {
+      const color = hovered || clicked ? strokeColor : 'white';
+      const thickness = clicked ? 0.5 : 0.2;
+      const material = box.material;
+      material.color.set(color);
+      material.linewidth = thickness;
+    }
+  });
+
+  // const annotationRef = useRef(null);
+  const annotationData = [
+    {
+      label: '闀�',
+      value: width + '绫�',
+    },
+    {
+      label: '瀹�',
+      value: height + '绫�',
+    },
+  ];
+
+  return (
+    <group
+      onClick={handleClick}
+      onPointerOver={handlePointerOver}
+      onPointerOut={handlePointerOut}
+      onDoubleClick={handleDoubleClick}
+      onPointerMissed={() => setClicked(false)}
+    >
+      <mesh ref={meshRef} position={position}>
+        <boxGeometry attach="geometry" args={size} />
+        <lineSegments>
+          <edgesGeometry attach="geometry" args={[new THREE.BoxGeometry(...size)]} />
+          <lineBasicMaterial attach="material" color={strokeColor} linewidth={0.2} />
+        </lineSegments>
+        <meshBasicMaterial attach="material" color={strokeColor} transparent opacity={0.2} />
+      </mesh>
+
+      {areaNumber && (
+        <Text2
+          position={new THREE.Vector3(position.x, textHeight, position.z)}
+          text={areaNumber}
+          scale={new THREE.Vector3(100, 100, 100)}
+          fontSize={100}
+        />
+      )}
+      {/* <Annotation
+        ref={annotationRef}
+        title={areaNumber}
+        position={position}
+        data={annotationData}
+      ></Annotation> */}
+    </group>
+  );
+};
+
+export default Area;
diff --git a/src/components/text.jsx b/src/components/text.jsx
new file mode 100644
index 0000000..d5dfdaa
--- /dev/null
+++ b/src/components/text.jsx
@@ -0,0 +1,40 @@
+import * as THREE from 'three';
+import { useEffect, useState } from 'react';
+
+
+function generateSprite(text, color, fontSize = 50) {
+  const canvas = document.createElement('canvas');
+  canvas.width = 300;
+  canvas.height = 300;
+  const context = canvas.getContext('2d');
+  context.beginPath();
+  context.font = `${fontSize}px Microsoft YaHei`;
+  context.fillStyle = color;
+  context.textAlign = 'center';
+  context.textBaseline = 'middle';
+  context.fillText(text, canvas.width / 2, canvas.height / 2);
+  context.fill();
+  context.stroke();
+  return canvas;
+}
+
+const Text2 = ({
+  text,
+  position,
+  scale = new THREE.Vector3(100, 100, 100),
+  color = '#00D1D1',
+  fontSize = 50,
+}) => {
+  const [material, setMaterial] = useState(undefined);
+  useEffect(() => {
+    const material = new THREE.SpriteMaterial({
+      map: new THREE.CanvasTexture(generateSprite(text, color, fontSize)),
+      blending: THREE.AdditiveBlending,
+    });
+    setMaterial(material);
+  }, [text, color, fontSize]);
+
+  return <sprite material={material} position={position} scale={scale} />;
+}
+
+export default Text2;
diff --git a/src/core/warehouse.jsx b/src/core/warehouse.jsx
index e349492..43a1b77 100644
--- a/src/core/warehouse.jsx
+++ b/src/core/warehouse.jsx
@@ -2,11 +2,13 @@
 import { useFrame } from '@react-three/fiber';
 import * as THREE from 'three';
 import Tunnel from '../components/tunnel';
+import Area from '../components/area';
 import Shelf from '../components/shelf';
 import Box from '../components/box';
 import Agv from '../components/agv';
 
 import tunnelData from '@/assets/data/tunnel';
+import areaData from '@/assets/data/area';
 import shelfData from '@/assets/data/shelf';
 import agvRealDataList from '@/assets/data/agv';
 import { INTERVAL_TIME } from '@/config/setting'
@@ -40,6 +42,10 @@
         return tunnelData.map((data, index) => <Tunnel key={index} {...data} />)
     }, []);
 
+    const areaEl = useMemo(() => {
+        return areaData.map((area, index) => <Area key={index} {...area} />)
+    }, []);
+
     const shelfEl = useMemo(() => {
         return shelfData.map((data, index) => <Shelf key={index} {...data} />)
     }, []);
@@ -64,6 +70,7 @@
         <>
             <group>
                 {tunnelEl}
+                {areaEl}
                 {shelfEl}
                 {/* {shelfEl1} */}
                 {agvEl}

--
Gitblit v1.9.1