Search the Community
Showing results for tags 'animation'.
-
I wanna create a scrollTrigger animation like the one in https://figr.design/ website homepage; if you have any suggestions, that would be a great help for me.
- 1 reply
-
- scrolltrigger
- animation
- (and 4 more)
-
My question leans more to a THREE problem than to a GSAP problem, I suppose. But I know that there are some THREE enthusiasts on this forum, and given the fact that this is the best JS-related forum anyway, I dare to post my question hoping you don't disagree with me too much... Thank you in advance! I couldn't get my example working on CodePen, so I prepared one on Stackblitz, hope that's ok: https://stackblitz.com/edit/nuxt-starter-d1zs6g?file=components%2FPointCloud.vue In this example there are several PointClouds that can be loaded into a THREE canvas (in a Nuxt app). A deletePlyModel function takes care of unloading the current model before a new one is loaded: const deletePlyModel = () => { // If no model is currently loaded, do nothing if (!currentPlyModel) return; // Find the point cloud object in the scene const pointCloud = scene.getObjectByName(currentPlyModel); // If the point cloud object is found, dispose and remove it if (pointCloud) { pointCloud.geometry.dispose(); pointCloud.material.dispose(); scene.remove(pointCloud); // Clear the currentPlyModel reference currentPlyModel = null; } render(); // Update the scene }; Even though I am not sure if everything is correct with this dispose function, it works. What I would like to achieve is to implement some animation (fade out, scale, etc) on the points of the pointcloud before they are removed from the scene. (Much like lumalabs.ai does it, if anybody is familiar with that site.) But even with the help of AI I am not able to achieve a working result. First I tried this: const timeline = gsap.timeline(); timeline.to(pointCloud.material, { opacity: 0, duration: 1 }); Gemini.ai suggested some other solutions, the last one was to loop over the colors after converting them to their Float32 pendent: function hexToNormalizedRgb(hex) { const r = (hex >> 16) & 0xFF; const g = (hex >> 8) & 0xFF; const b = hex & 0xFF; return [r / 255, g / 255, b / 255]; } const deletePlyModel = () => { // [..] if (pointCloud) { const timeline = gsap.timeline(); const normalizedFadeColor = hexToNormalizedRgb(0xffffff); pointCloud.geometry.attributes.color.array.forEach((color, i) => { // Access the color components directly const colorElement = pointCloud.geometry.attributes.color.array[i]; timeline.to(colorElement, { x: normalizedFadeColor[0], y: normalizedFadeColor[1], z: normalizedFadeColor[2], duration: 1, delay: i / pointCloud.geometry.attributes.color.count * 0.5 }); }); } } This resulted in GSAP target 0 not found. What would be the proper way to apply a fadeout or a scale function (staggered) to those points?
- 3 replies
-
- three
- pointcloud
-
(and 1 more)
Tagged with:
-
First of all sorry, but I can't provide a codepen, I will try to describe the problem the best I can. Basically I have this type of structure: <div class='middle'> <div class='canvas-holder'> <!-- [Three.js Canvas] --> </div> </div> This is the CSS each of this element have: .middle { position: relative; margin-top: 7rem; } .canvas-holder { position: absolute; height: 100%; // [Three.js Canvas] canvas { position: sticky; top: 0; } } The Three.js canvas has a certain size (window.innerWidth, window.innerHeight), with GSAP I wanted to animate the position of a model inside the Three.js canvas. I wanted to move up the model by 5 when I scroll, so I wrote this: // peeler_model is the model I want to move gsap.to(peeler_model.position, { y: 5, scrollTrigger: { target: middle_div, // I wanted to take the div as a reference point for the markers start: "top top", end: "bottom bottom", scrub: true, markers: true } }) Now with this what I thought would've happened is that by setting the target as the middle_div the first top at the start would have went at the top of the middle_div like this: But instead what happened was that START went at the top of the body. I don't know how to really fix it, I used percentages instead of top and bottom to fix it a bit, but it would be really helpful if top would go at the top of the target like it always did for me. The only thing I can think of of why this is happening is because the canvas has a parent with absolute positioning, but that's really strange. Anyways thanks in advance for the help.
- 2 replies
-
- scrolltrigger
- scroll
- (and 12 more)
-
Hello everyone, I need help with my WordPress site on Elementor, specifically with animation using GSAP. What I'm trying to achieve with GSAP in WordPress Elementor is this: Imagine there's a first section with a video background and text overlay. As I scroll down, another section appears while the first section remains fixed in the viewport. As I continue scrolling, the second section gradually reveals itself. The first section's video remains visible, while the second section's background fills the screen. In the middle of the second section, there's a logo that is masked/clipped, allowing you to see through to the video of the first section. please see the video example from apple website https://www.apple.com/sg/ipad-pro/ or can visit this link to see the exact video https://filebin.net/pw5ljr9fqsm1aupr
- 2 replies
-
- scrolltrigger
- animation
-
(and 2 more)
Tagged with:
-
I want to create CS2 case opening animation in my Nuxt 3 project using GSAP plugin. I am using gsap in my project for the first time, so I am facing many difficulties. The result I want to achieve is to make the case opening animation like in cs2. However, my result is far from that. I am facing these problems. I can't create a loop with gsap. Transitions between animations are not smooth they should move as if they were a single animation. I have shared the code in the codepen url but I couldn't get the Vue code to run in the codepen. Currently, the only working part of the code is that the indicator stops on the earned item when the animation ends.
-
Hello Everyone, iam new to gsap and still learning day by day.. but in this i got stuck and not able to find any answers. what im trying to do is that i have crated a pinned Panels where panels of same class will overlap one by one, im trying to animate the full animation first rquired of that pinned element and after all the animation of that pinned element get completed then only it should start overlapping Please watch this youtube video To know what i want ; its only 10sec long video
- 10 replies
-
Help Needed: Combining Scroll-Based Div Resizing with Text and Image Animations Using GSAP
availablecode posted a topic in GSAP
My Problem: I can't make the transition between the two animations in my CodePen so that they are combined into a single smooth animation. What I'm Looking for in the Animation: Global Animation: The two animations below should be combined into a single smooth animation. Resize on Scroll: During scrolling, a div should resize until it reaches a certain size on the left side. Text Appearance: Once the size is reached, text should appear on the right side. Image Change: For each section of text, a new image should appear. Technical Details: Div Resizing: The div should gradually change size based on scrolling until it reaches a predefined width on the left side of the screen. Text Appearance: The text should appear smoothly after the div has reached its final size. Each section of text corresponds to a different scroll step. Image Change: Each new section of text should trigger the appearance of a new image. What I've Tried So Far: GSAP ScrollTrigger: I've used GSAP ScrollTrigger to try and trigger the animations on scroll. I managed to resize the div, but then I can't get the text to scroll alongside it. GSAP Timeline: I tried creating a timeline with GSAP to sequence the animations, but I'm having trouble synchronizing the text appearance and image change with the div resizing. CSS Transitions: I also tried using CSS transitions for resizing, with a fixed position. Additional Information: Sketch: I have attached a sketch to help illustrate what I'm aiming for. YouTube Link: Here is a YouTube link showing the expected result in two parts after resizing: Youtube Link :- 2 replies
-
- help
- scrolltrigger
-
(and 2 more)
Tagged with:
-
I have a layout that includes a full-width image and below 2 columns with text. 1. In the beginning I would like to hide text columns, so it is something like an image covering the whole text in the viewport. https://prnt.sc/qMmbPSGgazwy 2. When you start scrolling the image moves up (like a normal scroll) and then uncovers the "fixed" lext column. https://prnt.sc/DsNgwu3TfMla https://prnt.sc/ITl-ejbnOFfR 3. When I scroll enough, I have a gap between the image and the left column. I would like to lock the position of the image (so it is a little) visible above the left column. https://prnt.sc/BhYYBCI0WsHM When I scroll more, then it will appear scrolling the right column up. The right column will be moved up as long as reaches the left column top. https://prnt.sc/PUsj_YQneNCV 4. After reaching the position, then it will start in the normal scroll. I tried a few methods with sticky, fixed positions, but I stuck with that. Any help here?
-
Hello, I will be much appreciate if someone can help me with this! Since I am not a programmer I have used some help and basic knowledge to achieve the following scrolling effect. https://codepen.io/M-Milde-the-scripter/pen/pomNZeV Basically it start with a image sequence animation, followed by second animation presenting a text with half opacity words, which becomes visible while the user scroll down, and once all the words becomes visible the entire text continue to scroll to reveal the next content. As you can see I am adding some classes on the html element while the user scroll down: - on the header I add .header-active and on the body I add .bg-1 when the first animation ends - and again on the body I add .bg-2 when the second animation ends What I want to achieve is simply to remove those classes in the same order, once the user start to scroll up: - remove the class .bg-2 from the body once the second animation reveals from the t and start to play backwards - remove the class .header-active from the header and .bg-1 from the body, once the firs animation is showing from the top and star to go backwards while the user scrolling up. So the final effect will be when the user scroll back to top the background is again white and the navigation is not visible. on the top example I try with "onReverseComplete", but no success Thank you in advance!
-
Hi, I would like to get help to fix an issue I'm encountering with the DrawSVG plugin and GSAP. I would like to animate my SVG element on hover and when I mouse leave it should revert. Currently, It's working fine except- If there are are multiple buttons all animation are executing at the same time when I hove any of the element, which I don't want. I want to execute the animation individually for each button. How can I achieve this effect? Many Thanks, Sajidul
- 2 replies
-
- gsap
- drawsvgplugin
-
(and 1 more)
Tagged with:
-
I want to make a half wheel animation with javascript, the purpose of the animation is an animation with 50 or more long names and I want to determine the winner in the variable, but I could not make this animation and I could not find any examples on the internet. example:
- 3 replies
-
- animation
- javascript
-
(and 3 more)
Tagged with:
-
Hello everyone! I'm working with React+Three.js + GSAP. I'm trying to animate a 3D model to make it rotate infinitely around its Y axis. The animation itself is applied, but I encounter a bug. The issue is that the animation randomly stops (does not complete a full rotation), and to restart it, I have to either drag the model again or move it (change its coordinates); otherwise, the model just remains stationary. So, it does not seem like a loading issue since otherwise, it would continue rotating on its own. I've tried animating using GSAP and useFrame. I've attempted importing the model as .jsx, as .glb, but I get the same effect everywhere. I also made a rotation animation in Blender and imported it, but I have the same error. I also used other models. But I'm getting the same error. This is the first time I'm encountering such an issue. Please advise on what might be the problem. Here is a GIF demonstrating the operation: https://drive.google.com/file/d/14pjIwIL-RqjsGepeEYC2owZ97dopJgDC/view?usp=drive_link This is the code of my component with a 3D model. I've shortened it for convenience. The comments indicate functions that I also tried. It didn't work. import React, { useRef, useEffect } from 'react' import { useAnimations, useGLTF } from '@react-three/drei' import * as THREE from 'three'; import { useGSAP } from '@gsap/react'; import gsap from 'gsap'; import { useFrame } from '@react-three/fiber'; export function Model(props) { const group = useRef() const { nodes, materials, animations } = useGLTF('models/bmw_m4_csl_2023.glb') const { actions, names } = useAnimations(animations, group) /*useEffect(()=>{ actions[names[0]].reset().fadeIn(3).play() },[]) */ gsap.registerPlugin(useGSAP) /*useGSAP(()=>{ let ctx = gsap.context(() => { gsap.to(group.current.rotation,{ y: "+=1", repeat: -1, ease: 'none', repeatRefresh: true, duration: 4 }),group}) return () => ctx.revert(); },[]);*/ /* useFrame(() => { group.current.rotation.y += 0.01 })*/ useEffect(() => { if (!group.current) return; gsap.to(group.current.rotation, { duration: 2, repeat:-1, y:2*Math.PI }); }, []); return ( <group ref={group} {...props} dispose={null}> <group scale={0.01}> <group rotation={[-Math.PI / 2, 0, 0]} scale={100}> <mesh castShadow receiveShadow geometry={nodes.M4xNME_exhaust_M4xNME_mechanical_0.geometry} material={materials.M4xNME_mechanical} /> <mesh castShadow receiveShadow geometry={nodes.M4xNME_exhaust_M4xNME_silver_0.geometry} material={materials.M4xNME_silver} /> </group> <group rotation={[-Math.PI / 2, 0, 0]} scale={100}> <mesh castShadow receiveShadow geometry={nodes.M4xNME_radiator_M4xNME_Black_0.geometry} material={materials.M4xNME_Black} /> <mesh castShadow receiveShadow geometry={nodes.M4xNME_radiator_M4xNME_Grille7_0.geometry} material={materials.M4xNME_Grille7} /> </group> </group> ) } useGLTF.preload('models/bmw_m4_csl_2023.glb') export default Model; Here is the component where the component with the 3D model is called. import React, { useEffect, useRef } from 'react'; import Model from './Model'; import { OrbitControls } from '@react-three/drei'; import { Canvas } from '@react-three/fiber'; const ModelView = () => { return ( <Canvas frameloop='demand' camera={{ position: [20, 10, 20], fov: 12 }}> <directionalLight position={[-19.772, 15.337, -0.439]} intensity={3.5} color="white"></directionalLight> <directionalLight position={[21.998, 14.051, -3.370]} intensity={2.46} color="white"></directionalLight> <directionalLight position={[-0.069, 13.752, -21.463]} intensity={5.08} color="white"></directionalLight> <directionalLight position={[4.116, 16.240, 20.387]} intensity={2.4} color="white"></directionalLight> <ambientLight intensity={2.12}></ambientLight> <directionalLight position={[0.009, 0.076, 7.499]} intensity={1.6} color="white"></directionalLight> <OrbitControls enableZoom={false} maxPolarAngle={Math.PI / 2} minPolarAngle={Math.PI / 2} /> <Model /> </Canvas> ); }; export default ModelView;
-
Hi, i have made some animation with gsap, i used gsap.from for made the animation, but when i refresh with (CTRL+R) for F5 the animation on my bottom page don't play... i upload video for you can see what i talk .. my code : https://codepen.io/arkunis/pen/zYXKKLx video for you can see Thx for your help !
-
Hi, i am starting a new project where a slider has already been set up with swiper js. Now i was wondering if its possible to add a cool animation when i drag or scroll through the slider like on this website: http://manifesto.clapat.com/index-showcase-carousel.html the images seem to be cut on the sides and seem to have more depth also they skew in the direction they are dragged. I was just wondering if someone could give me some direction on how to approach this kind of effect with GSAP or if there is a tutorial that someone could point me to. So no debugging for now^^. Also i wanted to know, if this effect is possible with a slider made with swiper JS or if there are any complications. Additionally i would like to implement the transition effect when clicking on the slider images. I saw that it can be made with the FLIP plugin, i just hope it works within Swiper JS. Thanks
-
Horizontal Scrolling Section & sticking it when it come into the viewport.
whizbbig posted a topic in GSAP
How can I use GSAP to animate cards within elementRef such that each card pauses when entering the viewport during a scroll, and as I scroll further, the card fades in opacity while moving to the left before the next card comes into view? Sandbox Link I have added the link of the sandbox so that I can explain my goals more clearly. You should view the preview in a next window in the editor only then will you be able to see the horizontal scroll. Thank you very much for your help ?- 5 replies
-
- horizontal
- gsap
-
(and 1 more)
Tagged with:
-
Slider banner with ScrollTrigger and ScrollToPlugin like in example
Vadim Volnitskyi posted a topic in Banner Animation
Hello everyone, I have a task to create a banner like next: https://www.moxionpower.com/industries/ I've tried, but it isn't work fine.- 1 reply
-
- scrolltrigger
- scrollto
-
(and 3 more)
Tagged with:
-
Hi, I'm currently making a personal website, and I was thinking I could implement a small animation to add to the details. The intended animation that I was trying to create was one that when the viewer of my website hovers overs certain <span> elements, those <span> elements would animate, without animating the other <span> elements. However, when I wrote my code, it didn't create the intended animation. Instead, it only animated the first <span> element regardless of whichever <span> elements that I hovered over. I have attached my CodePen demo URL as per the community guidelines, so if you want to take a look at my current code, it is readily available there. I would appreciate any inputs that I could get. Thank you!
-
Horizontal scroll snap with different width and different scroll animation
Subhankar posted a topic in GSAP
Hello everyone, and thanks in advance for help! I am trying to create horizontal scroll animation with 3 main section where first section should be 50% width and other 50% should be 50% of first image in second section. Right now I have created with 5 sections and same is working fine if there is not different concept for middle section. On load first div appears with 50% width and 50% of second div is visible in viewport Once middle div appears in viewport it should have 3 inner divs scrolling one by one Second div on viewport initially After scrolling one by one image should move left with text appearing left aligned After completion of the above animation, the second div should swipe left and the third div should appear. having different animations on it. https://codepen.io/subho0777/pen/gOEdjMV -
Hi everyone! I'm working on a landing page and I need to create a pre-loader that uses my handwritten logo as an SVG. Desired effect: The desired effect is a Stroke Reveal, implemented with GSAP3. How can I achieve this effect? Logo positioning: After loading, the logo/preloader should be positioned centrally on the navbar. Request for help: To achieve this project, I would need your help. What should I study? Best practices? What resources and tutorials do you recommend to learn more about?: Creating pre-loaders Stroke Reveal effect with GSAP3 Dynamic positioning of SVG elements What can I get inspiration from? Do you have any examples of websites or projects that use similar effects? Conclusion: Thank you in advance for your support! Additional information: I'm using GSAP3 My logo is a handwritten SVG The landing page is developed in HTML, CSS and JavaScript Thank you very much for your help!
-
JavaScript Developer for Slider Revolution at ThemePunch
themepunch posted a topic in Jobs & Freelance
Location Remote (Global team, company based in Europe) Type Freelance, full-time engagement, with potential for long-term partnership About ThemePunch ThemePunch, a renowned name in the WordPress plugin space, has been a market leader for over a decade. Our flagship product, Slider Revolution, is at the forefront of creating fully animated, responsive websites. As we embark on the exciting journey of developing a new major update of Slider Revolution, we are seeking a talented and experienced JavaScript Developer to join our diverse, global team. Key Responsibilities - Develop and enhance the Slider Revolution project, focusing on creating a seamless and innovative website builder tool. - Implement advanced features using JavaScript, Three.js, and GSAP. - Work closely with the team to create animations, timelines, and manage layers within the product. - Ensure compatibility and optimal performance in the WordPress environment. - Utilize HTML5 and CSS to enhance visual and functional aspects of web designs. Qualifications - Profound expertise in JavaScript, along with frameworks/libraries such as Three.js and GSAP. - Strong background in web animation and a deep understanding of the principles of animation. - Extensive experience with WordPress, particularly in developing plugins or addons. - Proficiency in HTML5 and CSS, with an eye for design and layout. - Familiarity with website builder tools and a strong grasp of WYSIWYG editors. - A portfolio showcasing previous work and accomplishments in similar projects. What We Offer - The opportunity to work on a leading product in the WordPress plugin space. - A remote work setting that allows flexibility and comfort. - Collaboration with a dynamic and skilled team spread across various continents. - A long-term partnership with potential for full-time engagement. - A chance to influence the future of website building and slider technology. How to Apply Please submit your resume along with a portfolio of your work. Highlight your experience with JavaScript, Three.js, GSAP, and any relevant WordPress projects here and/or to [email protected]. We look forward to discovering how your skills and experiences align with our vision for Slider Revolution. Join us at ThemePunch and be part of shaping the future of web design and animation!- 7 replies
-
- 1
-
-
- wordpress plugin
- javascript
- (and 7 more)
-
Hello, I'm new to GSAP and JS in general, but I wanted to add animation to my burger menu on click. let typeSplit = new SplitType(".mobile-menu-page-container", { types: "lines, words, chars", tagName: "span", }); // plain JavaScript version document.querySelector(".burger-wrap").addEventListener("click", function () { setTimeout(function() { gsap.from(".mobile-menu-page-txt .char", { y: "110%", opacity: 1, rotationZ: "10", duration: 0.2, ease: "power1.out", stagger: 0.05, }); }, 200); }); Everything works on the first click, but if I open and close the menu, it looks strange. What can I do? Thanks RPReplay_Final1706268273.mp4
- 2 replies
-
- split text
- menu gsap
-
(and 2 more)
Tagged with:
-
Hello my Wonderful Community, I have created some pages with GSAP scroll trigger animations, but now I want to add smooth scrolling, whatever packages I found are creating fake scroll due to which my scroll trigger animations are not triggered. Is there any package or solution to solve it?
- 4 replies
-
- smooth scroll
- scroll trigger
-
(and 1 more)
Tagged with:
-
Hello good people at Team GreenSock, happy new year and all the best wishes! I'm trying to create something similar like in this example Zoomable treemap / D3 | Observable (observablehq.com) , can anyone help me and point me in the right direction? Thank you!
-
Increase speed of marquee when mouse hover while changing direction with respect to scroll
diqqa_1909 posted a topic in GSAP
The direction of Marquee changes on hovering when scrolling upwards but it works fine when scrolling downwards. Somebody pls help me with this. ? CodePen File attached! HTML: <div class="marquee"> <div class="marquee-inner"> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> <div class="marquee-part"> Technology Redefined <div class="shape"></div> </div> </div> </div> JS let currentScroll = 0; let isScrollingDown = true; const marquee = document.querySelector('.marquee'); const marq = document.querySelector('.marquee-part'); const mrq = document.querySelector('.marquee-inner'); const loop = horizontalLoop(mrq, { paused: false, repeat: -1, }); marquee.addEventListener("mouseenter", () => { gsap.to(loop, { timeScale: 3, ease: "power1.in" }); }); marquee.addEventListener("mouseleave", () => { gsap.to(loop, { timeScale: 1 }); }); window.addEventListener("scroll", function() { if(window.pageYOffset > currentScroll){ isScrollingDown = true; }else{ isScrollingDown = false; } gsap.to(loop, { timeScale: isScrollingDown ? 1 : -1, }).totalProgress(1); currentScroll = window.pageYOffset; }); /*---------------HORIZONTAL LOOP FN-------------------*/ function horizontalLoop(items, config) { items = gsap.utils.toArray(items); config = config || {}; let tl = gsap.timeline({repeat: config.repeat, paused: config.paused, defaults: {ease: "none"}, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100)}), length = items.length, startX = items[0].offsetLeft, times = [], widths = [], xPercents = [], curIndex = 0, pixelsPerSecond = (config.speed || 1) * 100, snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural totalWidth, curX, distanceToStart, distanceToLoop, item, i; gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster. xPercent: (i, el) => { let w = widths[i] = parseFloat(gsap.getProperty(el, "width", "px")); xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / w * 100 + gsap.getProperty(el, "xPercent")); return xPercents[i]; } }); gsap.set(items, {x: 0}); totalWidth = items[length-1].offsetLeft + xPercents[length-1] / 100 * widths[length-1] - startX + items[length-1].offsetWidth * gsap.getProperty(items[length-1], "scaleX") + (parseFloat(config.paddingRight) || 0); for (i = 0; i < length; i++) { item = items[i]; curX = xPercents[i] / 100 * widths[i]; distanceToStart = item.offsetLeft + curX - startX; distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX"); tl.to(item, {xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond}, 0) .fromTo(item, {xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100)}, {xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false}, distanceToLoop / pixelsPerSecond) .add("label" + i, distanceToStart / pixelsPerSecond); times[i] = distanceToStart / pixelsPerSecond; } function toIndex(index, vars) { vars = vars || {}; (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); // always go in the shortest direction let newIndex = gsap.utils.wrap(0, length, index), time = times[newIndex]; if (time > tl.time() !== index > curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments vars.modifiers = {time: gsap.utils.wrap(0, tl.duration())}; time += tl.duration() * (index > curIndex ? 1 : -1); } curIndex = newIndex; vars.overwrite = true; return tl.tweenTo(time, vars); } tl.next = vars => toIndex(curIndex+1, vars); tl.previous = vars => toIndex(curIndex-1, vars); tl.current = () => curIndex; tl.toIndex = (index, vars) => toIndex(index, vars); tl.times = times; tl.progress(1, true).progress(0, true); // pre-render for performance if (config.reversed) { tl.vars.onReverseComplete(); tl.reverse(); } return tl; }