-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(dataroom): DotGrid animation (#442)
* Open branch * feat: πΈ Add Industry Comparison Section * fix: π address PR comments * refactor: π‘ address PR comments * docs: βοΈ add descripition for useMousePosition hook * refactor: π‘ remove container ref from useMousePosition * refactor: π‘ add SlidingPanel component and update Cryptopunks * refactor: π‘ dynamic import for framer motion * refactor: π‘ address PR comments * refactor: π‘ conditionally call drawDots to improve performance * style: π remove unused title style * refactor: π‘ remove unused prop dimensions from drawDots --------- Co-authored-by: iamacook <[email protected]> Co-authored-by: Diogo Soares <[email protected]>
- Loading branch information
1 parent
3c36729
commit 45be219
Showing
4 changed files
with
111 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 45 additions & 5 deletions
50
src/components/DataRoom/IndustryComparison/utils/drawDots.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,52 @@ | ||
type Position = { x: number; y: number } | ||
|
||
const DOT_COLOR = '#12312' | ||
const MAX_SCALE_DISTANCE = 15 | ||
const MOBILE_MAX_SCALE = 8 | ||
const DESKTOP_MAX_SCALE = 12 | ||
const DOT_COLOR = '#121312' | ||
|
||
let lastUpdatedArea: { x: number; y: number; radius: number } | null = null | ||
|
||
export const drawDots = ( | ||
ctx: CanvasRenderingContext2D, | ||
dots: Position[], | ||
mousePosition: Position, | ||
isMobile: boolean, | ||
) => { | ||
const maxScale = isMobile ? MOBILE_MAX_SCALE : DESKTOP_MAX_SCALE | ||
const updatedRadius = MAX_SCALE_DISTANCE * maxScale | ||
|
||
// Clear the previously updated area | ||
if (lastUpdatedArea) { | ||
ctx.clearRect( | ||
lastUpdatedArea.x - lastUpdatedArea.radius, | ||
lastUpdatedArea.y - lastUpdatedArea.radius, | ||
lastUpdatedArea.radius * 2, | ||
lastUpdatedArea.radius * 2, | ||
) | ||
} | ||
// Clear the new (to be updated) area | ||
ctx.clearRect(mousePosition.x - updatedRadius, mousePosition.y - updatedRadius, updatedRadius * 2, updatedRadius * 2) | ||
|
||
export const drawDots = (ctx: CanvasRenderingContext2D, dots: Position[]) => { | ||
ctx.fillStyle = DOT_COLOR | ||
|
||
dots.forEach((dot) => { | ||
ctx.beginPath() | ||
ctx.arc(dot.x, dot.y, 1, 0, 2 * Math.PI) | ||
ctx.fill() | ||
const dx = mousePosition.x - dot.x | ||
const dy = mousePosition.y - dot.y | ||
const distance = Math.sqrt(dx * dx + dy * dy) | ||
|
||
if (distance <= updatedRadius) { | ||
const scale = Math.max(1, maxScale - distance / MAX_SCALE_DISTANCE) | ||
ctx.beginPath() | ||
ctx.arc(dot.x, dot.y, 1 * scale, 0, 2 * Math.PI) | ||
ctx.fill() | ||
} else { | ||
// Draw unupdated dots with normal size | ||
ctx.beginPath() | ||
ctx.arc(dot.x, dot.y, 1, 0, 2 * Math.PI) | ||
ctx.fill() | ||
} | ||
}) | ||
|
||
lastUpdatedArea = { x: mousePosition.x, y: mousePosition.y, radius: updatedRadius } | ||
} |
43 changes: 43 additions & 0 deletions
43
src/components/DataRoom/IndustryComparison/utils/useMousePosition.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { useState, useEffect } from 'react' | ||
import type { MotionValue } from 'framer-motion' | ||
import { useIsMediumScreen } from '@/hooks/useMaxWidth' | ||
|
||
/** | ||
* Custom hook to track mouse position or simulate it based on scroll progress. | ||
* @param canvasRef - Reference to the canvas element. | ||
* @param dimensions - Object containing width and height of the container. | ||
* @param scrollYProgress - MotionValue for scroll progress, used on mobile devices. | ||
* @returns An object with x and y coordinates representing either: | ||
* - Actual mouse position relative to the canvas (on desktop) | ||
* - Simulated position based on scroll progress (on mobile) | ||
*/ | ||
export default function useMousePosition( | ||
canvasRef: React.RefObject<HTMLCanvasElement>, | ||
dimensions: { width: number; height: number }, | ||
scrollYProgress?: MotionValue<number>, | ||
) { | ||
const isMobile = useIsMediumScreen() | ||
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }) | ||
|
||
useEffect(() => { | ||
if (isMobile && scrollYProgress) { | ||
const updatePositionMobile = () => { | ||
const progress = scrollYProgress.get() | ||
setMousePosition({ x: dimensions.width - dimensions.width / 8, y: progress * dimensions.height }) | ||
} | ||
return scrollYProgress.on('change', updatePositionMobile) | ||
} else { | ||
const canvas = canvasRef.current | ||
const updatePositionDesktop = (e: MouseEvent) => { | ||
const rect = canvas?.getBoundingClientRect() | ||
if (rect) { | ||
setMousePosition({ x: e.clientX - rect.left, y: e.clientY - rect.top }) | ||
} | ||
} | ||
canvas?.addEventListener('mousemove', updatePositionDesktop) | ||
return () => canvas?.removeEventListener('mousemove', updatePositionDesktop) | ||
} | ||
}, [canvasRef, isMobile, scrollYProgress, dimensions]) | ||
|
||
return mousePosition | ||
} |