redfawx Posted July 5, 2020 Share Posted July 5, 2020 Hi Everyone, This may be a bit complicated to get a view of everything since I'm working in nuxt. Long story short I have a basic effect of what I want to accomplish but, it's not seamless. My overall goal is to create a single marquee strip that will start to animate left to right. Easy right? Well to make it more interactive I want it to accelerate faster from left to right in the user is scrolling down. Again easy? well if the user scrolls up I want it to now stop where it is and start scrolling right to left while also accelerating when the user is scrolling. To currently achieve this I'm having basic marquess scrolling from left to right but containing it in a larger container that is being pushed left to right with the use of Scroll Trigger. So far the container essentially works and it's fine but my marquees are not seemless since there is the use of change of direction. A visual example can be found here: https://suturacreative.com/ if you scroll down a bit. I think essentially, I'm doing what's correct by duplicating left to right but do I have to create two duplicates at this point and have copies on either side or something? attached below is my basic logic for one marquee: <template> <div v-observe-visibility="visibilityChanged" class="font-hel"> <div class="my-auto mx-auto overflow-x-hidden text-2xl md:text-4xl lg:text-5xl xl:text-6xl font-medium" > <div :class="'marquee-container-' + marqueeText" style="width: 200vw; margin-left: -100vw;" > <div class="hero-marquee"> <div class="marquee"> <span :class="'marquee-text-' + marqueeText" class="clipped-text"> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> </span> <span :class="'marquee-text-' + marqueeText" class="clipped-text"> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> <span class="text-yellow-500">{{ copy }} </span> <span class="text-white">{{ copy }}</span> </span> </div> </div> </div> </div> </div> </template> <script> import { TimelineLite, Linear, TweenLite } from 'gsap/dist/gsap' import NuxtSSRScreenSize from 'nuxt-ssr-screen-size' export default { components: { // Service, // globe }, mixins: [NuxtSSRScreenSize.NuxtSSRScreenSizeMixin], props: { copy: { type: String, required: true }, marqueeText: { type: String, required: true }, rate: { type: Number, required: true }, offSet: { type: Number, required: true } }, data() { return { isHidden: true, isVisible: true, animated: false, animation: new TimelineLite(), line1: new TimelineLite(), scrollDirection: 1, distance: null, style: null, marginRight: null, totalDistance: null, time: null, container: null } }, beforeDestroy() { // window.removeEventListener('scroll', this.onScroll) }, mounted() { this.$nextTick(function() { let lastScrollTop = 0 const thisObj = this // element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element. addEventListener( 'scroll', function() { // or window.addEventListener("scroll".... const st = window.pageYOffset || document.documentElement.scrollTop if (st > lastScrollTop) { // downscroll code TweenLite.to(thisObj.container, thisObj.time, { repeat: -1, x: '-=' + thisObj.totalDistance, ease: Linear.easeNone }) } else { // upscroll code TweenLite.to(thisObj.container, thisObj.time, { repeat: -1, x: '+=' + thisObj.totalDistance, ease: Linear.easeNone }) } lastScrollTop = st <= 0 ? 0 : st // For Mobile or negative scrolling }, false ) const marquee = document.querySelectorAll( '.marquee-text-' + thisObj.marqueeText ) marquee.forEach((el) => { // set a default rate, the higher the value, the faster it is // thisObj.rate = 30 // get the width of the element thisObj.distance = el.clientWidth // get the margin-right of the element thisObj.style = window.getComputedStyle(el) thisObj.marginRight = parseInt(thisObj.style.marginRight) || 0 // get the total width of the element thisObj.totalDistance = thisObj.distance + thisObj.marginRight // get the duration of the animation // for a better explanation, see the quoted codepen in the first comment thisObj.time = thisObj.totalDistance / thisObj.rate // get the parent of the element thisObj.container = el.parentElement this.animation.set(thisObj.container, { x: '-' + thisObj.totalDistance / thisObj.offSet, ease: Linear.easeNone }) }) setTimeout(function() { thisObj.animation.from( '.marquee-container-' + thisObj.marqueeText, { scrollTrigger: { trigger: '.marquee-container-' + thisObj.marqueeText, start: 'top center', scrub: 2 }, x: '+=200', duration: 0.25 }, 0 ) }, 1500) this.line1 = new TimelineLite({ force3D: true, repeat: -1, paused: false }) }) }, methods: { visibilityChanged(isVisible, entry) {}, getPosition(element) { let xPosition = 0 let yPosition = 0 while (element) { xPosition += element.offsetLeft - element.scrollLeft + element.clientLeft yPosition += element.offsetTop - element.scrollTop + element.clientTop element = element.offsetParent } return { x: xPosition, y: yPosition } } } } </script> <style scoped> .hero-marquee { overflow: hidden; white-space: nowrap; } .marquee { font-size: 0; } .clipped-text { display: inline-block; font-size: 100px; margin-right: 24px; } @media only screen and (max-width: 600px) { .marquee { font-size: 0; } .clipped-text { display: inline-block; font-size: 33px; margin-right: 15px; } } </style> Link to comment Share on other sites More sharing options...
mikel Posted July 5, 2020 Share Posted July 5, 2020 Hey @redfawx, Just small suggestions ... See the Pen oNXoOBq by mikeK (@mikeK) on CodePen See the Pen a268f68810ba894fdc72bf966d7be862?editors=1010 by mikeK (@mikeK) on CodePen Happy scrolling ... Mikel 3 1 Link to comment Share on other sites More sharing options...
redfawx Posted July 5, 2020 Author Share Posted July 5, 2020 @mikel Thank you so much! Was just spending the weekend getting frustrated with it. I really appreciate the help! 2 Link to comment Share on other sites More sharing options...
redfawx Posted July 5, 2020 Author Share Posted July 5, 2020 @mikel Thank you so much for all the help and I've translated the above codepen into my es6 environment. One thing I'm having trouble with is when switching directions it's starting the animation from the beginning and not keeping the marquee at the current position its already animated to. Is there a simple way of doing this? Thank you again for all your help. Below is my current version of the marquee component: <template> <div class="font-hel"> <div id="no01" ref="marquee" class="wrapper"> <div class="boxes"> <div class="box">GreenSock</div> <div class="box">Nice Tool</div> <div class="box">GreenSock</div> <div class="box">Animate</div> <div class="box">Fast & easy</div> <div class="box">GreenSock</div> <div class="box">The best</div> </div> </div> </div> </template> <script> import { gsap, TimelineLite } from 'gsap/dist/gsap' import NuxtSSRScreenSize from 'nuxt-ssr-screen-size' export default { mixins: [NuxtSSRScreenSize.NuxtSSRScreenSizeMixin], props: { copy: { type: String, required: true }, marqueeText: { type: String, required: true } }, data() { return { master: null, boxWidth: null, totalWidth: null, no01: null, dirFromLeft: null, dirFromRight: null, mod: null, animation: new TimelineLite() } }, mounted() { this.$nextTick(function() { this.boxWidth = 250 this.totalWidth = this.boxWidth * 7 // * n of boxes this.no01 = this.$refs.marquee.querySelectorAll('.box') this.dirFromLeft = '+=' + this.totalWidth this.dirFromRight = '-=' + this.totalWidth this.mod = gsap.utils.wrap(0, this.totalWidth) this.setMarquee(this.no01, 15, this.dirFromLeft) const thisObj = this thisObj.animateFromLeft() }) }, methods: { setMarquee(which, time, direction) { const thisObj = this gsap.set(which, { x(i) { return i * thisObj.boxWidth } }) }, marquee(which, time, direction) { const thisObj = this thisObj.animation.to(which, { x: direction, modifiers: { x: (x) => thisObj.mod(parseFloat(x)) + 'px' }, duration: time, ease: 'none', repeat: -1 }) }, animateFromRight() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromRight) }, animateFromLeft() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromLeft) } } } </script> <style scoped> .wrapper { width: 150%; height: 50px; background: grey; overflow: hidden; } .wrapper .box { position: absolute; width: 250px; height: 50px; background-color: grey; color: black; font-size: 40px; font-weight: 600; line-height: 50px; text-align: center; } .wrapper .boxes { position: relative; left: -250px; } </style> Link to comment Share on other sites More sharing options...
redfawx Posted July 6, 2020 Author Share Posted July 6, 2020 This topic can be closed. I've fixed what I was aiming to accomplish with simply changing Timeline to TweenLite. Thank you again all for your help. If someone is trying to find a solution this was the code that ended up working for me (still need to dry it out): <template> <div class="w-full overflow-x-hidden"> <div id="no01" ref="marquee" class="wrapper flex font-hel"> <div class="boxes my-auto"> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> </div> </div> </div> </template> <script> import { gsap, TweenLite // TimelineLite } from 'gsap/dist/gsap' import NuxtSSRScreenSize from 'nuxt-ssr-screen-size' export default { mixins: [NuxtSSRScreenSize.NuxtSSRScreenSizeMixin], props: { copy: { type: String, required: true }, marqueeText: { type: String, required: true } }, data() { return { master: null, boxWidth: null, totalWidth: null, no01: null, dirFromLeft: null, dirFromRight: null, mod: null, animation: null } }, mounted() { this.$nextTick(function() { this.boxWidth = 250 this.totalWidth = this.boxWidth * 16 // * n of boxes this.no01 = this.$refs.marquee.querySelectorAll('.box') this.dirFromLeft = '+=' + this.totalWidth this.dirFromRight = '-=' + this.totalWidth this.mod = gsap.utils.wrap(0, this.totalWidth) this.setMarquee(this.no01, 15, this.dirFromLeft) const thisObj = this thisObj.animateFromLeft() }) }, methods: { setMarquee(which, time, direction) { const thisObj = this gsap.set(which, { x(i) { return i * thisObj.boxWidth } }) }, marquee(which, time, direction) { const thisObj = this thisObj.animation = TweenLite.to(which, { x: direction, modifiers: { x: (x) => thisObj.mod(parseFloat(x)) + 'px' }, duration: time, ease: 'none', repeat: -1 }) }, animateFromRight() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromRight) }, animateFromLeft() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromLeft) } } } </script> <style scoped> .wrapper { width: 150%; height: 150px; background: grey; overflow: hidden; } .wrapper .box { position: absolute; width: 250px; height: 50px; /* font-size: 40px; */ font-weight: 600; line-height: 50px; text-align: center; } .wrapper .boxes { position: relative; left: -250px; } </style> Link to comment Share on other sites More sharing options...
OSUblake Posted July 6, 2020 Share Posted July 6, 2020 1 hour ago, redfawx said: simply changing Timeline to TweenLite TweenLite, TweenMax, TimelineLite, and TimelineMax are deprecated. You should use the new syntax. 4 Link to comment Share on other sites More sharing options...
redfawx Posted July 6, 2020 Author Share Posted July 6, 2020 @OSUblake Thank you so much! That helps clear up my confusion of why all these things were different syntax! Thank you so much 3 Link to comment Share on other sites More sharing options...
dev_jigar Posted August 27, 2020 Share Posted August 27, 2020 On 7/6/2020 at 6:45 AM, redfawx said: This topic can be closed. I've fixed what I was aiming to accomplish with simply changing Timeline to TweenLite. Thank you again all for your help. If someone is trying to find a solution this was the code that ended up working for me (still need to dry it out): <template> <div class="w-full overflow-x-hidden"> <div id="no01" ref="marquee" class="wrapper flex font-hel"> <div class="boxes my-auto"> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-white">{{ copy }}</div> <div class="box text-2xl md:text-6xl text-yellow-500">{{ copy }}</div> </div> </div> </div> </template> <script> import { gsap, TweenLite // TimelineLite } from 'gsap/dist/gsap' import NuxtSSRScreenSize from 'nuxt-ssr-screen-size' export default { mixins: [NuxtSSRScreenSize.NuxtSSRScreenSizeMixin], props: { copy: { type: String, required: true }, marqueeText: { type: String, required: true } }, data() { return { master: null, boxWidth: null, totalWidth: null, no01: null, dirFromLeft: null, dirFromRight: null, mod: null, animation: null } }, mounted() { this.$nextTick(function() { this.boxWidth = 250 this.totalWidth = this.boxWidth * 16 // * n of boxes this.no01 = this.$refs.marquee.querySelectorAll('.box') this.dirFromLeft = '+=' + this.totalWidth this.dirFromRight = '-=' + this.totalWidth this.mod = gsap.utils.wrap(0, this.totalWidth) this.setMarquee(this.no01, 15, this.dirFromLeft) const thisObj = this thisObj.animateFromLeft() }) }, methods: { setMarquee(which, time, direction) { const thisObj = this gsap.set(which, { x(i) { return i * thisObj.boxWidth } }) }, marquee(which, time, direction) { const thisObj = this thisObj.animation = TweenLite.to(which, { x: direction, modifiers: { x: (x) => thisObj.mod(parseFloat(x)) + 'px' }, duration: time, ease: 'none', repeat: -1 }) }, animateFromRight() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromRight) }, animateFromLeft() { const thisObj = this thisObj.marquee(thisObj.no01, 15, thisObj.dirFromLeft) } } } </script> <style scoped> .wrapper { width: 150%; height: 150px; background: grey; overflow: hidden; } .wrapper .box { position: absolute; width: 250px; height: 50px; /* font-size: 40px; */ font-weight: 600; line-height: 50px; text-align: center; } .wrapper .boxes { position: relative; left: -250px; } </style> Hi @redfawx I want the same way as you mentioned in your first comment. But i need that in JS not in es6 environment. Can you please help me? Thanks JC Link to comment Share on other sites More sharing options...
ZachSaucier Posted August 27, 2020 Share Posted August 27, 2020 Hey @dev_jigar. Are you having a specific issue implementing it? We can't help blindly. Link to comment Share on other sites More sharing options...
dev_jigar Posted August 31, 2020 Share Posted August 31, 2020 Hi @ZachSaucier, Yes I am having issue actually i have post my question but not really helpful that. I would like to make something like https://cuberto.com/ have text scrolls in this section I have tried the codepen scripts in my dev server but not getting the result as i want similar to cuberto. Thanks, Jigar Link to comment Share on other sites More sharing options...
dev_jigar Posted August 31, 2020 Share Posted August 31, 2020 I am trying to implement this codepen but it is not working in my dev server. I don't know what is causing the issue because there is no script error. See the Pen qLxwPy by mikeK (@mikeK) on CodePen Please help Thanks, Jigar 1 Link to comment Share on other sites More sharing options...
redfawx Posted August 31, 2020 Author Share Posted August 31, 2020 @dev_jigar, I’m starting a new job today and getting a new laptop. Give me the day and I’ll try to get back to you later this evening. Sorry for the delay. Hope you’re all safe and healthy during these weird times. 1 Link to comment Share on other sites More sharing options...
ZachSaucier Posted August 31, 2020 Share Posted August 31, 2020 Please stick to one thread. Link to comment Share on other sites More sharing options...
dev_jigar Posted September 2, 2020 Share Posted September 2, 2020 On 8/31/2020 at 9:57 PM, ZachSaucier said: Please stick to one thread. OK.. @ZachSaucier Thanks for your reply. @redfawx. @redfawx Please message me on above thread which i have created. Thanks, Jigar Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now