Jump to content

Rodrigo last won the day on March 17

Rodrigo had the most liked content!

Rodrigo

Moderators
  • Content Count

    1,749
  • Joined

  • Last visited

  • Days Won

    158

Rodrigo last won the day on March 17

Rodrigo had the most liked content!

Community Reputation

2,559 Superhero

About Rodrigo

  • Rank
    Advanced Member

Contact Methods

  • Skype
    r_hernando

Profile Information

  • Gender
    Male
  • Location
    Santiago - Chile

Recent Profile Visitors

22,123 profile views
  1. Well I was creating a sample an Jack beat me to it. Also a piece on friendly advice. Try to avoid updating the state of any component on events that are triggered a lot like mouse move or scroll. It could create quite a burden in the app since that component re-renders and so it will any child component in it even if they don't re-render because of the state update, Reat still will look and do a shallow comparison to see if something has to be updated. If possible try to set up an event emitter and store the mouse position outside the class, remember that you're working with ES6 modules, which means that you can export the event emitter from the main file (or other file if you want), create the event listener in the new cursor file and emit the event in the parent component, that will be far cheaper in terms of processing than updating the state on every mouse move. If you take a look at this scroll spy library, you'll see that the guy does and stores all the calculations in an object and then compares those values with the ones stored. Once the scroll value exceeds the value of one of those items the state is updated only once: https://github.com/makotot/react-scrollspy/blob/master/src/js/lib/scrollspy.js#L191-L201 Happy Tweening!!!
  2. Just the beginning https://greensock.com/docs/TimelineLite
  3. Hi, I haven't used hooks a lot, since I've been extremely busy with literally no free time so I couldn't tell you in this one. The one solution (that you probably are aware of) I can suggest is to use a regular class component just for the switch element. I know is not the ideal case, but with a component that small the overhead created by the extra code shouldn't be noticeable, unless we're talking about hundreds of instances. You can compare the outcome of this small snippet in Babel's repl playground: const MyComponent = () => { const tl = "TimelineInstance"; return <div></div>; } class ClassComponent extends Component { constructor(props){ super(props); } render() { return <div></div>; } } Of course Babel is going to add a few lines at the start of the outcome for the class declaration but you'll find this: var MyComponent = function MyComponent() { var tl = "TimelineInstance"; return React.createElement("div", null); }; var ClassComponent = /*#__PURE__*/ function (_Component) { _inherits(ClassComponent, _Component); function ClassComponent(props) { _classCallCheck(this, ClassComponent); return _possibleConstructorReturn(this, _getPrototypeOf(ClassComponent).call(this, props)); } _createClass(ClassComponent, [{ key: "render", value: function render() { return React.createElement("div", null); } }]); return ClassComponent; }(Component); As you can see the difference is not much, for something as simple as this of course, but as I mentioned, the gain in a small component that it doesn't have hundreds of instances the overhead is minimal and most likely unnoticeable. Actually there is not a lot of issue in creating instances outside the declaration of a React component. Keep in mind that those are just object constructors, nothing more. Also is very important to keep in mind that the bundling tools (today almost everyone uses Webpack) creates independent, encapsulated modules so each file has no communication with the global scope unless is set up in such way, which @PointC's suggestion doesn't so it should be very safe to do so. Hopefully this comes as helpful. Happy Tweening!!
  4. Mhh... just realized that @mikel's codepen (first answer in this thread) does exactly that...
  5. Since you're using jQuery, you can check the scroll value of the window element or any element you're using as a main wrapper for the site. This is an extremely simple example of using that particular way to update the progress of a GSAP instance: https://codepen.io/rhernando/pen/RNpBYx Happy Tweening!!
  6. Hi and welcome to the GreenSock forums. The CDN links are working for me. Perhaps the issue is the order the tags are placed. Remember to put the tag with the href to your code after the tags with the CDN links. If your code is in a file called myScript.js, then you should add the tag for that after the GSAP files and for that matter after every other library or framework you use in your site: <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.0.min.js"></script> <!-- NOW ADD YOUR FILE --> <script src="js/myScript.js"></script> Happy Tweening!!!!
  7. Well, I won't say that every jQuery method returns the jQuery instance, because I could be wrong, but is for chaining purposes. In this case you're basically selecting the slider element and assigning a width based on the calculations you made previously on your code. What's odd is that you didn't thought about doing the same you're already doing with the handle, that is use a set() instance to set the width of the slider element: TweenLite.set(slider, { width: boxWidth * sections }); That seems to work OK in the codepen sample. This hopefully will help you get a better understanding of the different widths and heights of an HTML element object: https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively Happy Tweening!!!
  8. Honestly I'd do my best to accommodate both instances to update the X value on the slides parent container and do some math in order to update the value from the handle Draggable instance in a way that reflects the drag amount of the handle. Another possibility is to create a regular TweenLite instance that should be updated via the handle's Draggable instance. For example use a regular Draggable with snapping for the slides container. At the same time create a regular TweenLite instance (this should remain paused all the time) that moves the slides container all the way to the left using the X value on it and update that TweenLite instance using Draggable, like this: https://codepen.io/rhernando/pen/Batoc That is, IMHO, basically the simplest way to achieve that. Happy Tweening!!
  9. Hi Richard and welcome to the GreenSock forums. It seems that this could be solved by using the update() method all Draggable instances have, which is very useful when something outside the realm of the Draggable instance itself, updates it's target. On top of that right now you're updating two different things, that also could be a source of problems. Let's go backwards. First you're updating two different things. On the slides the Draggable instance is set to Scroll Left while the handle Draggable instance updates the slides X position. Those are two completely different things. My advice is to create a consistent update in both cases the handle callback and the property being updated by the Draggable instance that controls the slides. Second, if you're updating the same property that a Draggable instance is affecting, then the recommendation is to use the update method in order to tell that Draggable instance that the value of that specific property has been updated outside the Draggable instance. In that case GSAP updates the value in the Draggable instance and the next time the user drags that updated value will be reflected: https://greensock.com/docs/Utilities/Draggable/update() Unfortunately I don't have enough time to fiddle with your code and try to create a working solution, but hopefully this will help you get started. Happy Tweening!!
  10. Ha!! yeah the extra rest can do that
  11. Ok my take on this is to use onStart instead of onComplete in the out animation instance and in that callback use a delayedCall which is a timer but it runs with GSAP ticker so everything will be synced perfectly if you change browser tabs: https://codepen.io/rhernando/pen/KYerxb Happy Tweening!!
  12. Hi Apollos, I agree with Jack, there is a lot you want to do in your sample and basically most of the resources you need are here in the forums and other documentation. For example to draw an SVG path you can use the Draw SVG plugin. Also you could tween the width of a div element with no height but a border-top property as well. As far as using GSAP in React this basically comes to using refs in order to gain access to the DOM nodes and use them in a GSAP instance. Here is a introduction of how to get your React project working with GSAP with live-editable samples: https://greensock.com/react Happy Tweening!!
  13. If you ask me it seems about right. Keep in mind that .set() instances are zero duration instances so, something that actually lasts nothing can have a progress? Is it at the start or the end? So to me is actually correct that it doesn't have a progress. Of course the Yoda of GSAP, our beloved master @GreenSock will clarify this for us all why set tweens progress don't have Happy Tweening!!
  14. Hi and welcome to the GreenSock forums. The fist thing here is that when you create a ref in directly in a component, you get the component instance and not the DOM node or tree that the component ultimately renders: class MyApp extends Componetn { constructor(props) { super(props); this.myCard = null; } componentDidMount () { console.log(this.myCard); // returns a React component object } render () { return <div> <Card ref={card => myCard = card} /> </div>; } } That because the ref callback is being called in a React Component instance and not a DOM node created in JSX. Then is not clear where you want to create the animations; In the parent component or on each card?. If you want to create the animations in the parent component then you should use Forwarding Refs in order to store a reference to the DOM node that sits at the top of the DOM tree created by that component. Forwarding refs is a bit of a complex resource for someone that is just staring with React, specially if your Card component can't be transformed into a functional component. If your Card component can be transformed into a functional component, then is pretty easy. This is an extremely simple example of using forward refs to create an animation with GSAP: https://stackblitz.com/edit/react-forwarding-refs-gsap An alternative is to use React Transition Group in order to create the animations inside each Card component. This approach can also be a bit convoluted as shown here: https://stackblitz.com/edit/gsap-react-transition-group-list Finally if you want to access the DOM element directly inside each instance of the Card component without all the hassle of React Transition Group you're very close in fact. Right now you have this on your Card component: class Card extends Component { tl = new TimelineLite({ paused: true }); componentDidMount() { console.log(this.refs); } render() { return ( <div className="slide"> <div className="card"> <div className={`${this.props.card.id} card-img`} /> <div className="card-content" ref> <p className="card-theme">{this.props.card.theme}</p> <h2 className="card-header">{this.props.card.header}</h2> <p className="card-para"> lorem lorem</p> <a className="card-link" href="#"> Read </a> </div> </div> <div className="prevnext"> <button className="pn-btn" id="prev" /> <button className="pn-btn" id="next" /> </div> </div> ); } } Keep in mind that the ref is a callback that, used as an attribute in the JSX code, grabs whatever is returned from the tag where is used, in this case a <div> element, but is a function, now you're only referencing that function but you're not doing anything with it. You have to create a reference to the DOM element in the constructor and then use the callback to update it at render time: class Card extends Component { constructor(props){ super(props); this.tl = new TimelineLite({ paused: true }); this.card = null; } componentDidMount() { console.log(this.card); // returns the div element } render() { return ( <div className="slide"> <div className="card"> <div className={`${this.props.card.id} card-img`} /> <div className="card-content" ref={div => this.card = div}> <p className="card-theme">{this.props.card.theme}</p> <h2 className="card-header">{this.props.card.header}</h2> <p className="card-para"> lorem lorem</p> <a className="card-link" href="#"> Read </a> </div> </div> <div className="prevnext"> <button className="pn-btn" id="prev" /> <button className="pn-btn" id="next" /> </div> </div> ); } } That particular use will allow you to use the <div> element in your GSAP instance with no problems. Hopefully this is enough to get you started. Happy Tweening!!
  15. Well, basically that has to do with dealing with asynchronous code. Since you're getting your app's data in the componentDidMount() event handler that code is executed and keeps waiting for an answer from the server and the rest of the code is executed regardless of that, hence the code is asynchronous. When you move your GSAP code to the .then() method of the promise returned by fetch() that is executed when the server sends a successful response, therefore you have the data and you can use it in your GSAP powered animations. Another alternative is to use async/await, but if you're not too familiar with promises it might come as a bit confusing. Basically async await allows you to write asynchronous code in a synchronous fashion, without the .then() and catch() methods. You can check this resources to learn about it: https://javascript.info/async-await And of course the crazy guy from Sweden (note, not every person in Sweden is crazy and maybe this guy isn't as well ): Happy Tweening!!