Jump to content
Search Community

OSUblake last won the day on September 16 2023

OSUblake had the most liked content!

OSUblake

Moderators
  • Posts

    9,196
  • Joined

  • Last visited

  • Days Won

    708

Posts posted by OSUblake

  1. 4 minutes ago, 321dev said:

    That's what i planed to do, but i wasn't sure if the transitions were smooth (enough).

     

    If it's not smooth, maybe make a simple demo so we can mess around and tweak it.

     

  2. 1 minute ago, 321dev said:

    So this would first interpolate between items 0 and 1, then 1 and 2, and so on.

     

    Yep.

     

    2 minutes ago, 321dev said:

    BTW:  Maybe gsap.utils.interpolate() could be expanded so that you could pass a custom function that interpolates between two elements? 

     

    That's not a bad idea. Any thoughts on this @GreenSock?

     

  3. So using three.js's slerp is fine, you just need to interpolate an array of them?

     

    Would something like this work?

     

    const interp = interpolate([q1, q2, q3]);
    
    let qx = interp(0.3);
    
    function interpolate(targets) {
      
      const interpolators = [];
      let len = targets.length;
      const iLen = len - 2;
      const q = new THREE.Quaternion();
      
      for (let i = 1; i < len; i++) {
        interpolators.push(slerp(targets[i - 1], targets[i], q));
      }
      
      len--;
        
      return p => {
        p *= len;
        let i = Math.min(iLen, ~~p);
        return interpolators[i](p - i);
      }
    }
    
    function slerp(a, b, q) {
      return p => {
        // three.js slerp 
        return q.slerpQuaternions(a, b, p);
      }
    }

     

    • Like 1
  4. 2 hours ago, 321dev said:

    E.g. when you wanted to interpolate a rotation in degrees from 350 to 10, the code should go from 350...359..0...10, instead of going backwards from 350 to 10.

     

    @GreenSock do you have some code for this? I can't find my demos that show this.

     

    • Like 1
  5. 8 hours ago, 321dev said:

    There are quite a few posts about this, but they're many years old, and many of them mention a plugin that can handle quaternions. What's the state today? Can GSAP tween quaternions, or do we still need a plugin?

     

    That's from the flash days.

     

    You should be able to just use onUpdate kind of like what shown here... although they are using Tween.js

     

    https://discourse.threejs.org/t/animating-quaternion-rotation/8015/12

     

     

    • Like 1
  6. 12 hours ago, mikaL said:

    No, it's not. All you have to do is 

    
    const element = document.createElement('div');
    element.attachShadow({mode: 'open'});

     

    Well, I would still consider that part of the web components API. So if you do that way, then how to do you add elements to the shadow root?

     

  7. You're right about it being no better/different. 

     

    Would that API work if you like create an animation after calling context?

     

    gsap.context(svgRef.current, () => {
      
      gsap.to("circle", {
        x: 100,
        onComplete() {
          gsap.to("rect", { ... });
        }
      });  
    });

     

     

     

     

  8. 51 minutes ago, GreenSock said:

    and one of the reasons for using refs

     

    The reason for using refs is to get the correct element. You really don't need refs if you are 100% sure that the document.querySelectorAll will get the correct element, but that's unlikely if a component is used more than once, which is basically the whole point of using components.

     

     

  9. 59 minutes ago, GreenSock said:

    Next question: how does this impact the whole re-rendering thing?

     

    I think there's been a lot of confusion over the years, especially with people throwing out terms like virtual DOM. Elements just don't get trashed or recreated. Once it's in the DOM, it's stays in there until you tell React to remove it.  

     

    Re-rendering basically just means applying changes made within React, or whatever component framework you're using, to the DOM. In this demo, React is re-rendering the cx attribute, which is being changed within React. GSAP is animating the cy attribute. There would only be an issue if gsap tries to change what React is trying to change.

     

    See the Pen bd15dbff73a59bd52de033864b2559d8 by osublake (@osublake) on CodePen

     

     

    • Like 2
  10. Now if a component has a bunch children elements that you want to animate, you're going to have to get a reference to them somehow.

     

    Most common is probably with the useRef.

     

    function MySvg() {
      
      const svg = useRef();
      const circle1 = useRef();
      const circle2 = useRef();
      const circle3 = useRef();
      const rect1 = useRef();
      const rect2 = useRef();
      const rect3 = useRef();
      
      useEffect(() => {
        gsap.to([circle1.current, circle2.current, circle3.current], {
          x: 100
        });
        
        gsap.to([rect1.current, rect2.current, rect3.current], {
          y: 200
        });
      }, []);
      
      return (
        <svg ref={svg}>
          <circle ref={circle1}></circle>
          <circle ref={circle2}></circle>
          <circle ref={circle3}></circle>
          <rect ref={rect1}></rect>
          <rect ref={rect2}></rect>
          <rect ref={rect3}></rect>
        </svg>
      );
    }

     

    If we had an option to pass in the context, we could eliminate all those useRefs except for the parent one, and just use query strings, greatly reducing the amount of code.

     

    function MySvg() {
      
      const svg = useRef();
      
      useEffect(() => {
        gsap.to("circle", {
          context: svg.current,
          x: 100
        });
        
        gsap.to("rect", {
          context: svg.current,
          y: 200
        });
      }, []);
      
      return (
        <svg ref={svg}>
          <circ></circle>
          <circ></circle>
          <circ></circle>
          <rect></rect>
          <rect></rect>
          <rect></rect>
        </svg>
      );
    }

     

    • Like 1
    • Thanks 1
  11. Well, let's first go over the biggest problem I see with React users, they don't use refs. They assume the selector string is just going to target that component, but if you use that component more than once, it's not going to animate correctly.

     

    This is supposed to animate the first box to 100 with a color of red, the second box to 200 with a color of green, and the third box to 300 with a color of yellow, but it doesn't happen.

     

    See the Pen 581c7a732f60e8322b5b543f4691a77b by osublake (@osublake) on CodePen

     

    Correct behavior using refs.

     

    See the Pen b8f05fd1700a1ef0c41ef1c41c9ca0fd by osublake (@osublake) on CodePen

     

     

     

    • Like 2
  12. 11 hours ago, mikaL said:

    As far as I know web components tend to use shadow DOM too. But as I said, it's not a deal breaker for me.

     

    How are you using shadow DOM without web components? AFAIK that's the only way.

     

     

  13. 16 hours ago, mikaL said:

    Yes, I think this is exactly what I'm looking for. I could even set it sort of globally beforehand, with something like this

    
    gsap.defaults({context: shadowRoot})

     

    I don't even know how that could work as a default. How would it get a reference to this.shadowRoot?

     

    Where I see this being the most helpful is with component frameworks like React. People wouldn't have to contemplate the best way to stagger elements.

     

     

  14. 7 hours ago, marosko said:

    if I call createBlob with different setup on scrollChange it rerenders whole "blob" and it's not smooth...


    Yeah, that's probably the worst thing you could do.

     

    Why don't you convert that demo over to gsap 3, research how to scale a vector, and then I can provide more guidance.

     

    For reference, this is the vector that we want to scale.

    var point = {
      x: options.centerX + Math.cos(angle) * options.minRadius,
      y: options.centerY + Math.sin(angle) * options.minRadius
    };   

     

     

    • Like 1
  15. That's what I'm thinking.

     

    So like in React, the user could just pass in the parent element of component.

    function App() {	
      const container = useRef(null);
      
      useEffect(() => {
        
        gsap.to(".box", {
          context: container.current,
          x: 100
        });
      }, []);
    	
      return (
        <div className="container" ref={container}>
            <div className="box"></div>
    		<div className="box"></div>
    		<div className="box"></div>
    		<div className="box"></div>
        </div>
      );
    }

     

    • Like 1
  16. 17 minutes ago, Robert Wildling said:

    Could it be that you just want to tell me "don't define menuTween on the data object, instead just declare it in methods"?

     

    Yep. The main point is that you can define your animations anywhere. It doesn't have to be inside a method per se. The only bad place might be inside created as you won't be able to access any refs at that point in the lifecycle.

     

     

    • Like 2
    • Thanks 1
  17. 1 hour ago, Robert Wildling said:

    Hmmm... I still do not see the place where I add a gsap instance to the object returned by the data object...

     

    He's saying you don't need to put anything related to GSAP on the data object. The data object is for reactive properties. GSAP animations are not reactive, and therefore you are putting additional overhead into your components by adding your animations to the data object.

     

    You can set your animations in any method, mounted, or from the vm passed in. It all points to the same instance.

    // this isn't needed
    data() {
      return {};
    },
    
    beforeRouteEnter(to, from, next) {
      next((vm) => {
    
        vm.foo();
        console.log(vm.bar); // Hello
      });
    },
      
    // Or using mounted
    mounted() {
      this.foo():
      console.log(this.bar); // Hello
    },
    methods: {
      foo() {
        this.bar = "Hello";
      }
    }

     

    • Like 1
×
×
  • Create New...