Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save guilhermerodz/404c1a6ca25a01173a64d9afb6fad1d0 to your computer and use it in GitHub Desktop.
Save guilhermerodz/404c1a6ca25a01173a64d9afb6fad1d0 to your computer and use it in GitHub Desktop.
react magnifier
'use client'
import * as React from 'react'
import { cn } from '@/lib/cn'
import Image from 'next/image'
export default function Home() {
const mirrorRef = React.useRef<HTMLDivElement>(null)
const mainRef = React.useRef<HTMLDivElement>(null)
const [isMagnifying, setIsMagnifying] = React.useState(false)
function mouseMove(e: React.MouseEvent<HTMLDivElement>) {
const main = mainRef.current
const mirror = mirrorRef.current
if (!main || !mirror) return
const mainRect = main.getBoundingClientRect()
const mirrorRect = mirror.getBoundingClientRect()
// get x and y offset within main
const x = e.clientX - mainRect.left
const y = e.clientY - mainRect.top
const diffX = mirrorRect.width - mainRect.width
const diffY = mirrorRect.height - mainRect.height
const px = x / mainRect.width
const py = y / mainRect.height
const tx = px * diffX - diffX / 2
const ty = py * diffY - diffY / 2
mirror.style.setProperty('--ox', `${tx}px`)
mirror.style.setProperty('--oy', `${ty}px`)
}
return (
<div className="w-screen h-screen">
<div
className="absolute w-[300px] h-[300px] left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border border-[red] overflow-hidden"
onMouseOver={() => setIsMagnifying(true)}
onMouseLeave={() => setIsMagnifying(false)}
onMouseMove={mouseMove}
>
<MainLayer ref={mainRef} />
{isMagnifying && <MirrorLayer ref={mirrorRef} />}
</div>
</div>
)
}
const MainLayer = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>((props, ref) => {
return (
<div ref={ref} className="relative w-full h-full">
<Image src="/placeholder.svg" fill alt="Arthur" />
</div>
)
})
MainLayer.displayName = 'MainLayer'
const MirrorLayer = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>((props, ref) => {
return (
<div
ref={ref}
className={cn(
'absolute pointer-events-none inset-0 border border-[green]',
'[--ox:0] [--oy:0]',
'[transform:scale(1.5)_translate(var(--ox),var(--oy))]',
)}
// IMPORTANT: prevent any user input such as pointer-events or keyboard
>
<MainLayer />
</div>
)
})
MirrorLayer.displayName = 'MirrorLayer'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment