Jump to content
Search Community

Lark

Members
  • Posts

    23
  • Joined

  • Last visited

Posts posted by Lark

  1. Sandbox URL (it's with React):
    https://codesandbox.io/s/floral-feather-o4du95?file=/src/Box.tsx:642-648

     

    I would like to control a draggable via SVG, like in the example.

    I create an svg (instead of a g, because I want to easily position children elements relative to it), then I instantiate the draggable in a single-time useEffect, to work on the group but be triggered by the rect.

    Add a new box by clicking anywhere on the blue part. A box is created and should be placed in the clicked part by calling gsap.set, but it doesn't.

    I added a console.log during dragging so that you can see that the draggable IS moving, but not the element.

    How do I solve this?

  2. In actuality I do call kill, this was an example of how I tried using the context, but I see what I did wrong.

    Either way you did explain the problem by blaming React 18 and it does not exist in production .

    In my current codebase, I am calling kill on all four draggables in cleanup, with no context.

     

    Either way I get it now, thank you.

    • Like 2
  3. I'm sad to say that even with the context this issue does not go away in development.

      useLayoutEffect(() => {
        const ctx = gsap.context(() => {
          const gId = `#${elementIds.getGroupId(annotation.id)}`;
          const getDisplay = () =>
            document.getElementsByClassName(elementIds.transformWrapper)[0]!;
          const getDisplayBounds = () => getDisplay().getBoundingClientRect();
          const getBox = () =>
            document.getElementById(elementIds.getRectId(annotation.id))!;
          const getBoxBounds = () => getBox().getBoundingClientRect();
          const getWrapper = () =>
            document.getElementById(elementIds.imageWrapper)!;
          const getWrapperBounds = () => getWrapper().getBoundingClientRect();
          const updateBox = () =>
            gsap.set(`${gId}`, {
              x: annotation.box.x,
              y: annotation.box.y,
            });
    
          const $right = document.createElement('div');
          const $top = document.createElement('div');
          const $bottom = document.createElement('div');
          const $left = document.createElement('div');
    
          const topDraggable = new Draggable($top, {
            trigger: `${gId} .top, ${gId} .topRight, ${gId} .topLeft`,
            onDrag(event) {
              const scale = annotation.scale;
              const { top, bottom, height } = getBoxBounds();
              const { top: wTop } = getWrapperBounds();
              const { top: dTop } = getDisplayBounds();
              const mouse = Math.max(event.clientY, dTop, wTop);
    
              if (mouse >= bottom) {
                const diff = (mouse - bottom) / scale;
                const relativeBottom = annotation.box.y + annotation.box.height;
                annotation.box = { y: relativeBottom, height: diff };
                topDraggable.endDrag(event);
                bottomDraggable.startDrag(event);
              } else {
                const diff = (top - mouse) / scale;
                const relativeTop = annotation.box.y;
                annotation.box = {
                  height: height / scale + diff,
                  y: relativeTop - diff,
                };
              }
            },
            onPress() {
              annotation.draggable.disable();
            },
            onRelease() {
              annotation.draggable.enable();
              updateBox();
              annotation.draggable.update();
            },
          });
    
          const bottomDraggable = new Draggable($bottom, {
            trigger: `${gId} .bottom, ${gId} .bottomRight, ${gId} .bottomLeft`,
            onDrag(event) {
              const scale = annotation.scale;
              const { top, bottom, height } = getBoxBounds();
              const { top: wTop, height: wHeight } = getWrapperBounds();
              const { top: dTop, height: dHeight } = getDisplayBounds();
              const mouse = Math.min(event.clientY, dTop + dHeight, wTop + wHeight);
    
              if (mouse <= top) {
                const diff = (top - mouse) / scale;
                const relativeTop = annotation.box.y;
                annotation.box = { y: relativeTop - diff, height: diff };
                bottomDraggable.endDrag(event);
                topDraggable.startDrag(event);
              } else {
                const diff = (mouse - bottom) / scale;
                annotation.box = { height: height / scale + diff };
              }
            },
            onPress() {
              annotation.draggable.disable();
            },
            onRelease() {
              annotation.draggable.enable();
              updateBox();
              annotation.draggable.update();
            },
          });
    
          const rightDraggable = new Draggable($right, {
            trigger: `${gId} .right, ${gId} .topRight, ${gId} .bottomRight`,
            onDrag(event: PointerEvent) {
              const scale = annotation.scale;
              const { left, right, width } = getBoxBounds();
              const { left: wLeft, width: wWidth } = getWrapperBounds();
              const { left: dLeft, width: dWidth } = getDisplayBounds();
              const mouse = Math.min(event.clientX, dWidth + dLeft, wWidth + wLeft);
    
              if (mouse <= left) {
                const diff = (left - mouse) / scale;
                const relativeLeft = annotation.box.x;
                annotation.box = { x: relativeLeft - diff, width: diff };
                rightDraggable.endDrag(event);
                leftDraggable.startDrag(event);
              } else {
                const diff = (mouse - right) / scale;
                annotation.box = { width: width / scale + diff };
              }
            },
            onPress() {
              annotation.draggable.disable();
            },
            onRelease() {
              annotation.draggable.enable();
              updateBox();
              annotation.draggable.update();
            },
          });
    
          const leftDraggable = new Draggable($left, {
            trigger: `${gId} .left, ${gId} .bottomLeft, ${gId} .topLeft`,
            onDrag(event: PointerEvent) {
              const scale = annotation.scale;
              const { left, right, width } = getBoxBounds();
              const { left: wLeft } = getWrapperBounds();
              const { left: dLeft } = getDisplayBounds();
              const mouse = Math.max(event.clientX, dLeft, wLeft);
    
              if (mouse >= right) {
                const diff = (mouse - right) / scale;
                const relativeRight = annotation.box.x + annotation.box.width;
                annotation.box = { x: relativeRight, width: diff };
                leftDraggable.endDrag(event);
                rightDraggable.startDrag(event);
              } else {
                const diff = (mouse - left) / scale;
                const relativeLeft = annotation.box.x;
                annotation.box = {
                  width: width / scale - diff,
                  x: relativeLeft + diff,
                };
              }
            },
            onPress() {
              annotation.draggable.disable();
            },
            onRelease() {
              annotation.draggable.enable();
              updateBox();
              annotation.draggable.update();
            },
          });
    
          reaction(
            () => annotation.creationEvent,
            creationEvent => {
              if (creationEvent) {
                annotation.select();
                topDraggable.startDrag(creationEvent);
                leftDraggable.startDrag(creationEvent);
                annotation.setCreationEvent();
              }
            },
          );
        });
    
        return () => ctx.revert();
      }, []);

    In production (after build) everything works fine (startDrag work as expected) but something must be breaking here in development. While this isn't a huge issue, I would still like to understand how to remedy this.

  4. Well, in the codepen, the lines are:

    const d = Draggable.create(box); --> presumably an array
    
    container.addEventListener("click", (e) => {
      d.startDrag(e); --> calling d instead of d[0]
    });

    It's clear that something isn't adding up, if d was an array it should have been called as d[0], no?

    I am also not using Draggable.create, I'm using new Draggable. Could this have something to do with it?

  5. Thank you for checking this out!

    I actually did not change this part of code from the version I'm trying to recreate, which means this definitely worked in the past. Was this changed to an array recently (i.e. in the past year)?

    Also, if what you're saying is true, how come calling startDrag doesn't throw a "not a function" error?

  6. Hello friends.

    I'm making an annotation tool as a personal projcet. I made it once before and you guys were great help, but now I'm rewriting the code I have and one thing doesn't work: when I trigger startDrag on a draggable it doesn't catch.

    I expect that, when the mouse is still pressed, the same mouse event would start dragging . The logic is there and it worked before and I must have broken it so I now ask for you help.

     

    I couldn't possibly reproduce this in a sandbox but I'm happily sharing my repo (just clone, yarn and yarn dev).

    https://github.com/LarkRanger/beyond-annotations

    The lines in question are in the file

    src/components/annotation/pieces/resize/Resize.tsx

    lines 171-174.

    The code definitely reaches there, but startDrag just won't trigger (or perhaps, it does but then immediately breaks).

     

    You can reproduce the issue by uploading any image, then hitting "Annotate" and clicking and dragging. What should happen is that the box appears and drags in the same event, but it doesn't drag and you end up clicking it again.

     

    I would greatly appreciate it if anyone reads this, it's quite hefty but I'm truely stuck. ❤️

  7. Hello!

    I'm trying to make a rain effect that's is at least midly efficient. In the below example, when an element reaches its destination it is deleted, then a new element is created.

    I would like to, instead, have an element reshuffle its size and color, then move to a new initial position and just fall again.

    I tried rewriting the generateRainDrop function, to have it take an existing drop and just set its size , color, and position.

    This worked to the extent that the boxes did reshuffle, but then they stopped spinning - they just fell down.

    I tried using pause and play in between setting, and also tried using invalidate, to varying degrees of failure.

    At no point could I get a box to: randomly change size, color and initial position then continue falling and spinning, without recreating the box fully.

    See the Pen ZEXemXg by LarkRanger (@LarkRanger) on CodePen

    • Like 1
  8. In the codepen, the spinning box should swap colors every iteration. I used `onComplete` to call a function that moves the color index further, and the tween should take the current index color from the array at the top.

    This... well... doesn't work as I expect it to, but I couldn't quite find a way to do this.

    Checking the colorIndex in the console after every spin shows that it doesn, in fact, change. But the Tween doesn't pick up the new value on the next spin. I wonder why, and I also wonder what the correct way is to do this.

     

    EDIT:

    I solved it myself by making background into a function, figuring that unlike the value, the function would be called every time.

    However, this doesn't seem right, and I'd still like to know if there's a better way to do this!

    See the Pen zYEqNRm by LarkRanger (@LarkRanger) on CodePen

  9. Just now, Cassie said:

    Hey there @Lark,

     

    I think the 'snap' you're talking about is the reversed 'back' ease? Maybe?

     

    If we were to do a linear ease is this behaviour what you're looking for?

     


     

     

    No, unfortunately if you look at it long enough it still snaps back at some point, seemingly randomly. I wanted the "back" ease for the overshoot effect, but it doesn't seem to make a difference anyway.

    • Like 1
  10. Hi!

    I've been following guides and also finding some nice things on the forums, but I got myself stumped.

    In the codepen I was trying to make a box, that spins around randomly back, then forth, then back again and so on until you get tired.

    I tried moving the repeat to the tween and adding yoyo, and this is the most reliable way I found to do it.

    But if you watch closely, every so often the box would snap to a new position, not sure why, and I don't know how to stop it. 😧

    See the Pen gOGPBaQ by LarkRanger (@LarkRanger) on CodePen

  11. Hello my friends,

    I would like to run a simple "fade in" tween (like in the CodePen) on a series of boxes. My code is exactly as appears in the CodePen, but this obviously runs sequentially. I would like to have the boxes appear in random order every time.

     

    I also tried a loop I saw elsewhere on the forums, with running from 0 to the number of elements, but this still runs sequentially unless I randomize the numbers myself, (i.e. literally make an array of 0 to n but in randomorder , then loop over that).

    How should I go about doing this?

    See the Pen wvrwyop by LarkRanger (@LarkRanger) on CodePen

  12. You 1st point is rather interesting. Though I do see the error of not specifying px, and maybe this is me completely misunderstanding SVGs, but in the original rect tag I do specify translate(20, 20), so what's that? Is that value translated to px by gsap?

     

    Either way thank you so much for the clarification!

  13. 1 hour ago, OSUblake said:

     

    As Cassie said, you should use x, y, etc instead of transform. If you really needed to change the transform orf an SVG element, which you shouldn't as it will mess stuff up with Draggable, you would need to change the transform attribute.

     

    gsap.to(".rect", {
      attr: {
        transform: "translate(70 70)"
      }    
    });

     

    Thank you so much!

    As I said, I ended up using x and y instead of transform, but I did mark this as the resolution since it does answer my original question.

    Thank you very much for the help, this solved a massive bug for me. :)

  14. Hey @Cassie, thanks for the reply!

    So this is slightly awkward, but minutes after posting this I have indeed tried using gsap.set(... {x:..., y:...}) instead of trying to set the transform, and it worked like a charm.

    I still do not understand why trying to set the transform property to a string bugs out like that (or is that a feature?), and why setting the x and y like this doesn't clash with the existing transform.

     

    Edit: In this codepen one can see that trying to move the thing right by setting the transform property just sets everything to 0.

    See the Pen vYJZzjK by LarkRanger (@LarkRanger) on CodePen

  15. Hello!

    I've been trying to utilize gsap to construct a certain tool, and I've run into the exact same problem in these thread:

    I'm currently using gsap 3.7.1.

    My case is very similar, where the draggable (and SVG element) is moved around, it's position is defined via transform, and there is another element which may affect this transform, so I need to use update().

    Trying to gsap.set(element, {transform: 'translate(...)'}) works unexpectedly and sets the transform to all zeros.

    I would like to use the parseTransform functionality discussed in these threads but can't find the functionality in gsap 3.0.

    Does it still exist, or is there an alternative? I need the draggable to be up to date with the element's transform, otherwise it keeps snapping back.

     

    I would love to make a codepen example but I cannot for the life of me manage use Draggable in there, since it does not appear as a plugin on the gsap import from npm, so if anyone can direct me on how to do that I'd love to show an example. 

    Otherwise if you understand my issue, by all means, I'd love some help. :)

     

×
×
  • Create New...