60 lines
1.4 KiB
TypeScript
60 lines
1.4 KiB
TypeScript
import { useCallback, useRef, useState, MouseEvent, useEffect } from "react"
|
|
import { FocalPoint } from "~/types/imagevault"
|
|
|
|
interface UseFocalPointProps {
|
|
focalPoint?: FocalPoint
|
|
onChange: (focalPoint: FocalPoint) => void
|
|
}
|
|
|
|
const DEFAULT_PERCENTAGE = 50
|
|
|
|
export default function useFocalPoint({
|
|
focalPoint,
|
|
onChange,
|
|
}: UseFocalPointProps) {
|
|
const ref = useRef<HTMLDivElement>(null)
|
|
const [x, setX] = useState<number>(DEFAULT_PERCENTAGE)
|
|
const [y, setY] = useState<number>(DEFAULT_PERCENTAGE)
|
|
const [canMove, setCanMove] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (focalPoint) {
|
|
setX(focalPoint.x)
|
|
setY(focalPoint.y)
|
|
}
|
|
}, [focalPoint])
|
|
|
|
const onMove = useCallback(
|
|
(e: MouseEvent) => {
|
|
if (canMove) {
|
|
const containerBoundingRectangle = ref.current!.getBoundingClientRect()
|
|
const xPixels = e.clientX - containerBoundingRectangle.left
|
|
const yPixels = e.clientY - containerBoundingRectangle.top
|
|
let x = Math.min(
|
|
Math.max((xPixels * 100) / ref.current!.clientWidth, 0),
|
|
100
|
|
)
|
|
let y = Math.min(
|
|
Math.max((yPixels * 100) / ref.current!.clientHeight, 0),
|
|
100
|
|
)
|
|
x = parseFloat(x.toFixed(2))
|
|
y = parseFloat(y.toFixed(2))
|
|
setX(x)
|
|
setY(y)
|
|
onChange({ x, y })
|
|
}
|
|
},
|
|
[canMove, onChange]
|
|
)
|
|
|
|
return {
|
|
ref,
|
|
x,
|
|
y,
|
|
onMove,
|
|
canMove,
|
|
setCanMove,
|
|
}
|
|
}
|