Coder Social home page Coder Social logo

Comments (14)

smeijer avatar smeijer commented on August 25, 2024 2

Thanks for the assistance, the second sandbox turned out to be very informative after all. Your explanations are very clear, and much appreciated.

I would suggest adding that explanation about returning temp to the Frequently asked questions that already exists in the readme. It's very useful knowledge.

For whoever comes here after me, here is a sandbox to a working split-pane solution build on react-spring and react-use-gesture. Without rerenders, and only a single animated element. If you need more than 2 columns, I would recommend to nest this component and not to add 2 draggers in a single 'splitPane' component.

https://codesandbox.io/s/react-use-gesture-72v26

react-gestures-split-pane

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024 2

Just so you know, I've finally changed temp to memo, as I think of it as a sort of cached value. temp is still there if you need it with the same value as memo :)

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024 1

Sure, happy to help. I’ll ask the creator of this lib @drcmda what he thinks about a new name for temp!

from use-gesture.

satvikpendem avatar satvikpendem commented on August 25, 2024 1

Figured it out, new docs explain it: https://use-gesture.netlify.com/docs/options

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024

Hey @smeijer, thanks for taking the time to capture the gif and creating the sandbox.

I suspect the bug is only due to z-index messing up things. Here is a working example (at least it works with me):
https://codesandbox.io/s/react-use-gesture-07q16

I've also corrected some code: here is your original code commented with the problems highlighted.

const [[left, right], set] = useState([250, 250]);

const bind = useGesture({
  onDrag: ({ initial: [x], delta: [dx] }) => {
  /* Here x will be the initial x-axis position of the MOUSE.
   * What you want instead is the initial position of the red handle!
   * It might have worked fine in your case if your element is in the top left corner of the screen
   * but it wouldn't if it was positioned elsewhere.
   * The solution is to use the `temp` argument like in the sandbox above */
 
    const nextLeft = x + dx;
    const nextRight = left + right - nextLeft;

    set([nextLeft, nextRight]);
  },
});

The other problem here is that you're re-rendering your component on every drag update. You could use for example the react-spring library to prevent useless renders when animating. Here is a reworked example, optimized (I've also changed the structure so only one div animates its transform attribute - since it's less costly than animating width).

https://codesandbox.io/s/react-use-gesture-k4bwv

from use-gesture.

smeijer avatar smeijer commented on August 25, 2024

Thanks for the fast response. I'll try that first sandbox later tomorrow, but it seems to make sense.

The second sandbox wouldn't work for me though. As the elements left and right from the dragger will contain content, and thereby both need to be resized.

*edit, one quick question. You're returning temp from the onDrag, is it required? Does it do something?

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024

Whatever works best, but in any case make sure you’re not re-rendering your whole component on each drag frame. You will probably need to have several animated.div nodes but I think you can still work it out with only one spring value.

Yes it is required by design to return temp. Essentially temp is a gesture state attribute that is undefined when the gesture starts, but then takes the return value of the handler function.

In our case, we want temp to hold the original value of x when the gesture starts so that it becomes our point of reference when adding the delta. So we set temp to the value of x when temp is undefined.

If we don’t return temp, then temp will still be undefined and in the next drag frame temp will take again the value of x, which will have updated in the meantime (therefore not being the point of reference when the gesture starts anymore).

It may sound silly but returning temp makes sure that we continue holding a reference to the initial value of temp, ie the original value of x when the gesture started.

Hope this is somehow clear.

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024

Clever use of flex :) yeah I know that temp is yet a somewhat obscure area of this lib, there is a section dedicated to it in the read me but I agree that it doesn’t explain a lot. I also think the name doesn’t help!

from use-gesture.

smeijer avatar smeijer commented on August 25, 2024

Maybe naming it ref or reference would help? As I now understand it does pretty much the same as useRef from react. And return reference; or even return current; does sound more understandable than return temp;.

To close this chapter from my side, I created a reusable and nestable component for the SplitPane above. Hope it might be useful for anyone:

https://codesandbox.io/s/react-use-gesture-j9v2q

gestures-resizable-pane

Again; thanks for the fast response and explanations. Much appreciated.

from use-gesture.

satvikpendem avatar satvikpendem commented on August 25, 2024

I've been following this issue as it's similar to something I'm making as well, and I found a few bugs, at least for the latest versions of react-spring and react-use-gesture. I made a simple slider example shown below.

On versions 6.0.0 or greater of react-use-gesture, it looks like the cursor doesn't exactly follow the mouse, when the panel is clamped to a specific value. It goes over or under the mouse:

https://imgur.com/2jwwakw

However, on versions below 6, such as on 5.2.4, the drag handle only resizes the box while the pointer is directly underneath the drag handle:

https://imgur.com/TLRJ1jr

This feels like a regression to me, but there might be good reasons, or fixes available for it, not sure.

Here's the sandbox:

Edit React Use Gesture Simple

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024

Hey @satvikpendem thanks for taking the time to report the issue. Having a sandbox and gifs is indeed super helpful 👍

In this case though, the answer is pretty trivial: 6.x deprecated temp, and delta was relabeled movement (in 6.x delta is xy - previous to match common usage).

Here is the updated sandbox: https://codesandbox.io/s/react-use-gesture-simple-id76z

I've commented out another implementation that uses v7 new initial and bounds options for your reference. Also updated react-spring to latest canary (hence size.get() instead of size.getValue()).

from use-gesture.

satvikpendem avatar satvikpendem commented on August 25, 2024

Oh thanks, looks good. This may not be entirely react-use-gesture related, but I wanted to make a draggable box, like Google Calendar where you can click and drag to resize events. If there's content inside of them, then the size of the Panel changes, so when I do

const [{ size }, set] = useSpring(() => ({ size: 300 }))

I'm not sure what to put as the initial size instead of 300. Is there a way to dynamically set the initial size property based on the content inside an element? I know the dragging takes care of the size changes afterward.

Here's the sandbox:

https://codesandbox.io/s/react-use-gesture-simple-esw2x

from use-gesture.

dbismut avatar dbismut commented on August 25, 2024

It’s actually 100% react spring related. You’ll need to use a hook such as useMeasure that watches the height of the children and set your spring to its value.

from use-gesture.

satvikpendem avatar satvikpendem commented on August 25, 2024

I see, thanks. I'm using useGesture, is there a way to specify the config object like you showed in the most recent sandbox within the onDrag property? It looks like it just takes the state. I'm trying to do something like this:

const bind = useGesture(
    {
      onDrag: (
        // State
        ({ movement: [, movementY], down }) => {
          console.log(movementY)
          set({ size: movementY, immediate: down })
        },
        // Config
        {
          bounds: { top: minSize, bottom: maxSize },
          initial: () => [0, size.get()],
          rubberband: true
        }
      ),
      onHover: state => {
        console.log(state)
      }
    }

from use-gesture.

Related Issues (20)

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.