Jump to content
Search Community

ModiFax

Members
  • Posts

    10
  • Joined

  • Last visited

Everything posted by ModiFax

  1. Hello GSAP Support Team, I am experiencing an issue with my GSAP timeline in combination with Observer.create in my Vue3 Nuxt3 setup (TypeScript). The timeline starts to stutter and does not run smoothly when it is scaled using the touch events. Parent: const ctx = gsap.context((self) => { Observer.create({ target: `#${idNameElementCardContainer}`, type: "pointer,touch,wheel", wheelSpeed: -1, onChange: (self) => { if (!mediaBarStore.isDragging && !mediaBarStore.isExpanded) { let timeScaleValue: number; if (self.event instanceof WheelEvent) { timeScaleValue = self.deltaY > 0 || self.deltaX > 0 ? -20 : 20; console.log(timeScaleValue); barItems.loop.value.timeScale(timeScaleValue); barItems.slow.value.invalidate().restart(); } else { const deltaX = Math.abs(self.deltaX); const deltaY = Math.abs(self.deltaY); timeScaleValue = deltaX > deltaY ? -self.deltaX : -self.deltaY; barItems.loop.value.timeScale(timeScaleValue); barItems.slow.value.invalidate().restart(); } } else { gsap.set(barItems.loop.value, { timeScale: 0 }); } }, }); }, barElementBase.value); this are the problematic lines: barItems.loop.value.timeScale(timeScaleValue); barItems.slow.value.invalidate().restart(); Child onMounted(() => { const idNameElementCardContainer = 'elementCardContainer'; const classNameElementCard = 'elementCard'; barItems.loop.value = HorizontalLoop(`#${idNameElementCardContainer} .${classNameElementCard}`, { paddingRight: 10 }); barItems.slow.value = gsap.to(barItems.loop.value, { timeScale: 0, duration: 0.5 }); barItems.loop.value.timeScale(0); }); function HorizontalLoop(elements, config) { let tl: gsap.core.Timeline = gsap.timeline({ repeat: config.repeat || -1, paused: config.paused || false, defaults: { ease: "none" }, repeatDelay: 1, onReverseComplete: () => { tl.totalTime(tl.rawTime() + tl.duration() * 100); }, }); // Additional configuration and animations for the timeline return tl; } Issue Description: Stuttering and Lag: The timeline begins to stutter when scaled using the touch events. Performance: Continuous scaling of the timeline seems to lead to performance issues. Setup: Framework: Vue3 with Nuxt3 Language: TypeScript Questions: Are there any known performance issues with using Observer.create with a GSAP timeline? Are there any recommendations on how to make the scaling of the timeline more efficient to avoid stuttering? Should I consider using a different method to scale the timeline? I should mention that the issue does not occur immediately but becomes apparent after swiping left and right multiple times (observable is calling timeScale hundreds of times) using touch gestures. Goal is to get a native slide effect with touch devices. but if i slide very slow this method is also micro jumping. Thank you in advance for your help. Best regards, Christoph Höhensteiger PS: Idea is from this page: https://codepen.io/andrei-savu/embed/BaPqzvX?height=450&slug-hash=BaPqzvX&user=andrei-savu&tab-bar-color=%23222&name=cp_embed_1 But there is no problem as fare as i can see.
  2. Hi GSAP Support Team, I am currently integrating GSAP into a Nuxt 3 project using Vue 3 and TypeScript. I have a question regarding the best practice for initializing GSAP in various components. Specifically, I am unsure whether I should initialize GSAP in each page and component individually using ref and ctx, or if I should initialize GSAP once in a parent component and then pass it as a prop to child components. Could you please advise on the best practice for this scenario? Additionally, I would appreciate it if you could review the following simplified example and let me know if there are any improvements or best practices that I should consider. Thank you for your support! Best regards, Christoph Example create gsap every time: Parent <template> <div ref="parentRef"> <ChildComponent /> </div> </template> <script setup lang="ts"> import gsap from 'gsap'; const parentRef = ref(); const ctx = ref(); onMounted(() => { ctx.value = gsap.context((self) => { // do some stuff }, parentRef.value); }); onUnmounted(() => { ctx.value.revert(); }); </script> Child <template> <div ref="childRef"> <!-- Child content here --> </div> </template> <script setup lang="ts"> import gsap from 'gsap'; const childRef = ref(); const ctx = ref(); onMounted(() => { ctx.value = gsap.context((self) => { //... }, childRef.value); }); onUnmounted(() => { ctx.value.revert(); }); Or is it better to give the child a prop <ChildComponent :parentRefInChild="parentRef" />
  3. hi, I created an animation that should move in the following order: 1. When you click on the number 13, it should jump to the first position of the respective line (an animated swap) 2. The object grows animatedly evenly 100% of the line (2.1 the breaks should be animated while growing) 3. scroll into the line. essentially it works quite well. However, I didn't see any possibility to attach the flip after a To(). The code should (even if it is not clean) calculate everything correctly so far. At the moment the animation jumps straight to the 1st line and grows. The exchange and waxing should happen one after the other. The browser have to be like this to test it: Important: in this constellation, the object must not be in the 1st position when testing. Then it doesn't work I know it's a lot of code. But the only passage that is really relevant is in the Grow function: Thaks for help
  4. Hi, I have now tried the animation when wrapping in different situations. Unfortunately I haven't found a solution how to deal with many objects. If I resize at 20 cards then everything is cool. However, as soon as I go to 200, the animation doesn't work as well as at all. What could I optimize here? to test this you have to open codepen and resize the browser. Did I do something wrong here? 20 elements: https://codepen.io/ModiFax/pen/jOvBebB 200 elements: https://codepen.io/ModiFax/pen/jOvBeKY
  5. Thank you that was very helpful!
  6. Ah ok i understand. Now i have a solution. Thank you very much: https://codepen.io/ModiFax/pen/zYJNKKP Do you have any suggestions for improvement or would you leave it as it is?
  7. Ok, since I'm new to this area, I will of course trust your judgment and use flip. I've already read up on the subject. However, not quite understood how it works with wrap. All the examples I found are triggered with an event or stimulated to animate by adding css classes. From what I understand, I need a state that stores the properties: position/size/rotation: const state = Flip.getState(".group", {props: "flex-wrap"}); and with Flip.from the flip object will set the animation if position change? the goal is the same, i try to animate on wrap. Many thanks in advance for the help As requested, I created a codepen example that simulates a box that should break when the browser is resized. Unfortunately (you suspect it doesn't quite work yet) https://codepen.io/ModiFax/pen/zYJNKKP
  8. hi Rodrigo, I see that it is somewhat difficult to define my concern. https://stackblitz.com/edit/nuxt-starter-npjk5z In any case, thanks for your suggestions. I created a new Nuxt project on stackblitz. I hope that you can follow the situation a little better here. Attached are some images to illustrate a little bit better. If you change the size, in my example the wrapping is often hesitant and behaves in the default mode. It only works if I change the size very slowly. Here you can see the animation is working: However, I also need it if the size of the space changes quickly. That is the Situation where my example fails.(without animation) In a few situations he uses animation. But in most cases the wrapping is done abruptly. When I use the codepen example, there is always an animation. The example i try to replicate is the Align-Content section: I want to animate the wrap behavior and not the toggle of Flex properties hope that I was able to present my request better now. Thank you once again for the help Chriss
  9. hi, i have on the site: [CodePen is on bottom] https://codepen.io/osublake/pen/dMLQJr?editors=0110 Found an animation that, when resizing the browser, makes the flex items change the columns in a perfect animation. I got the basic animation on the Vue page. Unfortunately, this doesn't really work smoothly with fast reductions and enlargements. If I have very fast movements, then it is no longer an animation, then the boxes are placed in the next line as in normal behavior. to reproduce resize the browser window. Here is my vue code: What do i have to change to get the same animation on wrapping? <template> <div style="height: 100%" ref="gsapBase"> <div class="card-container"> <div class="card-wrapper" :class="'item' + n" :key="n" v-for="n in 20" @click="GrowOnClick('.item' + n)"> <div class="card" :id="'card' + n">Test</div> </div> </div> </div> </template> <script setup lang="ts"> import gsap from "gsap"; let total = 0; let dirty = true; let time = 0.9; let omega = 12; let zeta = 0.9; let boxes: { height: number; node: HTMLElement; transform: any; width: number; x: number; y: number }[] = new Array<{ content: Node; height: number; node: HTMLElement; transform: any; width: number; x: number; y: number; }>(); const gsapBase = ref(); const ctx = ref(); onMounted(() => { ctx.value = gsap.context((self) => { let nodes = self.selector?.(".card-wrapper"); total = nodes.length; for (var i = 0; i < total; i++) { var node = nodes[i] as HTMLElement; var width = node.offsetWidth; var height = node.offsetHeight; var color = "rgb(" + colorGen() + "," + colorGen() + "," + colorGen() + ")"; gsap.set(node, { x: "+=0" }); gsap.set([node, node.children], { backgroundColor: color }); var transform = (node as any)._gsTransform; var x = node.offsetLeft; var y = node.offsetTop; boxes[i] = { height, node, transform, width, x, y }; } gsap.ticker.add(() => { dirty && layout(); }); }, gsapBase.value); window.addEventListener("resize", () => { dirty = true; }); }); onUnmounted(() => { ctx.value.revert(); window.removeEventListener("resize", () => { dirty = false; }); }); function layout() { console.log(boxes.length); dirty = false; if (boxes.length > 0) { for (var i = 0; i < total; i++) { var box = boxes[i]; var lastX = box.x ?? 0; var lastY = box.y ?? 0; box.x = box?.node?.offsetLeft ?? 0; box.y = box?.node?.offsetTop ?? 0; if (lastX !== box.x || lastY !== box.y) { var transx = box.transform?.x == undefined ? 0 : box.transform.x; var transy = box.transform?.y == undefined ? 0 : box.transform.y; var x = transx + lastX - box.x; var y = transy + lastY - box.y; // Tween to 0 to remove the transforms gsap.set(box.node, { x, y }); gsap.to(box.node, time, { x: 0, y: 0, ease }); } } } } function GrowOnClick(node: string) { console.log(node); gsap.to(node, 0.5, { flex: "1 0 100%", onComplete: () => { gsap.to(window, { duration: 0.5, scrollTo: node }); }, }); } function colorGen() { var generateColor = Math.floor(Math.random() * 256); return generateColor; } function ease(progress: number) { var beta = Math.sqrt(1.0 - zeta * zeta); progress = 1 - Math.cos((progress * Math.PI) / 2); progress = (1 / beta) * Math.exp(-zeta * omega * progress) * Math.sin(beta * omega * progress + Math.atan(beta / zeta)); return 1 - progress; } </script> <style lang="scss" scoped> .card-container { display: flex; flex-wrap: wrap; display: -webkit-flex; display: -ms-flexbox; padding: 10px; width: 100%; } .card-wrapper { margin: 0; display: inherit; padding: 10px; -webkit-align-items: center; -ms-flex-align: center; align-items: center; height: 300px; width: 200px; border: 2px solid red; } .card { border: 2px solid green; color: black; } </style>
×
×
  • Create New...