Hello Jan,
I'm trying a fairly simple layout with two ScrollMagic scenes. I've got the elements pinning and scrolling just as I need them to - this part was ok, the library's working really well :)
I've got an example here: http://codepen.io/anon/pen/doEgzp
However the layout falls apart when the screen is resized - the pinned elements seem to retain the dimensions they were given when the page initially loaded.
Looking through the old issues in this repo lead me to https://github.com/janpaepke/ScrollMagic/issues/38 where you suggest controlling layout with CSS rather than recalculating with JS. I think I've done this as much as I can since my layout uses only relative and absolute positioning, with percentage left/right values or vh height units.
I've tried explicitly updating the scenes' duration and offset values on resize, I've tried destroying and re-creating the scenes, I've even tried scene.refresh(); and scene.update(true) just in case.
Please could you suggest anything I might have missed?
Many thanks,
Gareth
I've kept at this and I think I've cracked it.
Initially I thought it wouldn't work, but moving scene creation and destruction into their own functions that can be called on screen resize seems to work.
$(window).on('resize', function() {
scene1.destroy(true);
scene2.destroy(true);
scene1 = createScene1();
scene2 = createScene2();
});
Here's an alteration of the example from my previous comment, now working on resize: http://codepen.io/anon/pen/NqVZRV
I also had to add a class to any pinned elements, because their widths weren't getting correctly calculated. I used !important to override the inline styles that were applied by the Javascript:
.col.active {
width: 50% !important;
}
I hope this helps someone - I couldn't get a CSS-only solution to work, because as far as I could tell ScrollMagic controls the layout by wrapping the pinned elements in new divs and then applying hard-coded pixel values for dimensions and positions. But I'm sure this is down to my strange Flexbox-based layout :)
Maybe this will help with the other referenced issues:
https://github.com/janpaepke/ScrollMagic/issues/81
https://github.com/janpaepke/ScrollMagic/issues/101
https://github.com/janpaepke/ScrollMagic/issues/116
https://github.com/janpaepke/ScrollMagic/issues/379
Had the same problem with pinned divs changing height on browser resize, solution worked great!
Thank you for this! This really got me out of some :hankey:
I modified your code a little, @4foot30.
var controller = new window.ScrollMagic.Controller();
var scenes = [];
var activeScenes = [];
// push a couple of scenes to our array (below are just examples)
// examples below use measurements that would need to be updated on resize
scenes.push( function() {
return new window.ScrollMagic.Scene({
triggerElement: '.schedule',
triggerHook: 'onEnter',
duration: function() {
return document.querySelector('.schedule').offsetHeight / 4;
}
})
.setTween('.accommodation, .schedule, .registry', {
backgroundColor: '#BBD5E7',
ease: window.Linear.easeNone
})
.addTo(controller);
});
scenes.push( function() {
// example of iPad > only scene using basic width condition)
var scene = null;
if (window.innerWidth >= 768) {
scene = new window.ScrollMagic.Scene({
triggerElement: '.schedule',
triggerHook: 'onLeave',
duration: function() {
var containerHeight = document.querySelector('.schedule').offsetHeight;
return containerHeight - window.innerHeight;
}
})
.setPin('.schedule__content')
.addTo(controller);
}
return scene;
});
function addScenes(newScenes) {
// reset active scenes
activeScenes = [];
// loop over each scene and add/re-add
newScenes.forEach(function (newScene, index) {
if (typeof newScene === 'function') {
// add the new scene
var newScene = newScene();
// push it to our active scenes array
activeScenes.push(newScene);
}
});
}
// debounced re-size event - less destroying and re-adding scenes
var timeoutDuration = 400;
var resizeTimeout = null;
window.addEventListener('resize', function(event) {
if (resizeTimeout) {
clearTimeout(resizeTimeout);
}
resizeTimeout = setTimeout(function() {
// loop over each active scene
activeScenes.forEach(function (scene, index) {
// make sure scene wasn't null
if (scene) {
// destroy active scene
scene.destroy(true);
}
});
// after we have destroyed old scenes, re-add them
addScenes(scenes);
}, timeoutDuration);
});
// add initial scenes
addScenes(scenes);
Hope this helps other people too.
@janpaepke Is this really the desired way to work with ScrollMagic? Looks very hacky to me and sounds like something ScrollMagic should do on it's own. Or did I miss something?
It is incredibly hacky!
But, as per the previous comments, we couldn't find a way to do this otherwise... if it does exist nobody has shown an alternative here yet (and this issue is almost 8 months old)
@lennerd @spacedawwwg That's what I was thinking - this destroy/recreate approach just didn't feel correct when I did it, I think I've missed something fundamental.
I think we all three doing some kind of same mistake here. But I'm not able to see it. 馃檲
See this example: http://janpaepke.github.io/ScrollMagic/examples/basic/simple_pinning.html
When you scroll down to the second element to pin the element with a duration of zero and you resize the window after a while of scrolling the element is repositioned. If you watch the pin spacer in the dev tools you will see, that the elements style properties are changed dynamically. Strange ... 馃槙
those examples use fixed durations
...I wonder what would happen if they wanted to use the variable height of a div, e.g:
var scene = new window.ScrollMagic.Scene({
triggerElement: '.section',
triggerHook: 'onLeave',
duration: function() {
// This height is variable as the text drops onto more lines when scaled
var containerHeight = document.querySelector('.section').offsetHeight;
return containerHeight - window.innerHeight;
}
})
// pin item to top while section is in view
.setPin('.section__pinning-thing')
.addTo(controller);
That might have been my trouble - my layout was heavily based on vh units. But as far as I could see, pinning an element gave that element fixed dimensions, which did not seem to update on screen resize.
So I was missing the dynamic duration value you guys are using. I have the same problem without a dynamic duration value.
Any hints for me? http://codepen.io/lennerd/pen/pyaYwa
So I have first added my 'hack' to deal with the viewport re-size
secondly, I have added a 'container' around you pin item to act as the trigger (as once the 'pin' is 'pinned' it will no longer act as a trigger element)
http://codepen.io/spacedawwwg/pen/ONQqzW
NOTE: Change timeoutDuration to 100 if you want a faster re-size (though It would be overkill in my opinion... as it is only us dev that re-size their browser window wildly to see what happens)
Thanks for this.
Most helpful comment
Thank you for this! This really got me out of some :hankey:
I modified your code a little, @4foot30.
Hope this helps other people too.