Jump to content

Search In
  • More options...
Find results that contain...
Find results in...

Rodrigo last won the day on April 27

Rodrigo had the most liked content!


  • Content Count

  • Joined

  • Last visited

  • Days Won


Rodrigo last won the day on April 27

Rodrigo had the most liked content!

Community Reputation

3,127 Superhero

About Rodrigo

  • Rank
    Advanced Member

Profile Information

  • Gender
  • Location
    Santiago - Chile

Contact Methods

  • Skype

Recent Profile Visitors

24,421 profile views
  1. I would suggest using either SVG with the Draw SVG Plugin or canvas to draw the lines. Either way shouldn't be too complicated if we're talking about straight lines between each point (like the image you added). It could get a bit more complex for lines with more than 2 points in canvas. In SVG you can use a polyline for that. This is something I've been working on for a few weeks, it uses SVG in a Vue component and since performance is good enough there was no need to use canvas. Unfortunately I can't share any code of this, but the animation is done using the Draw SVG plugin on click/touch events: Another alternative would be to create a timeline and use that to draw between each point. Unfortunately you caught me with very little time so I can't create a demo right now, but hopefully this information is enough to get you started. Happy Tweening!!!
  2. I suggested to remove the colors and messages arrays from the class because I don't see the benefit of having them there, but keep the reference to the timeline inside the component class, because when the component is unmounted and then mounted again the reference could be lost. This seems to be working fine for me: constructor(props){ super(props); this.state = { data:[], works:[], counter:0 } this.initialSet = this.initialSet.bind(this); this.generateText = this.generateText.bind(this); this.changeText = this.changeText.bind(this); this.tl = gsap.timeline({ repeat: -1 }); } async componentDidMount(){ const response = await fetch(`https://raw.githubusercontent.com/fernandocomet/website/master/fernandocomet/src/data/portfolio.json`); const json = await response.json(); this.setState({ data: json, counter: 0 }); this.initialSet(); } componentWillUnmount(){ this.tl.kill(); } initialSet(){ let worksArr = []; // for (let i = 0; i < this.state.data.length ; i++){ for (let i = 0; i < this.props.messages.length ; i++){ // worksArr.push(this.state.data[i].title) worksArr.push(this.props.messages[i].title) } this.setState({ works: worksArr }) //Here we go //var tl = gsap.timeline({ repeat: -1 }); this.props.colors.forEach((color) => { this.tl.to("#message", { xPercent: -50, left: "50%", duration: 1, delay: 1 }) .to("#bg", { backgroundColor: color.dark, duration: 1, delay: 3 }) .to("#message", { color: color.light, duration: 2, delay: 0 }) .add(this.generateText); }); } generateText() { gsap.to("#message", { text: this.changeText(this.props.messages) }); } changeText(arr) { console.log(this.state.counter); let counterChange = this.state.counter + 1; if (counterChange === 24) { counterChange = 0; } this.setState({ counter: counterChange }) return this.props.messages[counterChange].title; } I'm unable to replicate this error though... Happy Tweening!!!
  3. Rodrigo

    Job Market Question

    👆 No better way to learn IMHO, even if failing might cost you a job. Yeah, the issue is that sometimes there is no way around those...
  4. Rodrigo

    Job Market Question

    Hi, While that is not my main area these days (now I'm focused mostly on full stack) and to complement Zach's answer, the job market is there, is not as advertised as other areas, like the ones you mentioned, but because of how things are unraveling lately (not because of Covid-19 but development in general), is hard for a dev that has to keep up with stuff like Mongo, Postgres, MySQL, GraphQL, React, Vue, Angular, Webpack, server-side, etc., to keep up with those technologies you mentioned. In that regard I haven't done anything beyond a couple of demos using PIXI 5, so there is always a need for creative guys that can deliver good looking and performant work. On that note is important to focus on performance, I've seen and worked in projects where clients are focused on things "looking" amazing and doing crazy stuff without the slightest concern for performance, and then everything torn apart because of it. So if you can keep a good balance between both, you'll be all right. Also don't forget game development, you could add phaser to the mix and you'll have another tool in your belt. Happy Tweening!!!
  5. Hi, The main issue is that your GSAP instance keeps running as you go to another section. You need to stop all GSAP instances when a component is unmounted, your GSAP instance is still running and that calls the generateText method, which calls the changeText method, which updates the state of the component. Also in the console you can see that GSAP is complaining about not finding the message DOM element, that is why we recommend using refs to get the dom element inside the render() method. You should use componentWillUnmount in order to kill all GSAP instances, which will be created again when the component is mounted again by the router. Finally I don't see the real upside to have both the colors and messages as static properties of the class. Since every JS file is it's own closure you can add them as constants outside the class and since the class and the constants reside in the same closure, they are accessible inside the class. Just an advice in order to keep the code inside the class to a bare minimum. Happy Tweening!!!
  6. Or anything that uses the web component specification
  7. As I mentioned months ago I don't have enough time now to update that article or write a new one right now. Perhaps in a couple of months I'll have time to dedicate myself to it. Well right now the "official" React way is to use hooks, which is something Blake and I have ranted about a few times. The best approach GSAP-wise is to use class components and life-cycle methods, but it feels like is just Blake and Me against the entire React community on this one
  8. There are 10 types of persons, the ones that understand binary and the ones who don't
  9. @bj22 Keep in mind that PIXI is mostly a 2D renderer. While they have a 3D with the pixi projection plugin, I'm quite sure that the approach you have in your code is not going to work with it. Honestly I haven't even used it so I can't give you an example, but it seems a bit complicated for just a cube: https://www.pixiplayground.com/#/edit/CRZ6tB7_0eB2Y6Og9wocf https://www.pixiplayground.com/#/edit/POz1H3nlOYOuRykFpo3kl In this post in the PIXI forums there is a short discussion about it: https://www.html5gamedevs.com/topic/45094-pixi-projection-rotating-3d-cube/ Also it seems that using ThreeJS could be a simpler approach IMHO: https://threejs.org/docs/#api/en/geometries/BoxGeometry I've seen a few things using GSAP with ThreeJS and the results are quite good actually. Finally perhaps @OSUblake (the forums' PIXI wizard) could have more info regarding this. Happy Tweening!!!
  10. No worries, everyone is here to learn, the only difference is that some of us have been around more time, that's all Happy Tweening!!!
  11. Hi, I'm not completely clear on how you're planning to do this animations, but there are a few things wrong with your code. First, you're creating this timeline: const tl = gsap.timeline({ paused: true }); tl.to(usersDomNodes, { duration: 0.3, stagger: 0.05, y: 0, autoAlpha: 1 }).play(); That basically takes the elements from the current Y position to zero and from the current opacity to 1. The problem is that when your animation starts, the Y position of those elements is zero and their opacity is 1, so GSAP takes the elements and animates them from opacity 1 to 1, so nothing happens. You have to set the initial style of the elements to some Y position and opacity zero: cardHover: { maxHeight: "250px", padding: "10", margin: "5px", border: "1px solid #101010", borderRadius: "10px", borderTop: "none", // add these sytles to make them hidden opacity: 0, visibility: "hidden", // add this to create the animation in the Y axis transform: translateY(-25px), marginBottom: 10, } Second, as I mentioned before create the animation as an effect of the state being updated, not as a callback of the API response, right now GSAP is complaining that you're passing an array of null elements to animate, therefore nothing will happen, even if you set the initial styles properly. This code actually works: useEffect(()=>{ const tl = gsap.timeline({ paused: true }); tl.to(usersDomNodes, { duration: 0.3, stagger: 0.05, y: 0, autoAlpha: 1 }).play(); }, [data]); Just remove the runAnimation method from the component and the reference in the API callback. Third, you're using async/await without the await statement in the API call and without a try/catch block, if for some reason the API call fails, you're app will have an unhandled promise rejection and you won't know what the problem is: const getUsers = async () => { try { // for this sample I'm using axios const myUsers = await axios.get("domain.com/users"); // now update the state setData(responseData); } catch (err) { console.error(err); // perhaps do something else, some UI notification of an API error } } Finally, perhaps you should use some code to check that the images are loaded in order to start the animation after all the images are loaded, otherwise the animation runs on the empty containers. Happy Tweening!!!
  12. Mhh... I assume that setData() is the setter you're using with useState() in order to update the data state property, right? Also I'll assume that usersDomNodes are updated when the state is updated. If that is the case, it could be possible that by the time the timeline instance is created the usersDomNodes array is empty. Keep in mind that in my sample the whole idea of the buttons is to mimic a server response, that's why I create and run the timeline instance after the particular state property is updated. While the initial useEffect() is actually the best place to create your API call, it could not be the best place to create the GSAP instance to animate the elements that depend on the API callback. Could you provide a simple live sample so we can take a better look? That would speed up the debugging process. Happy Tweening!!!
  13. Hi, The inertia plugin can be used in Draggable and as Zach mentioned it is a club plugin. All you have to do is register as a club member, download the files and follow the instructions in the docs: https://greensock.com/docs/v3/Installation The syntax is pretty straight forward: useEffect(() => { console.log(sliderRef.current.clientWidth, sliderRef.current.innerWidth); Draggable.create(sliderRef.current, { type: "x", bounds: { minX: -sliderRef.current.clientWidth + window.innerWidth * 0.88, maxX: 0 }, inertia: true }); }, []); Just add the import statement and register the plugin: import React, { useEffect } from "react"; import { gsap } from "gsap"; import { Draggable } from "gsap/Draggable"; import { InertiaPlugin } from "gsap/InertiaPlugin"; gsap.registerPlugin(Draggable, InertiaPlugin); Happy Tweening!!!
  14. Hi and welcome to the GreenSock forums. First, thanks for becoming a GreenSock club member and supporting GSAP!!! The way that I would go about animating a set of elements that depends on a dynamic data would be to store the data in the state and the useEffect() hook to create the animation when the state is updated. Here is a very simple example illustrating that: https://codesandbox.io/s/gsap-stagger-dynamic-elements-2d20l?file=/src/Users.js Now, considering that you're asking about image tiling the approach could be different but similar in some way. For example you can store in the state the amount of tiles you want to generate, create the tile elements and store them in an array and finally create the GSAP instance and animate it. Finally keep in mind that GSAP Staggers are quite amazing and there is an extremely wide range of possibilities so you can create really amazing animations, check it out: https://greensock.com/docs/v3/Staggers Happy Tweening!!!
  15. Hi, Basically this falls into the same category as this previous thread where it was discussed extensively all the different approaches and reasons to create a GSAP instance in a React app: As I said in that thread, it depends on whether or not the Slider state will be updated during it's lifecycle, nothing more. Finally this code seems to work fine in my samples: import React, { useRef, useEffect } from "react"; import { gsap } from "gsap"; import { Draggable } from "gsap/Draggable"; gsap.registerPlugin(Draggable); const pictures = [];// pictures array const Slide = ({ imageSource, content }) => { return ( <div className="slide"> <div className="preview"> <img src={imageSource} alt="The Plant" draggable="false" /> </div> <div className="infos"> <h3>{content.date}</h3> <h2>{content.desc}</h2> </div> </div> ); }; export const Slider = () => { const sliderRef = useRef(null); useEffect(() => { console.log(sliderRef.current.clientWidth, sliderRef.current.innerWidth); Draggable.create(sliderRef.current, { type: "x", bounds: { minX: -sliderRef.current.clientWidth + window.innerWidth * 0.88, maxX: 0 } }); }, []); return ( <div id="slider" className="slider" ref={sliderRef}> {pictures.map((item, index) => { return ( <Slide key={index} imageSource={item.source} content={item.content} /> ); })} </div> ); }; Happy Tweening!!!