1.0.2 • Published 12 months ago

react-image-magnifier-waft v1.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
12 months ago

A responsive React image zoom component for touch and mouse.

Designed for shopping site product detail.

Features Include:

  • In-place and side-by-side image enlargement
  • Positive or negative space guide lens options
  • Interaction hint
  • Configurable enlarged image dimensions
  • Optional enlarged image external render
  • Hover intent
  • Long-press gesture
  • Fade transitions
  • Basic react-slick carousel support

Status

npm License

Author: Waft Technology

Demo

Coming soon* but works same like react-image-magnify package

Installation

npm install easy-magnify-waft

Usage

Usage is pretty simple. Remember: using latest version of this package is always recommended

import ReactImageMagnify from 'easy-magnify-waft';
...
<ReactImageMagnify {...{
    smallImage: {
        alt: 'redmi-phone',
        isFluidWidth: true,
        src: "assets/images/redmi-300.png"
    },
    largeImage: {
        src: "assets/images/redmi-1200.png",
        width: 1200,
        height: 1800
    }
    enlargedImageStyle: {
        objectFit: "contain",
    },
    enlargedImagePortalId: "ProductMagnify or preferred portal id",
    enlargedImageContainerClassName: "enlargeImage or preferred portal class",
    className: "magnifyimg or preferred portal class",
}} />
...
    ./styles.css;

    .enlargeImage img {
        max-width: none;
    }

    .enlargeImage {
        background-color: #ffffff;
        border: none !important;
        box-shadow: rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em,
            rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em,
            rgba(255, 255, 255, 0.1) 0px 0px 0px 1px inset;
    }

    // This is the portal div with portal id
    #ProductMagnify {
        position: absolute;
        left: 1%;
        top: 0;
        z-index: 9;
        transform: scale(0);
        opacity: 0;
        transition: all 0.2s ease-in-out;
    }

    // This div is added above the ReactImageMagnify component and is used to show the magnified image when hovered
    .ProExternaldiv:hover #ProductMagnify {
        left: 50%; /** Adjust left from your main div accordingly **/
        transform: scale(1.25); /** Scale magnified image accordingly **/
        opacity: 1;
    }

    .magnifyimg > img {
        /** Magnified Image Classs **/
    }

Usage with external carousel library such as react-responsive-carousel is very simple. In this case if you want your portal element outside of the your react magnify component scope you can target and change the style of the portal element using plain JS just targetting the element and changing it's opacity and scale value.

import ReactImageMagnify from 'easy-magnify-waft';
import { Carousel } from "react-responsive-carousel";
import "react-responsive-carousel/lib/styles/carousel.min.css";

  const handleMouseEnter = () => {
    const elem = document.getElementById("ProductMagnify"); // Your preferred portal id
    if (elem) {
      elem.style.opacity = 1;
      elem.style.transform = `scale(1.25)`;
      elem.style.left = "50%";
    }
  };

  const handleMouseLeave = () => {
    const elem = document.getElementById("ProductMagnify"); // Your preferred portal id
    if (elem) {
      elem.style.opacity = 0;
      elem.style.transform = `scale(0)`;
    }
  };

    // ** Note you can achieve this using css also. But in this approach my portal div is outside of the magnify scope, I am using js to target the elem and change it's style.
...
    <div
        className="w-1/3"
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        <Carousel
          showIndicators={false}
          renderThumbs={() =>
            images.map((each) => (
              <Fragment key={each.thumbnail}>
                <img
                  src={each.thumbnail}
                  alt={each.thumbnail}
                  className="w-[80px] h-[78px] object-contain"
                />
              </Fragment>
            ))
          }
        >
          {images.map((each) => (
            <Fragment key={each.original}>
              <ReactImageMagnify
                className="magnifyimg"
                {...{
                  smallImage: {
                    alt: "Testing",
                    imageClassName: "magnifyimgA w-full h-full object-contain",
                    src: each.original,
                    isFluidWidth: true,
                  },
                  largeImage: {
                    alt: "Testing",
                    src: each.original,
                    width: 1024,
                    height: 1024,
                  },
                  enlargedImageStyle: {
                    objectFit: "contain",
                  },
                  enlargedImagePortalId: "ProductMagnify",
                  enlargedImageContainerClassName: "enlargeImage",
                  shouldUsePositiveSpaceLens: false,
                }}
              />
            </Fragment>
          ))}
        </Carousel>
      </div>
      <div className="w-2/3 relative">
        <div id="ProductMagnify" />
        <div className="text-2xl font-bold">Another Div (outside of component scope)</div>
    </div>
...

Required Props

PropTypeDefaultDescription
smallImageObjectN/ASmall image information. See Small Image below.
largeImageObjectN/ALarge image information. See Large Image below.

Optional Styling Props

PropTypeDefaultDescription
classNameStringN/ACSS class applied to root container element.
styleObjectN/AStyle applied to root container element.
imageClassNameStringN/ACSS class applied to small image element.
imageStyleObjectN/AStyle applied to small image element.
lensStyleObjectN/AStyle applied to tinted lens.
enlargedImageContainerClassNameStringN/ACSS class applied to enlarged image container element.
enlargedImageContainerStyleObjectN/AStyle applied to enlarged image container element.
enlargedImageClassNameStringN/ACSS class applied to enlarged image element.
enlargedImageStyleObjectN/AStyle applied to enlarged image element.

Optional Interaction Props

PropTypeDefaultDescription
fadeDurationInMsNumber300Milliseconds duration of magnified image fade in/fade out.
hoverDelayInMsNumber250Milliseconds to delay hover trigger.
hoverOffDelayInMsNumber150Milliseconds to delay hover-off trigger.
isActivatedOnTouchBooleanfalseActivate magnification immediately on touch. May impact scrolling.
pressDurationNumber500Milliseconds to delay long-press activation (long touch).
pressMoveThresholdNumber5Pixels of movement allowed during long-press activation.

Optional Behavioral Props

PropTypeDefaultDescription
enlargedImagePositionStringbeside (over for touch)Enlarged image placement. Can be 'beside' or 'over'.
enlargedImageContainerDimensionsObject{width: '100%', height: '100%'}Specify enlarged image container dimensions as an object with width and height properties. Values may be expressed as a percentage (e.g. '150%') or a number (e.g. 200). Percentage is based on small image dimension. Number is pixels. Not applied when enlargedImagePosition is set to 'over', the default for touch input.
enlargedImagePortalIdStringN/ARender enlarged image into an HTML element of your choosing by specifying the target element id. Requires React v16. Ignored for touch input by default - see isEnlargedImagePortalEnabledForTouch.
isEnlargedImagePortalEnabledForTouchBooleanfalseSpecify portal rendering should be honored for touch input.
hintComponentFunction(Provided)Reference to a component class or functional component. A Default is provided.
shouldHideHintAfterFirstActivationBooleantrueOnly show hint until the first interaction begins.
isHintEnabledBooleanfalseEnable hint feature.
hintTextMouseStringHover to ZoomHint text for mouse.
hintTextTouchStringLong-Touch to ZoomHint text for touch.
shouldUsePositiveSpaceLensBooleanfalseSpecify a positive space lens in place of the default negative space lens.
lensComponentFunction(Provided)Specify a custom lens component.

Small Image

{
    src: String, (required)
    srcSet: String,
    sizes: String,
    width: Number, (required if isFluidWidth is not set)
    height: Number, (required if isFluidWidth is not set)
    isFluidWidth: Boolean, (default false)
    alt: String,
    onLoad: Function,
    onError: Function
}

For more information on responsive images, please try these resources:
Responsive Images 101
Responsive Images - The srcset and sizes Attributes

Large Image

{
    src: String, (required)
    srcSet: String,
    sizes: String,
    width: Number, (required)
    height: Number, (required)
    alt: String, (defaults to empty string)
    onLoad: Function,
    onError: Function
}

Support

Please open an issue.

Contributing

Please contribute using Github Flow. Create a branch, add commits, and open a pull request.