Closed antoniocosta closed 7 years ago
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.
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/
PS: On a slightly separate note... too bad passing scale: "1, .5"
for only Y scaling doesn't work anymore on the new beta.
I can see why you want this behavior, the end result should look awesome.
beta.20
~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.
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 useScrollReveal()
instead ofthis
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')
}
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]
.
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
@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.
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.
@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.
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!
@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');
};
};
This is awesome! Anyone have a working example?
Could we reopen this to discuss adding a directional
argument for the origin option?
Quite old but try this example: https://jsfiddle.net/abmc/oaxmma6y/
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!