Zoom into an area with precession in where it is positioned using css and js

39 views Asked by At

I had an issue before with using clip-path, and so I switched to using values of the transformOrigin and backgroundPosition,
My issue was as follows:
assume I have two boxes, and 1 box is larger than the other, and the other will always be smaller than the bigger box, and the smaller box will overlap the big box, when that happens I need to have an Event that when it happens I zoom into the area, and highlight the smaller box cutout,

AS EASY AS IT SOUNDS, I ended up with the following:
styles:

export const styles ={
  outerWrapper: {
    width: "100dvw",
    height: "100dvh",
    position: "relative",
    top: 0,
    left: 0,
    display: "flex",
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "center",
  },
  backGround: {
    display: "flex",
    flexDirection: "column",
    backgroundAttachment: "fixed",
    position: "fixed",
    top: 0,
    left: 0,
    width: "100%",
    height: "100%",
    backgroundPosition: "center center ",
    backgroundRepeat: "no-repeat",
    // backgroundSize: "cover",

    backgroundImage:
      "url(https://buffer.com/cdn-cgi/image/w=1000,fit=contain,q=90,f=auto/library/content/images/size/w1200/2023/10/free-images.jpg)",
    zIndex: "0",
    transition: "clip-path 0.5s ease",
    clipPath: "clip",
  },
  scaleTransition: {
    // transformOrigin: "center",
    transition: "transform 0.5s ease",
    transform: "scale(1)",
  },
}

React element, following is somepieces of code:

      <div style={styles.outerWrapper}>
        <div
          style={{
            ...styles.backGround,
            ...styles.scaleTransition,
            // clipPath:clip,
            backgroundSize: "contain",
            objectFit: "fill",
            overscrollBehaviorBlock: "contain",
            transform: inViewPort ? "scale(2.5)" : "scale(1)",
            transformOrigin: inViewPort ? position : "center center",
            backgroundPosition: inViewPort ? position : "center center",
            backgroundBlendMode: "multiply",
            transformBox: "fill-box",
          }}
          ref={bg}
        ></div>

        {!inViewPort && (
          <Rnd
            ref={selectionBox}
            style={{ ...style, scale: inViewPort ? "scale(3)" : "scale(1)" }}
            default={{
              x: 0,
              y: 0,
              width: 200,
              height: 200,
            }}
            onDrag={(e) => zoomHelper()}
            onDragStop={() => zoomHelper()}
            onMouseUp={() => zoomHelper()}
            onMouseDown={() => zoomHelper()}
          >
            Choose an area to highlight
          </Rnd>
        )}
      </div>

functions:

  function zoomHelper() {
    const outerBoundary = bg.current?.getBoundingClientRect();
    const rndElement = document.querySelector(".react-draggable-dragged");

    if (outerBoundary && rndElement) {
      const outerRect = outerBoundary;
      const rndRect = rndElement.getBoundingClientRect();

      // Check if the Rnd element overlaps with the background
      if (
        outerRect.right > rndRect.left &&
        outerRect.left < rndRect.right &&
        outerRect.bottom > rndRect.top &&
        outerRect.top < rndRect.bottom
      ) {
        // Calculate the overlapping area
        const x1 = Math.max(outerRect.left, rndRect.left);
        const y1 = Math.max(outerRect.top, rndRect.top);
        const x2 = Math.min(outerRect.right, rndRect.right);
        const y2 = Math.min(outerRect.bottom, rndRect.bottom);

        const width = x2 - x1;
        const height = y2 - y1;

        const xCenter = x1 + width / 2;
        const yCenter = y1 + height / 2;

        const topCenter = { x: xCenter, y: y1 };
        const leftCenter = { x: x1, y: yCenter };
        const rightCenter = { x: x2, y: yCenter };
        const bottomCenter = { x: xCenter, y: y2 };
        const centerCenterPosition = { x: xCenter, y: yCenter };

        let detectedArea = null;
        // all of the top area
        if (
          y1 <= outerRect.top &&
          y2 >= yCenter &&
          xCenter >= outerRect.left &&
          xCenter <= outerRect.right
        ) {
          // console.log("top center ");
          setPosition("top center");
        }

        if (
          y1 <= yCenter &&
          y2 >= outerRect.bottom &&
          xCenter >= outerRect.left &&
          xCenter <= outerRect.right
        ) {
          // console.log("bottom center");
          setPosition("bottom center");
        }

        if (
          x1 <= xCenter &&
          x2 >= outerRect.right &&
          yCenter >= outerRect.top &&
          yCenter <= outerRect.bottom
        ) {
          // console.log("right center");
          setPosition("right center");
        }

        if (
          x1 <= outerRect.left &&
          x2 >= xCenter &&
          yCenter >= outerRect.top &&
          yCenter <= outerRect.bottom
        ) {
          setPosition("left center");
        }
      }
    }
  }

  function isInViewPort() {
    const el = point.current?.children[0].getBoundingClientRect();
    return !(el.top > innerHeight || el.bottom < 0);
  }

what I was trying to achieve, is specify where the position of the overlapped box is, and move the origin and background position into that position and zoom into it using scale(), so I would like to know wether there is a simpler way to do this? since I'm clearly doing something wrong.
Thank you

0

There are 0 answers