0.3.7 • Published 5 months ago

react-image-pan-and-zoom-with-commenting v0.3.7

Weekly downloads
-
License
CC0 1.0 Universal
Repository
github
Last release
5 months ago

React Image Pan And Zoom With Commenting

Screenshot

Nifty Gateway has developed a React component for image pan and zoom, allowing users to comment on any part of an image. This component was recently utilized in a project with Sam Spratt called the Monument Game. It enables users to zoom and pan around a 20,000-pixel-wide image, creating a more interactive and immersive user experience.

The component can function independently as a standalone image pan and zoom viewer. However, if you aim to support commenting, the component offers the necessary properties for integration with your custom backend. Moreover, if commenting is enabled, and comments are persisted to your backend, you can deep-link to a specific comment via query parameters in the URL (?x=0.6016064257028112&y=0.6058201058201058). Simply provide the x and y coordinates, and the component will load the pan and zoom experience, highlighting the specified comment at those coordinates.

Why Do I Need to Provide A Src and SmallerSrc?

For desktop use, if you're employing an image with a width equal to or less than 10,000 pixels, props.smallerSrc can be left undefined. However, for larger images, providing an image for props.smallerSrc may enhance zoom performance. The image specified for props.smallerSrc will only be displayed when a user zooms in and if the current zoom width of an image is less than or equal to the intrinsic width of props.smallerSrc. During development, we discovered that the Chrome browser struggles to provide a smooth zooming experience for images beyond 10,000 pixels in width. To address this issue, we introduced the option to supply a lower resolution image for display during zoom, significantly improving performance in Chrome browsers.

For mobile use, it's advisable to limit the maximum width of an image to 10,000 pixels. During development, we found that using an image exceeding 10,000 pixels could randomly crash the browser or refresh the page. You can leave props.smallerSrc undefined, especially for images equal to or less than 5,000 pixels in width, but results may vary.

In the future, we plan to explore a version that supports image tiling. If you'd like to initiate work on this feature, feel free to open a pull request!

Data Flow Diagram on Commenting Flow

You can also take a look at the usage example below titled, Advanced Usage Showing How You can Tie in With A Custom Backend To Persist Comments

Screenshot

React Props

Prop NameDescriptionIs Required?Default ValueType
srcURL of main image to use for pan and zoomYesstring
smallerSrcURL of the main image on a smaller scale, used for pan and zoom. Displayed during zoom and after zoom if the current zoom width is <= intrinsic width of the provided imageOptionalundefinedstring OR undefined
previewBoxSrcURL of the image displayed in the pan and zoom preview box. Image width should be no larger than 100 pixelsYesstring
commentsList of comments and their coordinatesOptionalundefined{ x: number, y: number, comment: string}[] OR undefined
isLoadingFlag to indicate whether we are some loading stateOptionalFALSEboolean
panAndZoomEnabledOnMountFlag to indicate whether pan and zoom should be enabled on initial mountOptionalFALSEboolean
isCommentSubmitLoadingFlag to indicate whether we are in loading state for submitting a new commentOptionalFALSEboolean
enableCommentDropFlag to toggle whether we allow comments to be dropped when pan and zoom is activeOptionalTRUEboolean
enablePanAndZoomControlsFlag to toggle display of pan and zoom controls (ie. zoom in/out button and reset zoom button)OptionalTRUEboolean
enablePanAndZoomPreviewFlag to toggle the display of a smaller version of the image indicating your current pan location locationOptionalTRUEboolean
persistCommentDrawerWhenOpenFlag to toggle whether the Comment Drawer stays open while the user interacts with pan and zoom. Recommended to set to false for better mobile user experienceOptionalTRUEboolean
addingCommentsToTheFrontFlag to indicate whether new comments are being added to the front of the comments array or at the endOptionalFALSEboolean
zoomToPercentNumeric value between 25-50 to indicate what percent value to set when a user clicks on a comment within the Comment DrawerOptional50number
dotSizeNumeric value to indicate comment dot size in pixelsOptional20number
buttonEnablePanZoomTextText on button to enable pan and zoomOptionalObservestring
makeObservationTextText when pan and zoom is enabled and commenting is allowed to indicate a user can leave a commentOptionalMake Observationstring
commentDialogHeadingTextText for Comment Dialog headingOptionalWhat Do You See?string
commentDialogSecondaryHeadingTextText for Comment Dialog secondary headingOptionalMake an observation.string
commentDialogConfirmHeadingTextText for Comment Dialog confirmation headingOptionalConfirmationstring
commentDialogConfirmSecondaryHeadingTextText for Comment Dialog confirmation secondary headingOptionalAs a last step please confirm your submission. Once it's submitted, it can't be undone.string
commentDialogConfirmCheckboxTextText to accompany Comment Dialog checkboxOptionalI understand this can't be undonestring
commentDialogTextAreaPlaceholderTextPlaceholder text for Comment Dialog textareaOptionalstring
commentDialogCancelButtonTextText for Comment Dialog Cancel button when user is in pre-confirmation stateOptionalCancelstring
commentDialogBackButtonTextText for Comment Dialog Back button when user is in confirmation stateOptionalBackstring
commentDialogReviewButtonTextText for Comment Dialog Review button when user is in pre-confirmation stateOptionalReviewstring
commentDialogSubmitButtonTextText for Comment Dialog Submit button when user is in confirmation stateOptionalSubmitstring
primaryColorPrimary color (hex or rgba)Optional#fffstring
secondaryColorSecondary color (hex or rgba)Optional#000string
tertiaryColorTertiary color (hex or rgba)Optional#aaastring
dotColorComment dot color (hex or rgba)Optionalredstring
activeDotColorActive comment dot color (hex or rgba)Optionalorangestring
imgLoaderReact component or string to display when main image is loadingOptionalundefinedReact.ReactElement OR string OR undefined
zoomSupportLoaderReact component or string to display when zoom support image is being loaded. This will only come into play if you are using a very large image (10,000+ pixels in width) for props.srcOptionalundefinedReact.ReactElement OR string OR undefined
errorDisplayReact component or string to display when an error is encountered during main image loadOptionalundefinedReact.ReactElement OR string OR undefined
onCommentSubmitCallback function called when a new comment is submittedOptionalundefinedFunction OR undefined
onImageLoadCallback function called when the main image has loadedOptionalundefinedFunction OR undefined
onTogglePanAndZoomCallback function called when pan and zoom is toggled on/offOptionalundefinedFunction OR undefined

Demo

https://gemini-oss.github.io/react-image-pan-and-zoom-with-commenting/

Installation

yarn add react-image-pan-and-zoom-with-commenting
npm i react-image-pan-and-zoom-with-commenting

Basic Usage Image Pan And Zoom With Commenting

import ImagePanAndZoom from 'react-image-pan-and-zoom-with-commenting';

const App = () => {
    return (
        <ImagePanAndZoom src='LINK_TO_IMAGE' previewBoxSrc='LINK_TO_PREVIEW_IMAGE' />
    )
}

export default App

Basic Usage Image Pan And Zoom Only

import ImagePanAndZoom from 'react-image-pan-and-zoom-with-commenting';

const App = () => {
    return (
        <ImagePanAndZoom src='LINK_TO_IMAGE' previewBoxSrc='LINK_TO_PREVIEW_IMAGE' enableCommentDrop={false} />
    )
}

export default App

Advanced Usage Showing How You can Tie in With A Custom Backend To Persist Comments

import ImagePanAndZoom from 'react-image-pan-and-zoom-with-commenting';

const App = () => {
  const [isCommentSubmitLoading, setIsCommentSubmitLoading] =
    React.useState(false);
  const [isLoading, setIsLoading] = React.useState(true);
  const [comments, setComments] = React.useState<CommentDotProps[]>([]);

  const handleCommentSubmit = (comment: CommentDotProps) => {
    setIsCommentSubmitLoading(true);

    // Simulate a POST request to save a new comment
    setTimeout(() => {
      setComments([...comments, { ...comment }]);
      setIsCommentSubmitLoading(false);
    }, 3000);
  };

  React.useEffect(() => {
    // Simulate a GET request to retrieve existing comments 
    setTimeout(() => {
      setComments([
        {
          x: 0.6016064257028112,
          y: 0.6058201058201058,
          comment: "Lorem ipsum dolor sit amet. Et quod alias qui sequi labore est nostrum debitis sed officiis laborum qui ipsam consequuntur in rerum unde et recusandae quibusdam. Cum iste repudiandae sit sint placeat sed quia velit et quidem doloribus qui doloremque unde est asperiores similique.",
        },
        {
          x: 0.7653844927601894,
          y: 0.4520125762495482,
          comment:
            "Ut ipsum numquam qui expedita dolorem cum quaerat consequatur ut natus laudantium aut aspernatur laboriosam et asperiores assumenda. Ea voluptatem neque non quia laborum ut consequatur voluptatum in voluptas debitis et quisquam quidem. Ut ipsum numquam qui expedita dolorem cum quaerat consequatur ut natus laudantium aut aspernatur laboriosam et asperiores assumenda. Ea voluptatem neque non quia laborum ut consequatur voluptatum in voluptas debitis et quisquam quidem.",
        },
        {
          x: 0.45380107538609804,
          y: 0.6221498059102408,
          comment: "Rem aliquam galisum sed ducimus velit aut natus magni vel illum tempora est voluptatem vero et quam culpa eos sequi nostrum. Sed aliquam nihil ut fugit amet aut rerum dolorem et tempora voluptas et vitae repellendus et itaque dolor.",
        },
      ]);
      setIsLoading(false);
    }, 2000);
  }, []);

  return (
    <ImagePanAndZoom
      src='LINK_TO_IMAGE'
      previewBoxSrc='LINK_TO_PREVIEW_IMAGE'
      comments={comments}
      isLoading={isLoading}
      isCommentSubmitLoading={isCommentSubmitLoading}
      onCommentSubmit={handleCommentSubmit}
    />
  );
};

export default App

ClassNames You Can Target

ComponentDescriptionClassName
Active CommentComponent used to display an active comment.active-comment
Comment DialogComponent used to allow comment entry.comment-dialog
Comment Display SwitchComponent used to toggle comment display.comment-display-switch
Comment DrawerComponent used to display list of comments.comment-drawer
Comment Drawer BackdropComponent used to backdrop for list of comments.comment-drawer-tint
Dot ContainerContainer component to house comment dots.dot-container
Dot Container DotsComponent used for a comment dot.button--dot
Image Pan And ZoomComponent used for image pan and zoom.image-pan-and-zoom