代码之家  ›  专栏  ›  技术社区  ›  YotiPoti

我的照片太大了,无法容纳我的HTML画布。我该怎么办?

  •  0
  • YotiPoti  · 技术社区  · 11 月前

    我使用HTMLcanvas和一张照片创建了一个地图,但照片太大了,所以当我试图以正常大小渲染它时,画布的宽度和高度与照片的相同, 但当我放大时,它崩溃了,因为画布太大了。 我有两个放大事件(2_fingers_touch和滚轮);

    我还试着用一个选定的点将视图居中,但画布没有移动:D 我不知道如何从这里继续。 这是我的代码:

    import React, { useContext, useEffect, useRef, useState } from 'react';
    import { MapProps, TrackPoint, pwgParamsType, Pin } from '../../common/types/YotiMaps.types';
    import { CrisisContext } from '../../contexts/CrisisContextProvider';
    import { useGeolocation } from '../../common/hooks';
    import Loading from '../Loading/Loading';
    import crisisLocationImageSrc from '/maps/crisis-location-icon.png'
    import pinImageSrc from '/maps/pin.png';
    import locationImageSrc from '/maps/self-location-icon.png'
    import mapImgSrc from '/maps/suger.png';
    import { Crisis } from '../../common/types';
    import { convertLatLonToITM } from '../../pages/unit-conversion-page/components/conversionHelperFunctions'
    import { PopupContext } from '../../contexts/PopupContextProvider';
    import './maps.scss';
    
    const YotiMaps: React.FC<MapProps> = (props) => {
      const { height, width, maxPins } = props
      const { alertPopup } = useContext(PopupContext);
    
      const pgwData = useRef<pwgParamsType | null>(null)
      const pins = useRef<number>(0);
      const mapImage = useRef<HTMLImageElement | null>(null)
      const [pinArray] = useState<Pin[]>([])
      const canvasRef = useRef<HTMLCanvasElement | null>(null);
    
      const pgwFilePath = '/src/components/Map/suger.pgw';
      const { crisis } = useContext(CrisisContext);
      const myLocation = useRef(useGeolocation())
    
      // SCALE THINGS 
      const [scale, setScale] = useState(1.5);
      let initialTouchDistance = 1;
    
      // Drawing the Images first time
      const pinImage = new Image();
      const locationImage = new Image();
      const crisisLocationImage = new Image();
      pinImage.src = pinImageSrc;
      locationImage.src = locationImageSrc;
      crisisLocationImage.src = crisisLocationImageSrc;
    
      // draws the map first time
      useEffect(() => {
        const canvas = canvasRef.current;
        if (canvas) {
          const ctx = canvas.getContext('2d');
          if (ctx) {
            const map = new Image();
            map.src = mapImgSrc
            map.onload = () => {
              redrawCanvas(ctx, map);
              mapImage.current = map
            };
            getPgwData();
            canvas.addEventListener('click', handleCanvasClick);
            canvas.addEventListener("wheel", handleWheelChange, { passive: false });
            // Clean up event listener
            return () => {
              canvas.removeEventListener('click', handleCanvasClick);
              canvas.removeEventListener("wheel", handleWheelChange)
            };
          }
        }
      }, []);
    
    
      // *****FUNCTIONS****** 
    
      const redrawCanvas = async (ctx: CanvasRenderingContext2D, image: HTMLImageElement) => {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.drawImage(image, 0, 0);
        drawMyLocation(ctx);
        drawMeetupLocation(ctx, crisis)
      };
    
      const drawMyLocation = (ctx: CanvasRenderingContext2D) => {
        let x: number = 0;
        let y: number = 0;
        let fixedCoordinates = { easting: 0, northing: 0 }
        const context = ctx
        myLocation.current()
          .then((coords) => {
            x = coords.longitude;
            y = coords.latitude;
            context.drawImage(locationImage, x, y, locationImage.width * 2 / 3, locationImage.height * 2 / 3);
            fixedCoordinates = convertLatLonToITM(y, x)
            console.log(fixedCoordinates);
          })
          .catch((error: ErrorOptions) => {
            alertPopup(`מיקומך לא נמצא`, "red");
            console.error('Error loading self location', error)
          });
      }
      const drawMeetupLocation = (ctx: CanvasRenderingContext2D, crisis: Crisis | null) => {
        if (!crisis) return <Loading />
        const stringMeetup = crisis.meetup
        const meetup = { lat: parseFloat(stringMeetup.lat), lng: parseFloat(stringMeetup.lng) }
        // const meetup = { lat: 100, lng: 100 }
        ctx.drawImage(crisisLocationImage, meetup.lat, meetup.lng, crisisLocationImage.width, crisisLocationImage.height);
      }
    
      const getPgwData = async () => {
        try {
          const pgwResponse = await fetch(pgwFilePath);
          const pgwData = await pgwResponse.text();
          parsePGWFile(pgwData);
        } catch (error) {
          console.error('Error loading PGW file:', error);
        }
      }
    
      const calculateItmCoordinates = (clickX: number, clickY: number, pgwData: pwgParamsType | null,): { transformedX: number, transformedY: number } => {
        let tempObj: { transformedX: number, transformedY: number } = { transformedX: 0, transformedY: 0 }
        if (pgwData) {
          const transformedX = pgwData.pixelSizeX * clickX / scale + pgwData.originX;
          const transformedY = pgwData.pixelSizeY * clickY / scale + pgwData.originY;
          tempObj = { transformedX, transformedY }
        }
        return tempObj;
      }
      const calculatePixelCoordinates = (easting: number, northing: number, pgwData: pwgParamsType | null): { fakeX: number, fakeY: number } => {
        let tempObj: { fakeX: number, fakeY: number } = { fakeX: 0, fakeY: 0 }
        if (pgwData) {
          tempObj.fakeX = (easting - pgwData.originX) * scale / pgwData.pixelSizeX,
            tempObj.fakeY = (northing - pgwData.originY) * scale / pgwData.pixelSizeY
        }
        return tempObj;
      }
    
      const parsePGWFile = (pgwDataFromFetch: string): void => {
        const parameters = pgwDataFromFetch.trim().split('\n');
        const pixelSizeX = parseFloat(parameters[0]);
        const rotationX = parseFloat(parameters[1]);
        const rotationY = parseFloat(parameters[2]);
        const pixelSizeY = parseFloat(parameters[3]);
        const originX = parseFloat(parameters[4]);
        const originY = parseFloat(parameters[5]);
        pgwData.current = {
          pixelSizeX,
          rotationX,
          rotationY,
          pixelSizeY,
          originX,
          originY,
        }
      };
    
    
      // **********EVENTS-FUNCTIONS************
    
      const handleCanvasClick = (event: MouseEvent) => {
        const canvas = canvasRef.current;
        const ctx = canvas?.getContext('2d');
        if (canvas && ctx) {
          const rect = canvas.getBoundingClientRect()
          const clickedX = event.clientX - rect.left;
          const clickedY = event.clientY - rect.top;
          if (pinArray.length < maxPins) {
            let coordinatesObj: { transformedX: number, transformedY: number } = calculateItmCoordinates(clickedX, clickedY, pgwData?.current)
            ctx.drawImage(pinImage, clickedX - 23, clickedY - 40, pinImage.width, pinImage.height);
            const newPin: Pin = { id: pins.current, x: clickedX, y: clickedY, actualY: coordinatesObj.transformedY, actualX: coordinatesObj.transformedX };
            pins.current++;
            pinArray.push(newPin)
            console.log(pinArray);
          } else {
            let coordinatesObj = calculateItmCoordinates(clickedX, clickedY, pgwData?.current)
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            if (mapImage.current) {
              redrawCanvas(ctx, mapImage.current);
              for (let i = 1; i < pinArray.length; i++) {
                ctx.drawImage(pinImage, pinArray[i].x - 23, pinArray[i].y - 40, pinImage.width, pinImage.height);
              }
              ctx.drawImage(pinImage, clickedX - 23, clickedY - 40, pinImage.width, pinImage.height);
              const newPin: Pin = { id: pins.current, x: clickedX, y: clickedY, actualY: coordinatesObj.transformedY, actualX: coordinatesObj.transformedX };
              pinArray.splice(0, 1);
              pinArray.push(newPin);
              pins.current++;
              console.log(pinArray);
            }
          };
        }
      };
      function getTouchDistance(touch1: React.Touch, touch2: React.Touch): number {
        const dx = touch2.clientX - touch1.clientX;
        const dy = touch2.clientY - touch1.clientY;
        return Math.sqrt(dx * dx + dy * dy);
      }
    
      const handleCanvasTouchStart = (event: React.TouchEvent<HTMLCanvasElement>) => {
        if (event.touches.length >= 2) {
          const touch1 = event.touches[0];
          const touch2 = event.touches[1];
          initialTouchDistance = getTouchDistance(touch1, touch2);
        }
      };
    
      const handleCanvasTouchMove = (event: React.TouchEvent<HTMLCanvasElement>) => {
        if (event.touches.length >= 2) {
          const touch1 = event.touches[0];
          const touch2 = event.touches[1];
          const currentTouchDistance = getTouchDistance(touch1, touch2);
          const zoomLevel = currentTouchDistance / initialTouchDistance;
          setScale(zoomLevel);
        }
      };
    
      const handleWheelChange = (event: WheelEvent) => {
        event.preventDefault()
        const delta = Math.max(-1, Math.min(1, event.deltaY));
        const scaleIncrement = 0.001;
        setScale(prev=>  prev*delta+scaleIncrement)
      }
    
      return (
        <canvas
          id='yotiMaps'
          ref={canvasRef}
          width={14000 * scale}
          height={4116 * scale}
          style={{ transform: `scale(${scale})` }}
          onTouchStart={handleCanvasTouchStart}
          onTouchMove={handleCanvasTouchMove}
          onWheel={handleWheelChange}
        />
      );
    };
    
    export default YotiMaps;
    
    

    我试着把照片剪成7等分,但当你只放大一张照片,而你能看到另一张照片却没有放大时,这看起来很糟糕,

    我想也许可以试着做两个相等的画布,但在我做之前,我想看看是否有人有更好的想法。

    在画布渲染时,我试图将大小设置为比例大小,但它会压碎,所以这是一个错误。

    0 回复  |  直到 11 月前