How to scroll new page to top on load on click? - javascript

I'm using barba.js to fade new pages in. Code must be placed between the barba wrapper div. When I click a link to a new page though, the new page fades in at the same position as the previous page was in. So if the user clicks a link, the new page is loading in near , which I don't want.
How can I get the new page to load in at the top?
I found the answer on stack about scrollRestoration function but I still don't understand how to make this work.
Could somebody help me to compile the js code below, add some css or html to fix this issue?
$(window).scrollTop(0);
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
function delay(n) {
n = n || 2000;
return new Promise((done) => {
setTimeout(() => {
done();
}, n);
});
}
function pageTransition() {
var tl = gsap.timeline();
tl.to(".animate-this", {
duration: .2, opacity: 0, delay: 0, y: 30, //scale:0, delay: 0.2,
});
tl.to(".animate-this", {
duration: 0, opacity: 0, delay: 0, scale:0, //scale:0, delay: 0.2,
});
tl.fromTo(".loading-screen", {width: 0, left: 0}, {
duration: 1,
width: "100%",
left: "0%",
ease: "expo.inOut",
delay: 0.3,
});
tl.to("#svg-1", {
duration: 1, opacity: 0, y: 30, stagger: 0.4, delay: 0.2,
});
tl.to(".loading-screen", {
duration: 1,
width: "100%",
left: "100%",
ease: "expo.inOut",
delay: 0, //CHANGE TIME HERE END TRANS
});
tl.set(".loading-screen", { left: "-100%", });
tl.set("#svg-1", { opacity: 1, y: 0 });
}
function contentAnimation() {
var tl = gsap.timeline();
tl.from(".animate-this", { duration: .5, y: 30, opacity: 0, stagger: 0.4, delay: 0.2 });
}
$(function () {
barba.init({
sync: true,
transitions: [
{
async leave(data) {
const done = this.async();
pageTransition();
await delay(2500);
done();
},
async enter(data) {
contentAnimation();
},
async once(data) {
contentAnimation();
},
},
],
});
});
Have a look:
https://pasteboard.co/Ja33erZ.gif
Here also a codepen to check my issue (html,css):
https://codepen.io/cat999/project/editor/AEeEdg

scrollRestoration shouldn't be necessary, this can be done by resetting scroll position during the transition:
tl.fromTo(".loading-screen", {width: 0, left: 0}, {
duration: 1,
width: "100%",
left: "0%",
ease: "expo.inOut",
delay: 0.3,
onComplete: function() {
window.scrollTo(0, 0);
}
});
Working example here: https://codepen.io/durchanek/project/editor/ZWOyjE

This should be what you're looking for:
barba.hooks.enter(() => {
window.scrollTo(0, 0);
});
(can be found in the docs)

Related

How to scroll to a Label in GSAP scrollTrigger scrub Timeline

So I'm having this problem I have a scrollTrigger Timeline and i want a button to scroll to take me to a specific position.
I tried using seek but it didnt work even ScrollTo plugin lack a support for this
I have a gsap Timeline
const tl = gsap.timeline({
paused: true,
scrollTrigger: {
trigger: '.home',
start: 'top top',
end: 'bottom+=1000 top',
pin: true,
scrub: 0.5,
markers: true
},
defaults: {
duration: 2
}
})
// Main home animation
.to(['.left'], {
clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0 100%)',
ease: 'power1.out'
}, 'scene')
// Name scaling animation
.to(['.name-title'], {
scale: 0,
ease: 'power1.out'
}, 'scene')
.from(document.getElementById('achievements'), {
autoAlpha: 0
}, '-=1.5')
// Achievements reveal animation
.from(document.getElementById('achievements').querySelectorAll('.row'), {
motionPath: {
path: [
{
x: 0,
y: 100
}
]
},
autoAlpha: 0,
stagger: 0.2,
ease: 'power3.out'
}, '-=2')
.addLabel('achievements')
// Hide achievements animation
.to(document.getElementById('achievements').querySelectorAll('.row'), {
motionPath: {
path: [
{
x: 0,
y: -100
}
]
},
autoAlpha: 0,
stagger: 0.2,
ease: 'power3.in'
}, '+=2')
and i have a button in my home that should take me to achievements section but i cant find any proper solution.
So i deviced my own workaround solution (P.S: im using Vue)
scrollTo () {
const pos = Math.ceil(document.body.scrollHeight * (this.loadTl.labels.achievements / this.loadTl.duration()))
gsap.to(window, { duration: 2, scrollTo: pos, ease: 'linear' })
}
loadTl here is a computed property for my Timeline i Found the position of achievements and used ScrollToPlugin to scroll to that pixel.
But im looking for a better way of doing this.

Barba js scroll position

I'm new to barba.js so just trying to get my head round it.
When a page transition is performed, my browser page scroll stays where it was. Is this intentional?
Is it possible to have it so after the transition the next page is loaded at the top like normal?
Here is my code
function pageTransition() {
var tl = gsap.timeline();
tl.to('ul.transition li', { duration: .5, scaleY: 1, transformOrigin: "top left", stagger: .2 })
tl.to('ul.transition li', { duration: .5, scaleY: 0, transformOrigin: "top left", stagger: .1, delay: .1})
}
function contentAnimation() {
var tl = gsap.timeline();
tl.from('.hero', { duration: 1, translateY: 50, opacity: 0 })
}
function delay(n){
n = n || 2000;
return new Promise(done => {
setTimeout(() => {
done();
}, n)
});
}
barba.init({
sync: true,
transitions: [{
async leave(data) {
const done = this.async();
pageTransition();
await delay(500);
done();
},
async enter(data) {
contentAnimation();
},
async once(data) {
contentAnimation();
}
}]
});
After checking through the docs again I found the hooks.
barba.hooks.enter(() => {
window.scrollTo(0, 0);
});
This solves the issue if anyone else is having the same issue.

Framer-motion, delay rotateY while animating x

I'm working with Framer-motion and i'm trying to find a way to delay the the animation of rotateY while the x animates to a specific position then start the rotateY.
Is this possible in Framer motion ?
Example:
const variants = {
flip: {
rotateY: 0,
x: -20,
scale: 1,
transition: {
ease: "easeInOut",
duration: 1.2
}
},
hidden: {
rotateY: 180,
x: 150,
scale: 0.5,
transition: {
ease: "easeInOut",
duration: 1
}
}
};
You can configure a transition per property. This allows you to add the necessary delay to rotateY:
const duration = 1.2;
const variants = {
flip: {
rotateY: 0,
x: -20,
scale: 1,
transition: {
ease: "easeInOut",
duration,
rotateY: {
delay: duration,
duration
}
}
},
hidden: {
rotateY: 180,
x: 150,
scale: 0.5,
transition: {
ease: "easeInOut",
duration,
rotateY: {
delay: duration,
duration
}
}
}
};
See this CodeSandbox.
#amann's post above didn't wor for me in Sep 2020 v2.65
I had to update all relevant properties in the transition to ensure they ran in succession:
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
Full example:
import * as React from "react";
import { motion } from "framer-motion";
import styled from "styled-components";
const duration = 1.2;
const variants = {
flip: {
rotateY: 180,
x: 150,
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
},
hidden: {
rotateY: 0,
x: -20,
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
}
};
const Box = styled(motion.div)`
background: white;
border-radius: 30px;
width: 150px;
height: 150px;
`;
export const Example = (props) => {
return (
<motion.div
initial={false}
animate={props.toggle ? "flip": "hidden"}
>
<Box variants={variants} />
</motion.div>
)
}
Codesandbox Demo
You can give specific values for each transition. Therefore, you can control them individually like so:
transition={{
rotate: { duration: 1 },
scale: { duration: 0.2 }
}}

Wait function/tween to complete before starting another one

I use TweenMax to animate divs with multiples .mouseover but I'd like one to complete before starting another one.
In this JSFiddle, you can see the divs overlap if going to fast on the links.
Is there an easy solution for this ?
$(document).ready(function() {
var blocPrototypo = $("#wrap-image-menu");
$("#prototypo").mouseover(function() {
TweenLite.to(blocPrototypo, 1.4, {
backgroundColor: "#24d390",
ease: Circ.easeInOut
});
TweenMax.to(blocPrototypo, 0.5, {
width: "39vw",
ease: Circ.easeInOut,
repeat: 1,
yoyo: true
});
var allExcept = $(".all-img-menu").not(document.getElementById("img-prototypo"));
TweenMax.to(allExcept, 0.9, {
left: "0px",
opacity: 0
});
TweenMax.to($("#img-prototypo"), 0.7, {
opacity: "1",
width: "55vw",
left: "-90px",
ease: Expo.easeOut,
delay: "0.65"
});
TweenMax.to($("#line-pagination"), 0.5, {
width: "76px",
ease: Circ.easeInOut,
repeat: 1,
yoyo: true
});
$("#current-page").fadeOut(function() {
$(this).text("01").fadeIn(1000);
});
});
$("#esadvalence").mouseover(function() {
TweenLite.to(blocPrototypo, 1.5, {
backgroundColor: "#e12a1c",
ease: Power1.easeOut
});
TweenMax.to(blocPrototypo, 0.5, {
width: "39vw",
ease: Circ.easeInOut,
repeat: 1,
yoyo: true
});
var allExcept = $(".all-img-menu").not(document.getElementById("img-esadvalence"));
TweenMax.to(allExcept, 0.9, {
left: "0px",
opacity: 0
});
TweenMax.to($("#img-esadvalence"), 0.7, {
opacity: "1",
width: "55vw",
left: "-90px",
ease: Expo.easeOut,
delay: "0.65"
});
TweenMax.to($("#line-pagination"), 0.5, {
width: "76px",
ease: Circ.easeInOut,
repeat: 1,
yoyo: true
});
$("#current-page").fadeOut(function() {
$(this).text("02").fadeIn(1000);
});
});
});
TweenLite and TweenMax have onComplete callbacks that can be used to await completion prior to beginning the next operation:
TweenLite.to(blocPrototypo, 1.5, {
backgroundColor: "#e12a1c",
ease: Power1.easeOut,
onComplete: function() {
// perform next operation
}
});
There is also params you can pass via onCompleteParams, which you could perhaps use to indicate to some generic function the next operation you'd want to execute.
TweenLite.to(blocPrototypo, 1.5, {
backgroundColor: "#e12a1c",
ease: Power1.easeOut,
onCompleteParams: [{ prop1: value1, prop2: value2 }],
onComplete: function(someParams) {
// perform next operation using passed params
}
});
Another approach could be using Promise or jQuery Deferred in combination with the onComplete event callback such as:
function foo() {
return new Promise(function(resolve, reject) {
TweenLite.to(blocPrototypo, 1.5, {
backgroundColor: "#e12a1c",
ease: Power1.easeOut,
onComplete: function() {
return resolve(true);
}
});
});
}
foo().then(function() {
// perform next operation
});
Hopefully that helps!

GreenSock TimelineMax starting early

I have been trying to get the animation to fire off on click, I have created the animated via TimelineMax. I can't see why but it keeps firing off the first instance of this animation, there are 5 .blackout-panel and it plays the animation automatically for the first .blackout-panel, but I have no idea why - I want the full animation to be controlled by on click.
var showBarsTL = new TimelineMax({ paused: true, onComplete: killAnimation });
$('.portfolio-panel').on("click", function () {
showBarsTL.play()
});
showBarsTL.add (TweenMax.staggerTo(".blackout-panel", 0, {y:100+ '%', onStart: "", onStartParams:["{self}"], ease: Power1.easeInOut}, 0.1275, 0));
showBarsTL.add (TweenMax.from(".blackout-panel", 0, {css:{top:"auto", bottom:"0"}}));
showBarsTL.add (TweenMax.staggerTo(".blackout-panel", 0, {css:{height:"0", bottom:"0", top:"auto"}, delay: 0.1275, ease: Power1.easeInOut}, 0.1275));
function killAnimation() {
showBarsTL.clear();
}
I have created a codePen to demonstrate this: http://codepen.io/Tekkie/pen/XpBOYV/?editors=1010
Any guidance would be appreciated. Also my killAnimation function doesn't seem to be getting fired.
EDIT: 1 - I have resolved the pausing issue by putting a delay. My new JS is as follows:
var $blackoutPanels = $('.blackout-panel');
var showBarsTL = new TimelineMax({ paused: true });
showBarsTL
.add (TweenMax.staggerTo($blackoutPanels, **0.1275**, {y:100+ '%', onStart: "", onStartParams:["{self}"], ease: Power1.easeInOut}, 0.1275, 0))
.add (TweenMax.from($blackoutPanels, 0, {css:{top:"auto", bottom:"0"}}))
.add (TweenMax.staggerTo($blackoutPanels, 0, {css:{height:"0", bottom:"0", top:"auto"}, delay: 0.1275, ease: Power1.easeInOut}, 0.1275));
$('.portfolio-panel').on("click", function () {
showBarsTL.play();
});
EDIT: 2 - I have resolved all issues using the following JS:
var $blackoutPanels = $('.blackout-panel');
var showBarsTL = new TimelineMax({
paused: true
});
showBarsTL
.add(TweenMax.staggerFrom($blackoutPanels, 0, {
yPercent: -100,
top: -100 + "%",
onStartParams: ["{self}"],
ease: Power0.easeInOut
}, 0, 0))
.add(TweenMax.staggerTo($blackoutPanels, 0.3, {
yPercent: 0,
top: 0,
onStartParams: ["{self}"],
ease: Power1.easeInOut
}, 0.125, 0))
.add(TweenMax.to($blackoutPanels, 3, {
yPercent: +100,
top: +100 + "%",
onStartParams: ["{self}"],
delay: 0.3,
ease: SlowMo.ease.config(0.4, 1, false)
}, 0.3, 0))
.add(TweenMax.to($blackoutPanels, 0, {
yPercent: -100,
top: -100 + "%",
delay: 0.375
}));
$('.portfolio-panel').on("click", function() {
showBarsTL.restart(false, false);
});
Try to set the pause like this:
var showBarsTL = new TimelineMax({onComplete: killAnimation }).paused(true);
and in your function:
$('.portfolio-panel').on("click", function () {
showBarsTL.paused(false);
});

Categories