From f7d1573746db614407d19d0c73f34d4f41b8745a Mon Sep 17 00:00:00 2001 From: Muthu Kumar Date: Thu, 10 Apr 2025 01:03:40 +0530 Subject: [PATCH] fix: fix viewport coords to use page coordinates --- src/draggable.attempts/6/Draggable.ts | 45 +++--- src/draggable.attempts/6/Draggable2.tsx | 12 +- src/pages/main/Contact.tsx | 260 +++++++++++++++++--------------- 3 files changed, 163 insertions(+), 154 deletions(-) diff --git a/src/draggable.attempts/6/Draggable.ts b/src/draggable.attempts/6/Draggable.ts index 9969b02..cd3715a 100644 --- a/src/draggable.attempts/6/Draggable.ts +++ b/src/draggable.attempts/6/Draggable.ts @@ -12,8 +12,8 @@ interface Vec2 { export interface DraggableOpts { initialRotation?: number; - onViewportExit?: () => void; - onViewportEnter?: () => void; + onPageExit?: () => void; + onPageEnter?: () => void; } export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { @@ -21,8 +21,8 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { const calculateInitialCenter = (): Vec2 => { const rect = card.getBoundingClientRect(); return { - x: rect.left + rect.width / 2, - y: rect.top + rect.height / 2, + x: rect.left + rect.width / 2 + window.scrollX, + y: rect.top + rect.height / 2 + window.scrollY, }; }; @@ -55,25 +55,29 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { let lastMousePosition: Vec2 = { x: 0, y: 0 }; let activePointerId: number | null = null; let animationFrameId: number | null = null; - let isOutsideViewport = false; + let isOutsideBounds = false; // --- Helpers --- - const checkViewportExit = throttle(() => { - // Don't check if we're dragging, user may still be able to move the card back into view + const checkPageBounds = throttle(() => { if (state.dragging) return; const rect = card.getBoundingClientRect(); + const pageLeft = rect.left + window.scrollX; + const pageTop = rect.top + window.scrollY; + const pageRight = rect.right + window.scrollX; + const pageBottom = rect.bottom + window.scrollY; + const outside = - rect.right < 0 || - rect.bottom < 0 || - rect.left > window.innerWidth || - rect.top > window.innerHeight; - - if (outside !== isOutsideViewport) { - isOutsideViewport = outside; - if (isOutsideViewport) opts.onViewportExit?.(); - else opts.onViewportEnter?.(); + pageRight < 0 || + pageBottom < 0 || + pageLeft > document.documentElement.scrollWidth || + pageTop > document.documentElement.scrollHeight; + + if (outside !== isOutsideBounds) { + isOutsideBounds = outside; + if (isOutsideBounds) opts.onPageExit?.(); + else opts.onPageEnter?.(); } }, VIEWPORT_CHECK_INTERVAL_MS); @@ -158,10 +162,8 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { // 1. Store current visual state relative to the *old* initialCenter const currentDeltaX = center.x - initialCenter.x; const currentDeltaY = center.y - initialCenter.y; - const currentRotation = rotation; // Rotation doesn't depend on initialCenter // 2. Temporarily remove the transform - card.style.transition = "none"; // Disable transitions during adjustment card.style.transform = "none"; // 3. Force browser reflow to get the *untouched* layout position @@ -180,10 +182,7 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { // 6. Reapply the transform immediately before the next paint // Use the *stored* delta and rotation to put it back visually where it was - card.style.transform = `translate(${currentDeltaX}px, ${currentDeltaY}px) rotate(${currentRotation}rad)`; - - // 7. Re-enable transitions if they were used - card.style.transition = ""; // Or restore previous transition style if needed + card.style.transform = `translate(${currentDeltaX}px, ${currentDeltaY}px) rotate(${rotation}rad)`; // The render loop will continue from this adjusted state. }, RESIZE_DEBOUNCE_MS); // Apply debouncing @@ -231,7 +230,7 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) { rotate(${rotation}rad) `; - checkViewportExit(); + checkPageBounds(); animationFrameId = requestAnimationFrame(render); } diff --git a/src/draggable.attempts/6/Draggable2.tsx b/src/draggable.attempts/6/Draggable2.tsx index 669048d..3a959aa 100644 --- a/src/draggable.attempts/6/Draggable2.tsx +++ b/src/draggable.attempts/6/Draggable2.tsx @@ -5,8 +5,8 @@ import { css, cx } from "@emotion/css"; export type DraggableProps = React.HtmlHTMLAttributes & { as?: React.ElementType; - onViewportEnter?: () => void; - onViewportExit?: () => void; + onPageEnter?: () => void; + onPageExit?: () => void; children: React.ReactNode; initialRotation?: number; }; @@ -17,8 +17,8 @@ export const Draggable = forwardRef( as: Comp = "div", children, className, - onViewportEnter, - onViewportExit, + onPageEnter, + onPageExit, initialRotation, ...props }: DraggableProps, @@ -29,8 +29,8 @@ export const Draggable = forwardRef( useEffect(() => { if (!cardRef.current) return; return makeDraggable(cardRef.current, { - onViewportEnter, - onViewportExit, + onPageEnter, + onPageExit, initialRotation, }); }, []); diff --git a/src/pages/main/Contact.tsx b/src/pages/main/Contact.tsx index d3030bc..c04d122 100644 --- a/src/pages/main/Contact.tsx +++ b/src/pages/main/Contact.tsx @@ -96,13 +96,7 @@ const Contact: React.FC = () => { }, []); return ( - +

MKRhere

{visible < 1 && ( @@ -112,130 +106,146 @@ const Contact: React.FC = () => { Start over? )} - {contactCards.map((rot, i) => ( - setVisible(v => v - 1)} - onViewportEnter={() => setVisible(v => v + 1)} - initialRotation={rot} - className={css` - width: 17rem; - height: 11rem; - font-size: 0.8rem; - - position: absolute; - bottom: 0; - left: 0; - - padding: 0; - background: transparent; - `} - ref={setupCursorTracking}> - + {contactCards.map((rot, i) => ( + setVisible(v => v - 1)} + onPageEnter={() => setVisible(v => v + 1)} + initialRotation={rot} + className={css` + width: 21rem; + height: 13rem; + font-size: 1rem; + + @media screen and (max-width: 40rem) { + width: 18rem; + height: 11rem; + font-size: 0.85rem; + } + + position: absolute; + bottom: 0; + left: 0; + + padding: 0; + background: transparent; + `} + ref={setupCursorTracking}> + -
-
    - {Object.keys(contact).map(key => ( -
  • - {key}. -
  • - ))} -
-
    - {Object.keys(contact).map(key => { - const value = contact[key]; - - return ( +
    +
      + {Object.keys(contact).map(key => (
    • - {value.link ? ( - - {value.value} - - ) : ( - value.value - )} + {key}.
    • - ); - })} -
    - - } - back={ -
    - -
    - } - /> - - ))} + ))} +
+
    + {Object.keys(contact).map(key => { + const value = contact[key]; + + return ( +
  • + {value.link ? ( + + {value.value} + + ) : ( + value.value + )} +
  • + ); + })} +
+ + } + back={ +
+ +
+ } + /> + + ))} + ); };