UNPKG

react-zoom-image-hover

Version:
213 lines (166 loc) 8.79 kB
# React Zoom Image Hover A lightweight, performant React component that provides smooth image zoom on hover with customizable zoom behavior, touch support, and accessibility features. ## Features - 🖼️ **Smooth Zoom Animation** - Smooth image zoom on hover with customizable scale and transition timing - 📱 **Touch Support** - Works on mobile devices with touch gestures - ♿ **Accessible** - Uses native `<img>` elements with proper alt text support for screen readers - ⚡ **Performance Optimized** - Uses React hooks (`useCallback`, `useMemo`) and throttling for optimal performance - 🎨 **Highly Customizable** - Extensive props for styling and behavior customization - 🔍 **Smart Mouse Tracking** - Zoom follows mouse position with smooth, throttled updates - 📦 **TypeScript Support** - Full TypeScript definitions included - 🎯 **Zero Dependencies** - Only requires React as a peer dependency - 🌐 **Semantic HTML** - Uses native `<img>` elements for better SEO and accessibility ## Installation ```bash npm install react-zoom-image-hover ``` or ```bash yarn add react-zoom-image-hover ``` ## Preview ![Preview](/demo.gif) ## Basic Usage ```tsx import Zoom from 'react-zoom-image-hover' function App() { return <Zoom src='/path/to/image.jpg' width={400} height={300} zoomScale={2} alt='Product image' /> } ``` ## Advanced Usage ```tsx import Zoom from 'react-zoom-image-hover' function ProductImage() { return ( <Zoom src='https://example.com/product.jpg' width='100%' height={500} zoomScale={2.5} transitionTime={0.2} alt='Product detail view' className='product-image-container' innerClassName='product-image-inner' objectFit='cover' objectPosition='center' transitionTimingFunction='cubic-bezier(0.4, 0, 0.2, 1)' enableTouch={true} throttleDelay={16} style={{ borderRadius: '8px', boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)', }} /> ) } ``` ## Props ### Required Props | Prop | Type | Description | | -------- | ------------------ | ---------------------------------------------- | | `src` | `string` | Image source URL | | `width` | `string \| number` | Container width (CSS value: string or number) | | `height` | `string \| number` | Container height (CSS value: string or number) | ### Optional Props | Prop | Type | Default | Description | | -------------------------- | ---------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `className` | `string` | - | Additional CSS class name for the container | | `innerClassName` | `string` | - | Additional CSS class name for the inner image element | | `zoomScale` | `number` | `1.5` | Zoom scale multiplier | | `transitionTime` | `number` | `0.1` | Transition duration in seconds | | `style` | `CSSProperties` | - | Additional inline styles for the container | | `alt` | `string` | - | Alt text for accessibility (recommended) | | `objectFit` | `'contain' \| 'cover' \| 'fill' \| 'none' \| 'scale-down'` | `'contain'` | CSS object-fit value - controls how the image is resized to fit its container. Use `contain` to fit entire image, `cover` to fill container, or `fill` to stretch | | `objectPosition` | `string` | `'center'` | CSS object-position value - controls the position of the image within its container (e.g., `'center'`, `'top left'`, `'50% 30%'`) | | `enableTouch` | `boolean` | `true` | Enable touch support for mobile devices | | `throttleDelay` | `number` | `16` | Throttle delay for mouse movement in milliseconds (~60fps) | | `transitionTimingFunction` | `string` | `'ease-out'` | CSS transition-timing-function value | ## TypeScript Support The component is written in TypeScript and includes full type definitions. You can import the props interface: ```tsx import Zoom, { ZoomProps } from 'react-zoom-image-hover' const props: ZoomProps = { src: '/image.jpg', width: 400, height: 300, } ``` ## Performance The component is optimized for performance: - **Throttled Updates**: Mouse movement updates are throttled (configurable delay) to prevent excessive re-renders while maintaining smooth tracking - **Memoized Styles**: Style objects are memoized with `useMemo` to avoid unnecessary recalculations - **Optimized Callbacks**: Event handlers are wrapped in `useCallback` to prevent unnecessary child re-renders - **Browser Optimization**: Uses `willChange: 'transform'` to hint the browser about upcoming transforms for better rendering performance - **Efficient Position Calculation**: Mouse position is calculated relative to viewport, avoiding unnecessary scroll calculations ## Accessibility The component is built with accessibility in mind: - **Native `<img>` Elements** - Uses semantic HTML for better screen reader support - **Alt Text Support** - Proper `alt` attribute support for image descriptions - **Semantic Structure** - Clean, semantic HTML that's easy for assistive technologies to parse - **Keyboard Friendly** - Works with keyboard navigation (inherits from container) ## Browser Support Works in all modern browsers that support: - CSS transforms and transitions - CSS `object-fit` and `object-position` properties - React 16+ (tested with React 16.8+ for hooks support) ## Examples ### E-commerce Product Image ```tsx <Zoom src='/products/shoe.jpg' width={600} height={600} zoomScale={2} alt='Nike Air Max 90 - Side view' className='product-zoom' transitionTime={0.15} /> ``` ### Gallery with Custom Styling ```tsx <Zoom src='/gallery/photo.jpg' width='100%' height={400} zoomScale={3} alt='Landscape photography' objectFit='cover' transitionTimingFunction='ease-in-out' style={{ borderRadius: '12px', border: '2px solid #e0e0e0', }} /> ``` ### Mobile-Optimized ```tsx <Zoom src='/mobile-image.jpg' width={300} height={300} zoomScale={2.5} enableTouch={true} throttleDelay={20} alt='Mobile optimized image' /> ``` ### Portrait Image with Custom Positioning ```tsx <Zoom src='/portrait-photo.jpg' width={400} height={600} zoomScale={2.5} objectFit='contain' objectPosition='center' alt='Portrait photography' style={{ borderRadius: '8px', border: '2px solid #ddd', }} /> ``` ## License MIT ## Contributing Contributions are welcome! Please feel free to submit a Pull Request.