janpaepke / ScrollMagic

The javascript library for magical scroll interactions.
http://ScrollMagic.io
Other
14.9k stars 2.17k forks source link

Section wipes -> Anchor Scrolling #339

Open simon88pl opened 9 years ago

simon88pl commented 9 years ago

Hello,

I would like use "section wipes" to create simple one-page webiste. I have multiple effects exactly like in "Section Wipes (manual)" example (from left, from top etc.). Unfortunately, I have two problems that I cannot resolve:

  1. How can I navigate to a specific section? I have nav bar with link contians hashtag (ex. "#photos"). I would like to add: a) navigation on click and: b) condition with window.location.hash (if hash... go to section). I tried use scrollTo('#elementID"), but it scroll only to begin of wipes container.
  2. Similar problem like here: https://github.com/janpaepke/ScrollMagic/issues/333 - with larger content.

Could you give me any advice, examples?

Thank you in advance. Simon

JoelSParker commented 9 years ago

Plus one on this issue

janpaepke commented 9 years ago

Hi!

I'm only answering Question 1 here, because of the "One-Issue-per-Post" rule, supplied in the support guidelines. Question 2 will be answered here: https://github.com/janpaepke/ScrollMagic/issues/333

You can't use the section IDs in this case, because technically their vertical position doesn't change (they only move horizontally inside the fixed container).

There's several ways you can approach this: You can either calculate the correct offset or use other elements as scroll targets.

For method one you can make use of the fact that Controller.scrollTo() also supports Scene objects as targets. This will work if you have one scene per section, as done in the Section Wipes (natural) example. Just supply the respective Scene as the scroll target and you'll see it stopping at the correct position. If you put all animations into one scene (as in Section Wipes (manual) example), you will have to calculate the correct offset like so:

var targetSection = 2;
var targetPos = scene.scrollOffset() + (scene.duration()*(targetSection - 1));
controller.scrollTo(targetPos);

The second approach is using additional (empty) elements and positioning them accordingly. So you'd create a separate DIV for each section and position them using position: absolute. Then you use those elements as the scroll targets, instead of the sections.

hope this helps, J

simon88pl commented 9 years ago

Jon,

thank you for all advice. I try to use the first method, but it doesn't work. Please take a look at this fiddle: http://jsfiddle.net/Lt97jt7k/4/ . By this method you can go only to slide 1 or last slide on all other links. Do you have any idea how to solve it? Or maybe I'm doing something wrong?

I'll try yet second approach .

Thanks, Simon

pixiebox commented 9 years ago

Same issue as @simon88pl

janpaepke commented 9 years ago

There's two problems with this: 1st: I made a logic error. If course the correct position needs to be calculated in terms of the relative progress of the scene. So: Slide1: duration_0 Slide2: duration_0.33 Slide3: duration_0.66 Slide4: duration_1

To get these numbers the calculation should be this:

    var targetSection = $(this).attr('href').substring(1);
    var targetPerc = (targetSection-1) / $('nav a').length;
    var targetPos = scene.scrollOffset() + (scene.duration()*targetPerc);

See here: http://jsfiddle.net/bjjvgkut/

2nd: The problem is though, that the above solution only works if all scenes have the same length. In your case though, they don't, because of the additional content of slide 2.

So of course you could resolve this by calculating the correct lenghts etc. But the better way would be to go for one scene per animation, as mentioned before.

See here for a working example: http://jsfiddle.net/janpaepke/pra8gta0/

Now, because the scenes run successively the offset's need to be relative, so I used positioned trigger elements to make sure of that. I can see that for this usecase this is kind of complicated and there should be a better way. (maybe I'll introduce relative offsets after all) I'll definitely think about it for the next update.

simon88pl commented 9 years ago

Jon,

first, I would like to thank you for your help and examples. Navigation works fine, Unfortunately I still haven't solve the problem with content height. I updated your jsfiddle, please look at this example - http://jsfiddle.net/pra8gta0/1/ . It is more "real-life", more like real, typical one-page website. My goal is to make on this type of page nice animations instead standard scrolling, like section wipes in your plugin (this effect looks amazing).

Do you have any ideas?

janpaepke commented 9 years ago

Well the only thing you forgot when updating the DOM is updating the classname for the animated content. check here: http://jsfiddle.net/janpaepke/pra8gta0/2/

simon88pl commented 9 years ago

@janpaepke

I checked your jsfiddle, but it not looks good / not work. Please try scroll from top to down with your own. Ex. some content is jumping from one section to antoher.

janpaepke commented 9 years ago

Again - a selector issue. Using .content animated the content of all panels. So to narrow it down you need to use section.panel.turqoise .content... http://jsfiddle.net/janpaepke/pra8gta0/3/

simon88pl commented 9 years ago

@janpaepke you're right, thanks.

http://jsfiddle.net/pra8gta0/4/ - now it works almost the perfect. During the transition from one slide to another, I have moment when content end, but new slide doesn't start yet. It looks like empty slide - http://s12.postimg.org/m6z9fbkm5/screen_1.png

Is there a way to detect the end of the .content and immediately begin show the next slide? (here is prepared image what I mean - http://s15.postimg.org/8kggcv88b/screen_2.png)

simon88pl commented 9 years ago

@janpaepke do you have any idea here?

Please look at this example - http://jsfiddle.net/pra8gta0/1/ which is more "real-life", more like real, typical one-page website. My goal is to make on this type of page nice animations instead standard scrolling, like section wipes in your plugin (this effect looks amazing) and thanks to your help I'm now very close to achieving this.

The problem is that I don't know which content is main and additional, and I want to have transition for all slide, not separately for main and additional. For smaller screens window height is small and the greater part of content is invisible.

Thanks in advance!

janpaepke commented 9 years ago

I'm sorry but I'm really having trouble understanding your issue here. :-/

simon88pl commented 9 years ago

@janpaepke I'm sorry, I have on my mind this example: http://jsfiddle.net/pra8gta0/4/

I'll try to explain it in more detail:

  1. When I'm scrolling I have content - http://s18.postimg.org/6pzk5w561/image.png - it's looks OK. Keep going...
  2. ... and I have end of slide content (text, image) - http://s30.postimg.org/ybefl7li9/image.png - it's also looks OK, so keep scrolling...
  3. ... and now, after end of slide content I expected next slide, but I get empty slide (only background) - http://s2.postimg.org/8u03fcym1/image.png & http://s17.postimg.org/ls8as4hfj/image.png , not next slide.

It's looks a bit strange and I want to prevent it. After step 2 above (end of slide content) I expect something like that: http://s23.postimg.org/6ghedah57/image.png

Jan, do you understand my issue now?

Thanks, Simon

janpaepke commented 9 years ago

Yes I do.

You can easily adjust this by changing the amount of movement for the content in line 23, like so: http://jsfiddle.net/pra8gta0/5/

Now your next problem is gonna be that the amount of movement for the content is dependent on the height. So you might end up having to modify the amount of movement and maybe also the duration accordingly and do this on resize.

The thing is if I knew from the start where you wanted to go I might have approached this differently. Now It feels overly complicated for what you are trying to do. If possible we should use natural scroll instead of animated. So I came up with this solution: http://jsfiddle.net/janpaepke/jt3s3vsu/

This will dynamically scroll the content, if there's more and animate in the next section, if there's no more content. guess this is what you were going for, right?

simon88pl commented 9 years ago

@janpaepke yes, that is, perfect! Thank you so much :). Sorry for late feedback, but I was on holiday.

I have still two issues with one-page website:

A. First of them concerns to active class on navbar - please take a look: http://jsfiddle.net/jt3s3vsu/1/ . I tried use the setClassToggle(), but it works only partially.

Expected result: active class added when the section it begins to appear (it works ok) and remains until the end of scrolling in this section (unfortunately now it is removed after end of the section appearing). Additionally there is a problem with active class on first section - it doesn't disappear at all.

B. Second - adding the appropriate hash during the scrolling.

After load I'm checking hash in URL and go to the right section (ex. "#t2" go to section t2) and it works without problems. Problem is with automatic change hash in URL during the scrolling, like changing active class in navbar. For example: (scrolling) I'm on section "t1" and I have URL "domain.com#t1" (continues scrolling) and I'm on section "t2" and I have URL "domain.com#t2" etc. I think with a callback function at the start and end of a each section, this could be easily done. Is it possible in ScrollMagic?

Thanks!

MichaelCalleia commented 8 years ago

Similar issue, though took a different approach to trying to solve—down to one more issue.

The page has five panels (the last is the footer). If I do not include the footer in the tween, the pincontainer does not extend the full length of the footer. This results in two problems: 1. A faint change in shading between within the footer. This demarcates the end of the pincontainer. 2. On mobile devices, iScroll will not scroll the full length of the footer (since the footer extends beyond the scene/tween). https://jsfiddle.net/michaelcalleia/zyqhz893/

If I include the footer as part of the tween, then the scroll distance changes in an unexpected way. In the other example (Footer is a panel, but not included in scene: https://jsfiddle.net/michaelcalleia/zyqhz893/) scroll location for anchors is calculated based on div heights (adding up the panels before it). In this version div heights do not correspond to scroll location. But, can't figure out what the relationship is between the locations ScrollMagic has calculated and the div height calculated by adding up panels. https://jsfiddle.net/michaelcalleia/gp4xzdes/

If I knew what ScrollMagic (or is it GreenSock) is doing to recalculate the y-scroll distance based on height, I could make this work.

@janpaepke is there a formula I can use?

rastapopougros commented 8 years ago

Hello, thank you very much all of you, for your examples, because I was searching for wiping panels for weeks !…

I adapted code a little for two reasons, and maybe it could be useful for other persons : 1) because I don't need animations from left, right, etc : I just want my sections to scroll normally, and at the end, stop and fix, and the next section must scroll above 2) because I have a variable number of panels : I don't want to have static code, nor in the HTML, nor in the JS

It seems to work… :)

function wipe_panels(selector) {
    // Add pannel# to each panel
    $(selector).each(function(i) {
        $(this)
            .addClass("panel" + (i + 1));
    });

    // How many panels
    var numPanels = $(selector).length;

    // Init
    var controller = new ScrollMagic.Controller({
        globalSceneOptions: {triggerHook: "onEnter"}
    });

    // Define movement of panels
    for (var i = 0; i < numPanels; i++) {
        // For the first one
        if (i == 0) {
            new ScrollMagic.Scene({triggerElement: '.panel1'})
                .addTo(controller)
                .triggerHook("onLeave");
        }
        else {
            new ScrollMagic.Scene({
                triggerElement: '.panel' + (i+1),
                duration: "100%"
            })
                .setPin('.panel' + (i), {pushFollowers: false})
                .addTo(controller);
        }
    }
}
dfabian commented 7 years ago

@janpaepke

Apologies, I know this thread is old but am wondering about your fiddle here: http://jsfiddle.net/janpaepke/pra8gta0/

Is it possible to animate through the 'next' and 'previous' scenes? So, if i'm currently on 'Slide 1' and use the link the go to 'Slide 4' I would then see slides 2 and 3 animate through rather than jumping directly to the scene?

MichaelCalleia commented 7 years ago

@dfabian Like so? https://jsfiddle.net/michaelcalleia/gp4xzdes/

dfabian commented 7 years ago

@MichaelCalleia thanks much for the response -- I did try to build a little prototype based on your fiddles but experienced the same issues with height and position being slightly off. So, i'm currently attempting to build a proof of concept off of http://jsfiddle.net/janpaepke/pra8gta0/ -- i also need to incorporate the .additionalcontent tween as seen here: http://jsfiddle.net/Lt97jt7k/

it's working well enough but the animated scroll for the anchor links is my current blocker. Unsure how to proceed with http://jsfiddle.net/janpaepke/pra8gta0/ as my base code...

MichaelCalleia commented 7 years ago

@dfabian It has been a while since I worked on this, had forgotten that problem was still unsolved.

Currently using my last best attempt on a live site, but without anchor links. There is a planned update, which will introduce anchor links, so if someone does solve this problem, please post it back here.

dfabian commented 7 years ago

@MichaelCalleia took another look at your fiddle and did some yutzing. Here: https://jsfiddle.net/dfabian/2xqkbvsx/3/ I removed some of the duration calculations and some other functional bits just to simplify. Scroll positioning seems fine(as all panels are 100% instead of auto height).

In order to compensate for content that is taller than the window I tried using the technique above in the thread: https://jsfiddle.net/dfabian/2xqkbvsx/2/ -- that works but now the anchor scrolling is off once again.

Here: https://jsfiddle.net/dfabian/2xqkbvsx/4/ i have attempted to target the correct tween(line 72 in the js) -- currently the anchor scroll links work and the additionalContent div is moving but not at the proper time. I suppose it's a gsap issue -- it's hopefully close.

that example is rough -- footer still needs attention but if I can get the .additionalContent div to complete its scroll before panel3 moves it just might work.

Would appreciate your feedback if you have any.

Thanks much.

LarsFinley commented 4 years ago

I am having this same issue with some different implementation. Here is the codepen that I have used

I have tried everything above to make it work in this auto resizing codepen but cant get anything to work.