miguel-perez / smoothState.js

Unobtrusive page transitions with jQuery.
MIT License
4.43k stars 505 forks source link

Define different page transitions based on which link is clicked #143

Open mikeebee opened 9 years ago

mikeebee commented 9 years ago

Hi there!

Would it be possible to change the exiting animations based on which link was clicked? I'm trying to have it feel like a horizontal slideshow so that I have left and right exiting/entering navigation. So if I click on the left link the screen animates out left and vice versa with the right link.

I can't seem to attach anything to the click. Is this possible?

Further from this, if possible, I'd need to alter the animation on the following page, depending on the exiting animation. Is this a push too far?

Many thanks

pudgereyem commented 9 years ago

Hi @mikeebee, this is possible. I did this on a project of mine, where I have the content moving in from left/right depending on which "page" you are going to.

So when moving from Page 1 to Page 2:

  1. animate OUT to the left
  2. animate IN from the right

I wrote logic inside onClick and changed body data-pt="xxx", which I wrote different css animations for. That was how I solved the matter. Feel free to check out the site http://howarkitekter.se/ and inspect the code. I don't have time at this very moment to describe in detail.

mikeebee commented 9 years ago

@pudgereyem this is perfect! At first I was baffled at how I'd missed an onClick event in the docs, but you've added it yourself!

Thank you so much, your code being so well commented was invaluable to my understanding. I salute you!

@miguel-perez do you think this would be worth adding as a feature? I can imagine it being very useful to people.

pudgereyem commented 9 years ago

Hey @mikeebee, glad I could help out, and thanks for the kind words :)

Maybe this is to "specific" to add as a feature, but maybe we could add an "Examples" section for this repo where we could show off stuff like this. I'm more than happy to contribute if people would find that helpful. What are your thoughts on this @miguel-perez?

jesperlandberg commented 9 years ago

Sounds great @pudgereyem !

OT: nice site btw, think I saw it on Siteinspire earlier=)

JohnnyWalkerDigital commented 9 years ago

Yes. Please add these changes to SmoothState. Hopefully your request will awaken @miguel-perez from his slumber, too!

miguel-perez commented 9 years ago

Hey guys, sorry about the lack of activity on the development of smoothState. Since I'm not longer working at Weblinc, there is question on whether I should continue managing the repository. I'm hoping to hear back from Weblinc soon so that I can comfortably continue maintaining the repository.

JohnnyWalkerDigital commented 9 years ago

That's good news. I hope it happens.

(I note the License (MIT) actually allows anyone to do anything with the software, including selling it, so I am hopeful they will say yes!)

mikeebee commented 9 years ago

Yikes! Keep us posted on this Miguel, I'm literally about to use this on a project and would hate for support to evaporate. Thanks for letting us know.

JohnnyWalkerDigital commented 9 years ago

Any news, Miguel?

miguel-perez commented 9 years ago

Hey everyone! I finally got the repo back. I think this would be a super great feature and I've been giving a lot of thought on how to best implement this. I'm glad to see @pudgereyem has already worked out a solution. @pudgereyem would you be up for a chat about this some time? Let me know.

JohnnyWalkerDigital commented 9 years ago

Hurrah! How wonderful!

miguel-perez commented 9 years ago

So if we were to define a goal, it would be something like this:

As a designer, I would like to define unique page transitions depending on which
layout the user will load, so that:
- we don't have to use the same middle state
- I can define how elements that persist on the page
 should transform into new elements on the page.

Let's examine what that would look like with this Music store app. If we were to use smoothState to build this now, the app would need a "middle state" since it's unaware of which layout will be loaded. Maybe the middle state would be a solid color.

We could, however, implement something like this:

The anchor approach

<div id="main">
  <a href="/albumDetail.html?id=123" data-ss-transition="gallery-to-album-detail">
    <img src="/pharell-girl.png" />
  </a>
</div>
var
    options = {
        prefetch: true,
        transitions: {
            /* Default would run if [data-ss-transition] was not defined */
            default: {
                onStart: { /* ... */ },
                onProgress: { /* ... */ },
                onEnd: { /* ... */ },
                callback: { /* ... */ }
            },
            'gallery-to-album-detail': {
                onStart: { /* ... */ },
                onEnd: { /* ... */ },
                callback: { /* ... */ }
            },
            'album-detail-to-gallery': {
                onStart: { /* ... */ },
                onProgress: { /* ... */ },
                onEnd: { /* ... */ },
                callback: { /* ... */ }
            }
        }
    }, 
    $ssContainer = $('#main').smoothState(options);

The main issue with this implementation is that it's quite hard for a developer to back fill all the links on a website and define where they are going. There's also an issue where you might not know where the link is going, in the case of dynamic content.

Another way to approach this issue would be to define the layout at the container level:

The container approach

<div id="main" data-ss-layout="gallery">
  <a href="/albumDetail.html?id=123">
    <img src="/pharell-girl.png" />
  </a>
</div>
<div id="main" data-ss-layout="album-detail">
  ...
</div>

var
    options = {
        prefetch: true,
        transitions: {
            /* Default would run if [data-ss-layout] was not defined */
            default: {
                onStart: { /* ... */ },
                onProgress: { /* ... */ },
                onEnd: { /* ... */ },
                callback: { /* ... */ }
            },
            'gallery': {
                'album-detail': {
                    onStart: { /* ... */ },
                    onProgress: { /* ... */ },
                    onEnd: { /* ... */ },
                    callback: { /* ... */ }
                }
            },
            'album-detail': {
                'gallery': {
                    onStart: { /* ... */ },
                    onProgress: { /* ... */ },
                    onEnd: { /* ... */ },
                    callback: { /* ... */ }
                }
            }
        }
    }, 
    $ssContainer = $('#main').smoothState(options);

This is really nice because it's much easier to implement on a site. It doesn't require declaring the animation ID on each link, so there's less markup. It would also handle dynamic links, where we don't know where the link is going.

The biggest downfall to this approach is that we lose the ability to start prefetching the content while the onStart animation is going. We also lose the ability to define an onProgress. This is because we would need to make, and finish, an ajax call to the page and figure out what layout it is BEFORE we start animating.

_Thoughts anyone?_

erbridge commented 9 years ago

Could the container approach be done using the target href instead? If it took a regex, you could be as specific about the destination URL as you want.

miguel-perez commented 9 years ago

@erbridge That's an interesting thought. The only issue I see with it, however, is that it would require us to define a dictionary of Regex results to page transition IDs. I would imagine this to be really harsh for sites that use dynamic URLs, like eCommerce, blogs, or news sites.

JohnnyWalkerDigital commented 9 years ago

Wow. I really need to sit down and consider these two options. It seems like a complex issue.

erbridge commented 9 years ago

I don't think it would be that bad, since I imagine that in most cases you could use the a similar regex for a set of dynamic pages to the one you use to generate the URL in the first place, since page content is likely to be similar and therefore use the same transitions.

pudgereyem commented 9 years ago

Hey @miguel-perez, how awesome too see all the activity. I would love to chat with you about this, and anyone else that wants to join in. Miguel, if you use skype you can go ahead and add me; virremey.

miguel-perez commented 9 years ago

@pudgereyem I'm really happy to hear for you! I've gone ahead and added you on skype, as "webolize". I don't want to exclude anyone from the conversation, so we'll use this thread to document any of our thought processes and decisions.

erbridge commented 9 years ago

https://gitter.im/miguel-perez/smoothState.js

jesperlandberg commented 9 years ago

Is there any solution to this yet? Love the plugin but would like to have different animations depending on what linked i clicked or where I came from.

miguel-perez commented 9 years ago

Yes, this is currently possible.

On Fri, Oct 9, 2015 at 4:43 PM, ReGGaeBOSS notifications@github.com wrote:

Is there any solution to this yet? Love the plugin but would like to have different animations depending on what linked i clicked or where I came from.

— Reply to this email directly or view it on GitHub https://github.com/miguel-perez/smoothState.js/issues/143#issuecomment-146981732 .

Miguel Ángel Pérez User Experience Developer Miguel-Perez.com http://www.miguel-perez.com/

jesperlandberg commented 9 years ago

Nice, is there any examples on how this could be done?

miguel-perez commented 9 years ago

Hah, not really. Our demos are really lacking. Basically, you know always have access to the original anchor in all of the callbacks. So you can use that to determine which animation to run.

On Fri, Oct 9, 2015 at 4:51 PM, ReGGaeBOSS notifications@github.com wrote:

Nice, is there any examples on how this could be done?

— Reply to this email directly or view it on GitHub https://github.com/miguel-perez/smoothState.js/issues/143#issuecomment-146983145 .

Miguel Ángel Pérez User Experience Developer Miguel-Perez.com http://www.miguel-perez.com/

bfncs commented 8 years ago

Thanks for your very helpful example, @pudgereyem. Based upon your solution, I created a minimal and updated demo:

https://gist.github.com/bfncs/90ae0de3174e608465f6 https://rawgit.com/bfncs/90ae0de3174e608465f6/raw/index.html

This one uses a crude idea of viewports that are horizontally aligned to determine the needed animation: every anchor has a numeric data-target paramter that represents the needed viewport while every scene element provides a numeric data-viewport that reprents the current viewport. If the viewport needed for the clicked target is larger then the current viewport, the scene element is moved to the left, else to the right.

The logic to determine the wanted animation is implemented in the onBefore callback, the animations themselves are defined as pure CSS animations. Please feel free to take this as a starting point to implement you own animation logic.

It would be great if the module itself could provide an easier implementation, as I can see this as a commonly needed feature. Kudos for you work on the module, @miguel-perez!

miguel-perez commented 8 years ago

@bfncs thanks for that example! I'd love to see it merged into the demos folder.

bfncs commented 8 years ago

Thanks a lot, I'd like to contribute this demo to the project.

I'll issue a pull request to add the code as it is to the demos folder and you tell me whether anything needs to be changed?

miguel-perez commented 8 years ago

yup, that works.

MatteoPieroni commented 7 years ago

I know it's an old thread but I wanted to share my solution since it's not been very straightforward to implement the solution suggested by bfncs above. In my case I had a portfolio that needed a specific effect when opening a portfolio item and a generic effect when going to other pages. In my case, since the transitions where taken care for with CSS I thought to add an attribute to specific anchors and then, in the onBefore option check if that certain attribute is present. In case the attribute is present I add a specific class to the $container, in the CSS I defined a different animation for the same element using this class. Then, in the onReady option I check again the class of the container and in such a case remove it.

Something like this

onBefore: function ($currentTarget, $container) {
                //Check attribute of anchor
                var linkTo = $currentTarget.attr('to');
                if (linkTo === 'portfolio') {
                    $($container).addClass('to-portfolio');
                } else if (linkTo === 'single-work') {
                    $($container).addClass('to-single-work');
                }
            },
 onReady: {
                render: function ($container, $newContent) {
                    // Remove your CSS animation reversing class
                    $container.removeClass('is-exiting');
                    if ($container.attr('class') === 'm-scene to-portfolio') {
                        $container.removeClass('to-portfolio');
                    }
                    if ($container.attr('class') === 'm-scene to-single-work') {
                        $container.removeClass('to-single-work');
                    }
                    // Inject the new content
                    $container.html($newContent);
                }
            }

I just wanted to contribute since it may help some more noobs like me :-)