jonkwheeler / ScrollScene

ScrollScene is an extra layer on top of ScrollMagic as well as using IntersectionObserver to achieve similar effects.
https://scrollscene.jonkwheeler.now.sh/
MIT License
136 stars 9 forks source link

duration: "100%" gets the size of viewport not container #35

Closed NasKadir123 closed 4 years ago

NasKadir123 commented 4 years ago

Hi! First of all, thanks for this great plugin!!!

I've got an issue when using ScrollScene with duration:

import { ScrollScene, addIndicators } from 'scrollscene';

const domNode = document.querySelector('.test')
const anotherDomNode = document.querySelectorAll('.test .card')
const tl = gsap.timeline({ paused: true })

tl.to(anotherDomNode, {
  x: -200,
  duration: 1,
  ease: "none",
})

const scrollScene = new ScrollScene({
  triggerElement: domNode,
  gsap: {
    timeline: tl,
  },
  triggerHook: 1,
  duration: "100%",
})
scrollScene.Scene.addIndicators({ name: 'pin scene', colorEnd: 'yellow' })

So indicators shows start and end of the duration, which is not the height of the container (900px), it's the height of viewport (640px).

Am I doing something wrong? Can you help me, please?

jonkwheeler commented 4 years ago

Yeah, that's accurate. That's how ScrollMagic works. http://scrollmagic.io/docs/ScrollMagic.Scene.html#duration

jonkwheeler commented 4 years ago

If you want the scene length to match the element height, you need to calc and provide that. Try using https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

jonkwheeler commented 4 years ago

If you want to learn more on ScrollMagic, I like Petr's courses. https://ihatetomatoes.net/get-scrollmagic-101/

p.s. I did not create ScrollMagic, just this layer on top of it.

NasKadir123 commented 4 years ago

Yeah, that's accurate. That's how ScrollMagic works. http://scrollmagic.io/docs/ScrollMagic.Scene.html#duration

For example "100%" will keep the duration always exactly at the inner height of the scroll container.

This line in scrollMagic docs confused me. Thanks for your answer!

jonkwheeler commented 4 years ago

Ah, I see what you mean...

ScrollMagic has the ability to change the container...

So in your case, you want a unique controller. What you want to do is setup a new controller.

const scrollScene = new ScrollScene({
  useGlobalController: false,
  controller: {
    container: domNode
  }
})

and at this point you're using a local controller, and you should be able to pass a different container to that... let me know if that works. If not, I might need to add some code to help out.

NasKadir123 commented 4 years ago

@jonkwheeler not sure, that I have enough knowledge what you mean, I've just started to use scrollMagic, you mean make this:

const scrollScene = new ScrollScene({
  triggerElement: domNode,
  useGlobalController: false,
  controller: {
    container: domNode
  },
  duration: "100%",
  gsap: {
    timeline: tl,
  },
})

scrollScene.Scene.addIndicators({ name: 'pin scene', colorEnd: 'yellow' })

and check if is it working, right?

jonkwheeler commented 4 years ago

Yeah, see if that works. That should set the controller to use domNode versus window.

NasKadir123 commented 4 years ago

Yeah, see if that works. That should set the controller to use domNode versus window.

19:57:32:587 (ScrollMagic.Scene) -> ERROR: Invalid value for option "offset": NaN ScrollMagic.js:2647
    log ScrollMagic.js:2647
    _log ScrollMagic.js:1211
    validateOption ScrollMagic.js:1680
    validateOption ScrollMagic.js:1669
    construct ScrollMagic.js:835
    Scene ScrollMagic.js:2409
    Scene ScrollMagic.js:2491
    ScrollScene ScrollScene.js:161
    js script.js:25
    Webpack 5

I'm getting this error, but indicators are correct, animation is at the end of timeline.

jonkwheeler commented 4 years ago

Remove the gsap stuff for now and just see if firing an event or className toggle works. Seems like ScrollMagic is unable to set the container correctly.

NasKadir123 commented 4 years ago

@jonkwheeler No, it doesn't work, trigger pin scene is static and has the same level with end pin scene. Element has new class, but it doesn't change on scroll.

jonkwheeler commented 4 years ago

Anyway you can provide code. I might be able to debug this at some point shortly.

NasKadir123 commented 4 years ago
import { ScrollScene, addIndicators } from 'scrollscene';

const domNode = document.querySelector('.test')
const anotherDomNode = document.querySelector('.test .card')

const scrollScene = new ScrollScene({
  triggerElement: domNode,
  useGlobalController: false,
  controller: {
    container: domNode
  },
  toggle: {
    element: anotherDomNode,
    className: 'turn-blue',
  },
  duration: "100%"
})

scrollScene.Scene.addIndicators({ name: 'pin scene', colorEnd: 'yellow' })
jonkwheeler commented 4 years ago

Alright, I'm able to replicate, which is good! Easier to debug...

jonkwheeler commented 4 years ago

@NasKadir123 I def get this error, but I'm not sure it's an error. The ScrollMagic container on the controller is the element you want to add scroll tracking to. In your case, it's different, you want scroll tracking on the window still, but the duration to be height of the element. I think I should add a feature to make the duration match the element of choice, but I'll need a bit to update that.

In the meantime, any chance you could set the duration as a breakpoint and semi-match the css?

You can do

const scrollScene = new ScrollScene({
  duration: { 0: '50%', 768: '100%, 1440: 500 },
})

and this will update the length of the scene based on the mobile-first breakpoints you set.

jonkwheeler commented 4 years ago

I released a new update! It's pretty dope. You can now set the duration as an HTMLElement, and now the scene will last the length of that element.

https://scrollscene.jonkwheeler.now.sh/?path=/story/scrollscene-duration--duration-domnode

Check out the code here: https://github.com/jonkwheeler/ScrollScene/blob/master/src/stories/story.js#L706

const scrollScene = new ScrollScene({
  triggerElement,
  toggle: {
    element: containerElement,
    className: "turn-blue",
    reverse: true,
  },
  triggerHook: 0.25,
  duration: triggerElement,
});