Generate canvas polygone shape based on image map coords in react

Viewed 21

I have an image contains some solar pannels, i have to track each card in each pannel, for that i use react-img-mapper to highlight over these cards, i numbered each cards from "1, 2, 3 ..., 600" from an api i get an object like this :

// simulate the data
const dumpData = {
    startAt: 12,
    endAt: 25,
  };

startAt and endAt means the cards that should be highlighted, the problem in react-img-mapper is that the areas does not stay highlighted unless you click on it , so what i am trying to do is to create a canvas element and do some logic to determine it's position based on areas coords , to highlight over the specified areas,

here's my full example in Home.tsx:

function Home() {
  const [isOpen, setIsOpen] = useState(false);
  const [text, setText] = useState("");
  const [zoom, setZoom] = useState(0.2);
  const [mapData, setMapData] = useState<MapAreaWithName[]>(data);
  const [showButtons, setShowButtons] = useState(false);

  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement | null>(null);
  
  // this makes image area maps responsive
  useEffect(() => {
    // @ts-ignore
    import("image-map-resizer").then((module) => module.default());
  }, []);
  
  // my data
  const dumpData = {
    startAt: 12,
    endAt: 25,
  };
  
  // show a Modal when click on area 
  const clicked = (area: any, i: number, e: any): void => {
    setIsOpen(true);
    for (const item of mapData) {
      if (area?.name === item.name) {
        setText('This a pannel num ${area?.name}' );
      }
    }
  };
  
  // my example to set canvas posistion but does not work properly .
  useEffect(() => {
    // i update my array of areas based my data
    const arr = mapData.slice(dumpData.startAt, dumpData.endAt);
    // setMapData(arr);
    console.log(arr);
    const ctx = canvasRef.current?.getContext("2d");
    if (!ctx) return;
    ctx.fillStyle = "#f00";
    ctx.beginPath();
    ctx.moveTo(arr[1].coords[2], arr[1].coords[3]);
    ctx.lineTo(100, 50);
    ctx.lineTo(50, 100);
    ctx.lineTo(0, 90);
    ctx.closePath();
    ctx.fill();
  }, []);

  // * State handlers
  const zoomIn = useCallback(() => {
    setZoom((p) => p + 0.1);
  }, []);

  const zoomOut = useCallback(() => {
    setZoom((p) => p - 0.1);
  }, []);

  const handleShowButtons = useCallback(() => {
    setShowButtons((p) => !p);
  }, []);

  return (
    <Fragment>
      <div
        style={{
          zoom,
        }}
        className="">
        <ImageMapper
          src={URL}
          natural
          // rerenderProps={[]}
          map={{ name: "my-map", areas: mapData }}
          onClick={clicked}
        />
        {/* TODO: draw canvas over elements based on dumpData */}
        <canvas
          ref={canvasRef}
          className="bg-slate-500 top-[0] left-0  absolute  w-full"></canvas>
      </div>
      <Modal isOpen={isOpen} setIsOpen={setIsOpen} render={() => <>{text}</>} />
      <div className="fixed flex flex-col items-center gap-3 z-40 bottom-10 right-10">
        {showButtons && (
          <>
            <button
              type="button"
              onClick={zoomIn}
              className="text-gray-800 bg-gray-100 hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-300 font-medium rounded-lg text-sm p-2.5 text-center inline-flex items-center mr-2">
              <PlusIcon className="h-6" />
              <span className="sr-only">Icon description</span>
            </button>
            <button
              type="button"
              onClick={zoomOut}
              className="text-gray-800 bg-gray-100 hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-300 font-medium rounded-full text-sm p-2.5 text-center inline-flex items-center mr-2">
              <MinusIcon className="h-6" />
              <span className="sr-only">Icon description</span>
            </button>
          </>
        )}
        <button
          onClick={handleShowButtons}
          className="bg-gray-100  rounded-xl mt-2 px-3 py-3">
          <img className="h-5" src="/images/Vector.svg" alt="" />
        </button>
      </div>
    </Fragment>
  );
}

export default Home;

here's the app: https://gep-scada-2.vercel.app/ in the home page if the image did not appear just hit refresh

thanks in advance .

0 Answers
Related