Hey Sam, very cool video. I maintain react-use-gesture and wanted to add some additional insights on why you need "touch-action: none" and use non-passive events by setting "eventOptions: { passive: false }". So setting "touch-action: none" is a way to tell mobile browsers that interacting with the element shouldn't trigger any browser scrolling or zooming. Even when you're simply dragging an element (I say this because in the video you're adding touch-action when you move to the pinch gesture), there is a chance that your interaction might be interpreted as a scroll by the browser, so you should almost always want to set "touch-action: none" even when using the drag gesture (note that there are other properties such as 'pan-y', 'pan-x', I won't go into these details here). Now about "eventOptions: { passive: false }": it's a bit more complex. You don't need this on mobile because as seen above "touch-action: none" already takes care of preventing natural browser interaction. But here is what happens on desktop: zooming with your trackpad actually triggers a WheelEvent with the ctrlKey set to 1, and the browser natively interprets this as "the user wants to zoom on the page". Even on non multi-touch trackpads you can emulate the zoom behavior by simply scrolling on your trackpad and pressing the ctrl key. All that react-use-gesture detects is just a WheelEvent. Because the ctrl key is pressed, the lib understands that you want to zoom on the element. The problem is that there's no "wheel-action" property to indicate the browser that it shouldn't zoom on the whole page. So the lib tries to prevent the default behavior on the WheelEvent, to prevent the browser from zooming on the whole page by calling "event.preventDefault()". Now here is where it gets tricky: when you add event listeners for wheel or scroll, Chrome sets them as "passive" by default, for performance reasons (last time I checked, Chrome was the only browser to use passive events). And you can't prevent default on a passive event. So whenever the react-use-gesture detects a pinch gesture triggered by a WheelEvent with the ctrlKey pressed, it flags a warning on your console if it sees that the event isn't cancelable. This is why you need to set passive to false: to let react-use-gesture cancel WheelEvent on Chrome to correctly handle zoom. Addendum: to make things even worse, when you pass the wheel handler to a component the way React wants you to do it (like let's say " e.preventDefault()} />"), you'll get an error on Chrome: in fact, there's no way to tell React to add non-passive listeners, so all React handlers get passive, non cancelable events. And therefore, to support pinch with a trackpad, react-use-gesture asks you to use the "domTarget" option (which is what you're doing in the video) so that it can actually add events to the target via "domTarget.addEventListener('wheel', handleWheel, { passive: false })". Then and only then the events become cancelable and the pinch gesture can support trackpad zooming. Sorry for the long comment but these are things that were hard to figure out for and I thought I would make them clear as I understand they can feel a bit confusing for developers.
@samselikoff4 жыл бұрын
Meant to say thank you for this info! And thanks so much for your work on the library :) It sure seems like if there were such a thing as "wheel-action: none" that would be the simplest thing, because then we could use the typical way to attach event handlers (e.g. onWheel). Do you know if it's being worked on in the browser?
@DavidBismut4 жыл бұрын
@@samselikoff sorry to reply this late I’m not used to KZbin notifications. I don’t think this is planned unfortunately or maybe there’s a secret property I don’t know 🤷♂️
@unmy4004 жыл бұрын
nice !! thanks for the video Sam, i'm looking forward for the next ones ! 🚀
@agusterodin4 жыл бұрын
Hey, you make awesome videos. Thank you so much! Would love to see pinch to zoom based on where you pinched in future parts.
@samselikoff4 жыл бұрын
Coming in the next episode 😉
@uxweb4 жыл бұрын
Awesome Sam! I am building a UI to display a fullscreen image and let the user to zoom and pan the image, this is going to help me improve the user experience. Thank you!
@agusterodin3 жыл бұрын
Were you able to figure out how to get the cropped result?
@helloghoul3 жыл бұрын
Great video! Was very useful. Thanks for posting 😁
@swyxTV4 жыл бұрын
nice video and love the sweater! the pinching seems centered on the image center - any tricks on how to scale based on the start point of the pinch?
@HkanAktas4 жыл бұрын
Since the browser won't handle transform-offset changes gracefully (it'll be jumpy), one should probably move the x and the y away from pinch point when zooming in, and move them closer to pinch point on zoom out. I bet it gets pretty complicated unlike the simplistic example we have seen in the video.
@samselikoff4 жыл бұрын
Great question - will be sure to address this in the series!
@DavidBismut4 жыл бұрын
Here you go - doesn't work with rotate yet as it would probably require advanced calculations, but it does with zoom (on desktop, didn't test on mobile but I'm pretty sure it should work as well) codesandbox.io/s/boring-hertz-sokxs
@DavidBismut4 жыл бұрын
@@HkanAktas That's indeed the logic but it's not THAT complicated codesandbox.io/s/boring-hertz-sokxs
@devstefancho2 жыл бұрын
Thank for a great video! How to screen sharing ipad with mac? I want to test touch gesture on the ipad and also simultaneously see chrome console tab on the desktop
@mohammedg4853 жыл бұрын
wow thats impressive ... we need more of that .. keep it up
@tegaogheneovo58813 жыл бұрын
0:19 Please bro is this react and how Did you make it fullscreen like that. Thanks
@connerkennedy6691 Жыл бұрын
Does this work for SVG images as well? I want my SVG to remain interactable and zoomable
@AndroapkzoneBlogspotInapps2 жыл бұрын
Great video. I implemented as well. But how to disable zoom in and zoom out on mouse scroll?
@thedyslexicwebdev1654 Жыл бұрын
Amazing, thank you so much!!
@nazarm62153 жыл бұрын
Really good explanation. I want to know how cancel works. Guess I gotta dig deeper into the implementation and find out.
@dimitardimitrov49794 жыл бұрын
Amazing content! Love it!
@ВладиславПузырев-ю8л3 жыл бұрын
I have onPinch triggered if you hold down ctrl and turn the mouse wheel
@nawal77213 жыл бұрын
Hi Sam my image does not seem to drag smoothly like yours. The image only drags by very few pixels and then i have to press click and drag again. Any suggestions? Thanks for the video
@samselikoff3 жыл бұрын
It might be because you're on desktop and you'll need to add some extra rules. Try adding touchAction/userSelect rules as seen here: github.com/samselikoff/2020-12-15-image-cropper/blob/9d38f99d1921f22e0c5ed33981542c0ea444c6b1/pages/index.js#L155-L158 There's also some info about it in the docs: use-gesture.netlify.app/docs/faq/#why-cant-i-properly-drag-an-image-or-a-link
@nawal77213 жыл бұрын
@@samselikoff Thank you Sam for your response. To fix the drag I had to use style={{ transform: `translate(${drag.x}px, ${drag.y}px) scale(${zoomScale}) , touchAction: 'none'`}} Anyway thank you for your content. They are unique to the other developers on youtube. I like how you do deep dive to the problems/solutions and communicate that to us. Special channel. Please keep it the content going!
@samselikoff3 жыл бұрын
@@nawal7721 You're so welcome and I'm glad you figured it out! Definitely check out the rest of the series as I think you'll like the Framer Motion API. Lets you do scale={zoomScale} x={drag.x}, stuff like that. Simplifies the code a bit and uses requestAnimationFrame to ensure to performance!
@rajdeepchandra98072 жыл бұрын
Can we do these on objects on the canvas?
@surjithctly4 жыл бұрын
Can you do a video on how can we mimic the iOS Partial Modal (The Swipe up Modal) on Web? Working: Once you click a button, the modal will open Halfway with a grey bar on top indicate you can move up further. Then when we swipe, the modal goes taller and reach top with a curved border.
@무혜-z2j Жыл бұрын
Really cool
@Hangoutapp3 жыл бұрын
Thanks for the code.
@РусланКононов-ч9я4 жыл бұрын
Hi, thanks for your videos on this library, it helps me a lot in my work, please tell me how I can add a delay to the onDrag effect to make it smoother
@samselikoff4 жыл бұрын
This would involve adding Framer Motion or React Spring and animating the changing values. I was hoping to be farther along in the series by now but we will get there soon!
@star_gazer_14373 жыл бұрын
Can anyone tell how can we stop the 360 rotation of the image?
@bhatkanti97443 жыл бұрын
can we use it in reactJS?
@agusterodin3 жыл бұрын
Does anyone know how to get the cropped result? Trying to do it with canvases.
@agusterodin3 жыл бұрын
I've come to the conclusion that computing the result from outside the cropper component is impossible with the given setup. Ideally it would be nice to have enough information in state to be able to compute this from outside the component. I am aware that computing the result inside of the component is trivial since we can get bounding rectangles of both container and image as well as intrinsic image size. In my case I wanted to be able to perform the crop operation in a redux saga task before sending post request to the server. The only way I see get result from outside of component is possible is by having this functional component contain a getResult function that returns minX, minY, maxX, maxY where X and Y refer to dimensions of original image. You could then access this function from outside the component by the means of forwardRef. It makes me wonder if storing state as minX, minY, maxX, maxY (where X and Y refer to dimensions of the original image) would be better than x, y, and scale currently used. The real challenge would be making sure you could derive transforms in a performant way and even harder would be retaining the animations. Storing state in this alternate way could also enable centering of image when initially shown which is something I would really like on the app I'm working on. Thoughts?
@samselikoff3 жыл бұрын
@@agusterodin I added an onCropChange callback to the latest version of my image cropper, check out this gist for an example! gist.github.com/samselikoff/4a4e8d5e0ae7dcc1f2eb5149c1362e0c
@agusterodin3 жыл бұрын
@@samselikoff God bless you
@agusterodin3 жыл бұрын
@@samselikoff I tried pinging you on Twitter too so not sure if you saw but I was planning on adding keyboard navigation (+/- for zoom on current center, arrow keys to move around). Container div would be made focusable and would have a nice little focus-visible ring. Would be a nice a11y addition to this series if you were planning on expanding on it more. Would be trivial compared to the rest of the cropper but I will gladly share my implementation once done.
@jeffhicks60684 жыл бұрын
Very cool
@ThanHtutZaw3 Жыл бұрын
you forget to mention how to get drag snap like intro
@Iammrunkown3 жыл бұрын
use react-spring instead of react state for animating
@cryptoknight72564 жыл бұрын
I can easily use your code in react native too, correct?
@samselikoff4 жыл бұрын
I haven’t tried but I believe so!
@agusterodin3 жыл бұрын
This cropper does not work with portrait images
@agusterodin3 жыл бұрын
I was able to figure out a good solution: compute the image orientation before showing the page that contains the cropper and do something like this className={`relative ${orientation === 'portrait' ? 'w-full h-auto' : 'w-auto h-full'} max-w-none max-h-none`}
@ruairidhgrass3479 Жыл бұрын
Seems like this only works on mobile :/
@eminqasimovdev4 жыл бұрын
i wait framer vs react spring
@samselikoff4 жыл бұрын
These days I’m investing Framer Motion since react spring has been in a beta version for over a year