Coder Social home page Coder Social logo

sylvaindubus / react-prismazoom Goto Github PK

View Code? Open in Web Editor NEW
137.0 4.0 32.0 28.81 MB

A pan and zoom component for React, using CSS transformations.

License: Other

JavaScript 26.59% TypeScript 73.41%
react react-component zoom pan drag pinch-to-zoom css3 css3-animations

react-prismazoom's Introduction

react-prismazoom

About

A pan and zoom component for React, using CSS transformations.

Depends only upon prop-types, react and react-dom modules.
Works on both desktop and mobile.

Online demo here!

Zoom features ๐Ÿ”Ž

  • Zoom with the mouse wheel or a two-finger pinch
  • Zoom using double-click or double-tap
  • Zoom on the selected area and center

Pan features ๐Ÿ‘†

  • Pan with the mouse pointer or with one finger when zoomed-in
  • Intuitive panning depending on available space when zoomed-in
  • Adjusts cursor style to indicate in which direction the element can be moved

Contribution

If you want to contribute, feel free to send a merge request or open a discussion. Currently, I just have time to maintain the package, but not enough to make big changes or add important features.

All contributions would be quite appreciated! ๐Ÿ˜‰

Among changes I would like to apply: - Migrate to TypeScript - Transform to a functional component (that could help split the code)

  • Make motion logic less dependent to React
  • Replace Enzyme with another testing library

Breaking changes on v3

  • The locked prop has been replaced by allowZoom and allowPan to handle zooming and panning events separately

Breaking changes on v2

  • The package now requires React v16.3 or higher (to use react references)
  • The zoom feature through gestures or the mouse wheel got some improvements to react better with all devices. You may need to adjust the scrollVelocity property passed to the component to keep the same effect.

Installation

Install the component

$ npm i -D react-prismazoom

Install the demo

This project includes a full-featured application demo.

First clone the project.

Go to the subfolder:

$ cd demo

Then, install it:

$ npm ci

Run the Webpack Dev Server:

$ npm start

Run unit tests

โš ๏ธ There are no unit tests anymore since the previously used library is deprecated and doesn't support React 18. The current test suite needs to be adapted using a different library.

Usage

Implementation

import PrismaZoom from 'react-prismazoom'

<PrismaZoom>
  <img src="my-image.png" />
  <p>A text that can be zoomed and dragged</p>
</PrismaZoom>

Props

Name Type Default Description
className string None Class name to apply on the zoom wrapper.
style object None Style to apply on the zoom wrapper. Note that transform, transition, cursor, touch-action and will-change cannot be overridden. Example: style={{backgroundColor: 'red'}}.
minZoom number 1 Minimum zoom ratio.
maxZoom number 5 Maximum zoom ratio.
scrollVelocity number 0.1 Zoom increment or decrement on each scroll wheel detection.
onZoomChange function null Function called each time the zoom value changes.
onPanChange function null Function called each time the posX or posY value changes (aka images was panned).
animDuration number 0.25 Animation duration (in seconds).
doubleTouchMaxDelay number 300 Max delay between two taps to consider a double tap (in milliseconds).
decelerationDuration number 750 Decelerating movement duration after a mouse up or a touch end event (in milliseconds).
allowZoom boolean true Enable or disable zooming in place.
allowPan boolean true Enable or disable panning in place.
allowTouchEvents boolean false Enables touch event propagation.
allowParentPanning boolean false When enabled, allows the parent element/page to pan with single-finger touch events as long as zoom = 1.
allowWheel boolean true Enable or disable mouse wheel and touchpad zooming in place
ignoredMouseButtons number[] [] Optional array of ignored mouse buttons allows to prevent panning for specific mouse buttons. By default all mouse buttons are enabled. MDN

Note: all props are optional.

Public Methods

These functions can be called from parent components.

zoomIn (value) Increments the zoom with the given value. Param {value: Number} : Zoom value

zoomOut (value) Decrements the zoom with the given value. Param {value: Number} : Zoom value

zoomToZone (relX, relY, relWidth, relHeight) Zoom in on the specified zone with the given relative coordinates and dimensions. Param {relX: Number}: Relative X position of the zone left-top corner in pixels Param {relY: Number}: Relative Y position of the zone left-top corner in pixels Param {relWidth: Number}: Zone width in pixels Param {relHeight: Number}: Zone height in pixels

reset () Resets the component to its initial state.

getZoom () Returns the current zoom value. Return {Number} : Zone value

License

React PrismaZoom is licensed under the ISC license. See the LICENSE.md file for more details.

react-prismazoom's People

Contributors

apomelitos avatar erickriva avatar fkrauthan avatar frozen-byte avatar gregorjan avatar jcerdenia avatar jennifergoijman avatar rbrownstein-bd avatar saadtaimoor-tfd avatar sbekaert avatar sylvaindubus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-prismazoom's Issues

Support for embedding inside container

It looks as if the calculation for the right limit uses the document boundaries:

    // Get horizontal limits using specified horizontal boundaries
    const [leftLimit, rightLimit] = [
      leftBoundary,
      document.body.clientWidth - rightBoundary
    ]

Is it possible to use the bounding rect instead? It looks like there's already some kind of support for container bounds instead:

    // Get container and container's parent coordinates
    const rect = this.ref.current.getBoundingClientRect()
    const parentRect = this.ref.current.parentNode.getBoundingClientRect()

Is it possible to just use parentRect instead of document.body?

Zoom using double-click ignoring position

Using double-click the image zooms in to the center and ignores the event position.
I expected it to zoom in on the position I clicked.

Tested in current Chrome and Firefox.

Expose `setPos` and `setZoom` to `ref`

I have a use-case where I need to sync a couple of PrismaZoom objects. For that I need to be able to set position and zoom with fixed values (base on the event listeners). In older versions I was able to just use setState directly. But the new version doesn't have that capability anymore.

Scroll in PrizmaZoom

Hi everyone! I have some problem: then I use PrizmaZoom for my component I cannot use scroll for my pictures in component. I have pictures that are mapping one by one to column (I use flex-direction : column, then my flag "verticalPages" is true). The simplified code is:

pages.map((page, pageIndex) => (


<img
className={h-full w-full ${ verticalPages ? "" : "border-l-2" } border-black}
ref={(el) => {
imageRef.current = {
...imageRef?.current,
[pageIndex]: el,
};
}}
src={https:${page.BasePath}${ isSmall.width <= 768 ? 4 : 6 }/${page.FileName}}
alt="page"
/>

  And If I take away <PrismaZoom> - I can scroll my pages up and down, but with One - it impossible((( or may be I do something wrong? In principle, does it possible to use scroll and zoom together? 

Updating allowPan or allowZoom props has no effect

Hi, I am trying to use this nice component to allow users to edit a large SVG. However, I have various edit modes where certain ones are supposed to disable any changes to the current pan or zoom so that they can perform other actions. I figured changing the value of allowPan and allowZoom would be reflected. However, it seems that this doesn't cause any effect.

My hunch is that the useEffect needs to list allowPan and allowZoom (probably also most of the other props too) as dependencies and the event listener functions should be moved to be defined in the useEffect? However, I am fairly new to react, so I would appreciate any input you have or if I missed something obvious.

See this codesandbox reproduction.

EDIT: I played around with the code and just adding the props to the useEffect dependencies seems to make this work, but react exhaustive dependencies recommends to define the handler functions in the useEffect as well.

Move method removed?

In version 3.1.1 the ref object has a move method available on it. This allows us to implement panning via arrow keys. This method appears to have been removed in version 3.3.1. (zoomToZone doesn't seem to provide the same functionality.)

Is there a way to access the move method in 3.3.1, or a different way to enable keyboard navigation?

Pan does not work with React 18

Hello all

just upgraded to React 18.1.0 and have noticed that the pan no longer works. Please test it yourself - there are also problems on mobile devices. I'll downgrade to React 17 until a solution was found. I am looking forward to it...

How to limit panning to size of container element?

We have a defined rectangle on screen in which an image will be displayed. We want the user to be able to zoom in and pan the image, but still within these defined boundaries.

However, if we wrap PrismaZoon around the image, it will allow the user to pan the image outside the container. It is even possible to push it completely out of viewport, so the empty container is the only thing the user will see. This "over-panning" even happens if we set the overflow of the ancestor elements to hidden. This works on Google Chrome, but not on iOS.

Also, we noticed that all pen gestures are propagated to the underlying elements, even if they are not ancestors of the PrismaZoom element. In our use-case, we are using PrismaZoom within a "lightbox" (image on top of a dark-transparent background) which sits inside Bootstrap React modal. Beneath the modal is content which is pannable as well (a horizontal slider). If we pan the image inside PrismaZoom, the content of the main page (i.e. the slider underneath the modal) will be panned as well. Setting allowTouchEvents to false did not change anything.

Last but not least: We would like to close our lightbox modal when the user taps on the image. But this onClick is not being propagated to the ancestor element, and there's no onClick handler on PrismaZoom either.

doubleClickZoom

Hi! I would like to disable the zoom for double click, how to do it?

Demo images are being cropped

In the demo App.css entry .App-image background-size: cover prevents the entire image from being displayed. Setting it to background-size: contain will display the complete image.

Whether or not this is an issue, I'll leave that to the maintainer(s), just an observation.

React component props

Hi! I would like set React props in component like onClick, onDoubleClick, ref,.., but i have no do it, why?
Okay, ref i can set, but it is doesn't written at README. I think it need to add in README.

Default Value and minZoom.

Is there any way to set a default value? Also, when attempting to set minZoom to a value lower than 1 (minZoom={1}), the system becomes inoperable. Is there a way to set minZoom to a lower value than 1, as I'd like to be able to zoom out if the image is particularly wide.

Love this package btw, thanks for your work!

Touch events don't propagate on mobile devices

So for some reason it seems like touch events have issues on mobile devices. I had to do the following changes to get it working:

Remove event.preventDefault(); for the following three events: handleTouchStart, handleTouchMove and handleTouchStop

My use case is that I have an image and then ontop of that overlayed a couple of reactstrap UncontrolledTooltip elements. It works totally fine out of the box on desktop. But on mobile it was not triggering the tooltip on tab as expected without the above modifications.

Note: This only happens on a real mobile device. The Chrome emulator was working as expected.

Is it possible to not have the zoom affect the whole page

As stated, I would like to have a container for the image and have the zoom only affect that part of the webpage (leaving rest of the page unaffected). At the moment when you zoom in it zooms the whole webpage in hiding crucial parts of the page. Is this package not meant for something like this or is it somehow possible?

Thanks in advance!

Using public methods

Hello, can you give an example for using public methods, especially reset. I would like to reset the zoomer programmatically. I mean I would like to add a global reset button.

Thanks in advance.

Pinch doesn't work when pan is disabled

Hi!

There is an issue after version 3.0.0. Pinch to zoom doesn't work on mobile devices when using this prop: allowPan={false}.

Love this package btw, thanks for your work!

Option to disable panning?

Love this package, very easy to use.

Would it be possible to add a prop to disable panning or dragging, or otherwise disable the component completely while frozen at a specific zoom value? I'd like to be able to zoom at a particular point in an image, and have the mouse free to perform other operations on the image while frozen there.

Hope you'll consider it, and thanks for the great package!

Pinch doesn't work after version 2.0.0

Hi! Thanks for the plugin!

There is an issue after version 2.0.0. Basically, pinch and touch events don't work on desktop ( normal mode ). They only work with developer tools "on". I didn't find why, but after downgrade to version 2.0.0. everything started to work. But as version 2.0.0 has a different approach, I used negative boundaries to fix the "off-screen issues". Still, if you double click on edge of the screen very fast it will go "off the screen".

By the way, your demo is working because it's built on an older version of the plugin.

P.S. Sorry, I don't have a fast solution for this issue. I just played with negative boundaries and it seems to work.

I hope, I helped someone

Regards

how to typify ref?

In your demo I see this typing ref
image
What is the ComponentRef?
I don't understand how I can do typing :(

Is there any way to apply prsimazoom on react-pdf Pages separately?

I applied prismazoom on the array of pages created by Page of react-pdf. and on zoomout, it takes me back to the first page itself.I tried applying this inside the array where i am rendering per page, wrapped it like {Array.from(arr,()=> )} but doing this displays only one page.

Cannot read property 'getBoundingClientRect' of null

Problem

I've attached the Sentry error below and all extra information
image
image
image

package versions

"react-prismazoom": "^2.0.1"
"react": "^17.0.2"
"react-scripts": "^4.0.3"
"node": ">=10.0.0"

Implementation

carbon

I haven't been able to replicate and I wonder if you have any ideas?

Thanks!

When using mouse wheel zoom getting "Unable to preventDefault inside passive event listener due to target being treated as passive"

Full error shown in Chrome 87.0.4280.67

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312

My React component:

function Photo({ imageData }) {
  return (
    <PrismaZoom>
      <img src={imageData} />
    </PrismaZoom>
  );
}

The link in the error takes me to a general issues page... but seems to be a Chrome issue, not getting it in Safari.

React 17

Can the peer dependencies be updated to include React 17? It seems to work fine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.