LuLUE7775
Content Type
Profiles
Forums
Store
Blog
Product
Showcase
FAQ
Downloads
Posts posted by LuLUE7775
-
-
Hi,
I am building a slider based on this example
It works when it's alone on a page, https://yaojuilan.art/gsap
While it isn't working when there is something else https://yaojuilan.art/system_of_conductors/field-walk#kinmen (the slider works sometime. it is unstable. )
I tried logging out the observer onChange, the event does trigger, but the items just would not do the horizontal transition.
I am wondering if observer has some sort of limitation, or maybe observer listener is interfering with something?
Sorry i did not create a codepen, because this component does works standalone. Here is the slider component
export default async function Page() {const data= await getPageContent()return (<div id='intro' className='relative h-auto w-full overflow-x-hidden'><div className='h-[50vh] w-full'> some content </div><Slider items={data?.carousel_img?.images} /><div className='h-[200vh] w-full bg-red-100'> some content </div></div>)}
export default function Slider({ items, section }) {useGSAP(() => {let loop = horizontalLoop(`.carousel-${section} li`, { repeat: -1 })let slow = gsap.to(loop, { timeScale: 0, duration: 0.5 })loop?.timeScale(0)Observer.create({target: `.carousel-${section}`,type: 'pointer,touch,wheel',wheelSpeed: -1,preventDefault: true,onChange: (self) => {loop.timeScale(Math.abs(self.deltaX) > Math.abs(self.deltaY) ? -self.deltaX : -self.deltaY) // whichever direction is biggerslow.invalidate().restart() // now decelerate},})})return (<div className='absolute bottom-12 w-full cursor-grab overflow-hidden'><ul className={`carousel-${section} carousel flex flex-nowrap pl-0`}>{items?.map((item, i) => (<li key={i}><Imagealt={'collective of images'}src={item}width={150}height={150}sizes='100vw'className='pointer-events-none touch-none select-none '/></li>))}</ul></div>)}function horizontalLoop(items, config) {items = gsap.utils.toArray(items)if (!items.length) returnconfig = 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 naturaltotalWidth,curX,distanceToStart,distanceToLoop,item,igsap.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 - startXdistanceToLoop = 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 directionlet 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 adjustmentsvars.modifiers = { time: gsap.utils.wrap(0, tl.duration()) }time += tl.duration() * (index > curIndex ? 1 : -1)}curIndex = newIndexvars.overwrite = truereturn tl.tweenTo(time, vars)}tl.next = (vars) => toIndex(curIndex + 1, vars)tl.previous = (vars) => toIndex(curIndex - 1, vars)tl.current = () => curIndextl.toIndex = (index, vars) => toIndex(index, vars)tl.times = timestl.progress(1, true).progress(0, true) // pre-render for performanceif (config.reversed) {tl.vars.onReverseComplete()tl.reverse()}return tl}See the Pen BaPqzvX by andrei-savu (@andrei-savu) on CodePen
-
Hi, thank you all gsap team for the wonderful lib and resources.
I'm trying to get a slider works as below example in React. The problem is, when the user click fast, the slider x position will be off. So I'll need to get it snap back to the right position.
However, I can't get it snap. I assume I'll need to get a updated progress value, so I do it in onUpdate to manually update animation timeline progress value (which is animationRef.current here). If anyone can point out the right direction I'll be really grateful.
here's my minimal demo
See the Pen ExvZjZQ?editors=0010 by GreenSock (@GreenSock) on CodePen
- 1
Horizontal carousel totalwidth is not expanded.
in GSAP
Posted
Hi,
I am using Next.js with GSAP.
I discovered that the horizontal length does not expand according to the width of the images when users redirect from other pages.
Somehow, it works if the home page is refreshed.
In the horizontal helper function, I noticed that items[length - 1].offsetLeft is not the total width that should be added up.
Any help would be greatly appreciated!
https://codesandbox.io/p/devbox/gsap-horizontal-infinite-carousel-lzn99z?file=%2Fapp%2Fcomponents%2FSlider.jsx%3A41%2C16