Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reveal from bottom on scroll down and from top on scroll up #384

Closed
antoniocosta opened this issue Oct 18, 2017 · 14 comments
Closed

Reveal from bottom on scroll down and from top on scroll up #384

antoniocosta opened this issue Oct 18, 2017 · 14 comments
Labels

Comments

@antoniocosta
Copy link

Is it possible?
I have been fiddling but can't find a way to do it. I am guessing origin or distance would have to be reversed depending on scroll direction?
Please let me know... and thanks so much for the great work put into this!

@jlmakes
Copy link
Owner

jlmakes commented Oct 18, 2017

Hey Antonio,

ScrollReveal presently has no built-in awareness of scroll direction. I think options.scale is the closest approximation of getting elements to reveal "from the top on scroll up, from the bottom on scroll down". (Demo)

For what it's worth, I can point you to the correct part of the source to begin adding this functionality if you'd like to take a stab at forking the repository and creating a custom build.

@antoniocosta
Copy link
Author

Hi Julian,
Yeah... I noticed you achieve similar effect with scale. Scaling doesn't look that great when there's text though.
Yes... please do point me to the correct part of the source and I'll take a stab at it! I think it's worth a shot.
Here's roughly what I am trying to do: https://jsfiddle.net/abmc/9d0qpsb0/

@antoniocosta
Copy link
Author

antoniocosta commented Oct 18, 2017

PS: On a slightly separate note... too bad passing scale: "1, .5" for only Y scaling doesn't work anymore on the new beta.

@jlmakes
Copy link
Owner

jlmakes commented Oct 18, 2017

I can see why you want this behavior, the end result should look awesome.

Edit: This is now baked-in since beta.20

Tracking Scroll Direction.

You’ll want to start right here:
/src/instance/functions/delegate.js on line 16

I'd guess that you probably only have one container, but regardless, they are all stored within the object ScrollReveal().store.containers; each one will end up looking something like this:

{
	id: 2,
	node: <html>,
	geometry: {
		bounds: { top: 0, right: 420, bottom: 1446, left: 0 },
		height: 1446,
		width: 420,
	},
	scroll: { top: 360, left: 0 },
	direction: { x: 0, y: -1 }, // this is new!
}

Where 1 indicates scrolling down/right, and -1 indicates scrolling up/left.

@jlmakes
Copy link
Owner

jlmakes commented Oct 18, 2017

Applying The Right Animations

This is the part I think it gets complicated to bake into ScrollReveal. I think instead, you'd want to use ScrollReveal just to track visibility and provide callbacks... but not to create/apply the styles automatically.

Here is one way to do that:

var noEffect = {
	delay: 0,
	distance: '0',
	duration: 0,
	easing: 'linear',
	opacity: null,
	origin: 'bottom',
	rotate: { x: 0, y: 0, z: 0, },
	scale: 1,
	// container: this.defaults.container,
	// desktop: this.defaults.desktop,
	// mobile: this.defaults.mobile,
	reset: true,
	useDelay: 'always',
	// viewFactor: this.defaults.viewFactor,
	// viewOffset: this.defaults.viewOffset,

	afterReset: function (el) {},
	afterReveal: function (el) {},
	beforeReset: function (el) {}, // fill me in
	beforeReveal: function (el) {}, // fill me in
}

ScrollReveal().reveal('.items', noEffect)

Edit: The use of this here was a mistake in this pseudo code; these lines should be removed, or updated to use ScrollReveal() instead of this to prevent errors, e.g. ScrollReveal().defaults.container.

. . .

This reveal() effectively won't do anything, but it does give you access to callbacks.

If you create your own CSS animation/transition classes, you can apply them based on the container's direction property. Here’s an example of how you might implement those callbacks:

var beforeRevealCallback = function (el) {
	var id = el.getAttribute('data-sr-id')
	var containerId = ScrollReveal().store.elements[id].containerId
	var container = ScrollReveal().store.containers[containerId]

	if (container.direction && container.direction.y > 0) {
		el.classList.add('animateFromBottom')
	} else {
		el.classList.add('animateFromTop')
	}
}

var beforeResetCallback = function (el) {
	el.classList.remove('animateFromBottom')
	el.classList.remove('animateFromTop')
}

@jlmakes
Copy link
Owner

jlmakes commented Oct 18, 2017

Now, I haven't tested this implementation all the way through, but this should hopefully give you a solid start at achieving the effect you'd like.

PS: On a slightly separate note... too bad passing scale: "1, .5" for only Y scaling doesn't work anymore on the new beta.

This is because instead of passing options.scale into a template string like "scale(" + options.scale + ")", ScrollReveal 4 generates CSS Transform matrices—so that hack no longer works 😉

If you'd like, you can create a new issue to request that feature be added. If it can garner some community support, it could be possible to add support for something like options.scale = [1, 0.5].

@sebszocinski
Copy link

sebszocinski commented Jan 10, 2018

Hey guys, I've been looking for the same thing, and have tried your code above @jlmakes and noticed a small bug which was forcing it to always add the class of animateFromTop but the fix is...

if (container.direction > 0) { should be if (container.direction.y > 0) {

This works, however on first load before you scroll I get:

Cannot read property 'y' of undefined

@jlmakes
Copy link
Owner

jlmakes commented Jan 10, 2018

@sebszocinski Nice catch. I updated the pseudo code with:

if (container.direction && container.direction.y > 0) {
	el.classList.add('animateFromBottom')
} else {
	el.classList.add('animateFromTop')
}

Also, I've taking a second look at the commit though, and I'm not sure why container.direction is assigned before the container scroll is captured (causing it to be undefined on first load).

I'll report back with why, or bump a new version with the fix.

@antoniocosta
Copy link
Author

Whoa!!! :)
Here's my stab at that pseudocode: https://jsfiddle.net/abmc/oaxmma6y/
Just had to comment all the this.defaults.* props to get rid of undefined errors.

@jlmakes
Copy link
Owner

jlmakes commented Jan 18, 2018

@antoniocosta Nice!

You're totally right about the undefined errors with this, my brain done did a bad. I updated my earlier comment with a note on those erroneous lines, and how to fix them.

@rh-erivera
Copy link

rh-erivera commented Apr 19, 2019

Hey guys, Ive been able to achieve this affect with the following code:

block1MedImgLeft()

function block1MedImgLeft() {
  ScrollReveal().reveal('#block1-medImgLeft', { origin: 'bottom',
    afterReveal: function () {
      ScrollReveal().reveal('#block1-medImgLeft', { origin: 'top',
        afterReveal: block1MedImgLeft
      })
    }
  })
}

This assumes the user will scroll down past #block1-medImgLeft and then scroll up again. This is not a perfect solution so I am wondering if there has been any headway on this functionality. I am using this code for a SPA and would like to add the scroll effect to all elements that are dynamically generated. This means writing a function like the one above for every element with a unique Id. Any ideas on a better way to achieve this affect and apply it to all the generated elements? Thanks!

@eiranix
Copy link

eiranix commented Nov 26, 2020

@jlmakes Another refinement to your if statement there is to make it pick the correct direction on first load:

if (container.direction) {
    if (container.direction.y > 0) {
        el.classList.add('animateFromBottom');
    } else {
        el.classList.add('animateFromTop');
    };
} else {
    if(el.getBoundingClientRect().top > 0) {
        el.classList.add('animateFromBottom');
    } else {
        el.classList.add('animateFromTop');
    };
};

@BenRacicot
Copy link

BenRacicot commented Oct 4, 2022

This is awesome! Anyone have a working example?
Could we reopen this to discuss adding a directional argument for the origin option?

@antoniocosta
Copy link
Author

Quite old but try this example: https://jsfiddle.net/abmc/oaxmma6y/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants