Parallax digital story. Need to scroll slower and smoother - javascript

Problem:
So, made a digital story with illustrations. I pieced it all together by using simple waapi css animations, that gives a parallax effect. Problem with my code is that all my content/images is placed on a timeline in relation to a offset value between 0 and 1. This makes the whole story blast trough in one fast scroll motion on the trackpad/scrollwheel :(
Tried various css and js methods to smooth and slow down the scroll without luck.
How can I best write this so the scroll is slowed down?
Demo (Best in 1440px900px window): https://andyradall.github.io/andylax/
Source code git: https://github.com/Andyradall/andylax
Source code in Jsfiddle: https://jsfiddle.net/Andyradall/yLvboa6t/8/
Example of javascript code for one of the images:
// Settings for animations length
const animasjonSettings = {
duration: 12000,
fill: "both"
}
// Settings for one of the images
const tekstboks3 = document.querySelector("#tekstboks3");
const tekstboks3Keyframes = [
{top: "2.5rem", left: "-22rem", opacity: 1.0},
{top: "2.5rem", left: "-22rem", opacity: 1.0, offset: 0.41},
{top: "2.5rem", left: "3rem", opacity: 1.0, offset: 0.46},
{top: "2.5rem", left: "3rem", opacity: .01, offset: 0.7},
{top: "2.5rem", left: "3rem", opacity: .01,}
];
const tekstboks3Animasjon = tekstboks3.animate(tekstboks3Keyframes, animasjonSettings);
// Start all animations in array on scroll
function animerAlle() {
const y = scrollY;
for(const animasjon of animasjoner) {
animasjon.currentTime = y * 3;
}
}
document.addEventListener("scroll", animerAlle);

I'm not 100% sure since i don't have a tactile device, but I could make the scroll longer (and thus, slower) only by changing these two properties of your code (multiplying by 2 but you can try other operations...)
/* index.css */
body {
height: 1530vh; /* 765 * 2 = 1530 */
background: #7DD3E2;
}
// index.js
// Innstilling for animasjonslengde
const animasjonSettings = {
duration: 24000, // 12000 * 2 = 24000
fill: "both"
}
don't know if it's what you want...
Besides, really good job your site is amazing!
[edit]
for the smooth part, you can look into scroll-snap property but I fear it would make more harm than good

Related

Popmotion: Bounce Effect

As seen below, I tried to create a bounce effect at the end of another animation, in Popmotion.
I was not sure how to go about it, so I tried to reverse the velocity once it hit a certain threshold.
The results are sporadic and does not always work.
Any ideas on how to best create a bounce effect with Popmotion?
Clarification 1
The ball bounces most of the times, but how long it bounces varies greatly. Sometimes it stops abruptly after just one bounce. I am not sure why that is, because I do not fully understand how the solution actually works. Why does it slow down, if we simply reverse the velocity. Looking at the code, my guess would have been that the ball would oscillate indefinitely, but it does not.
Clarification 2
In Firefox 65.0.1, the animation seems consistent. In Chrome 72.x, it acts irrationally. I.e. the animation and bounce length changes each time.
const {
tween,
styler,
value,
easing,
physics,
transform
} = popmotion;
const {
clamp,
pipe,
conditional
} = transform;
const ball = document.querySelector('#ball');
const ballStyler = styler(ball);
const ballY = value(0, ballStyler.set('y'));
const BOTTOM = 50;
const pipedPhysics = physics({
acceleration: 2000,
// friction: 0.5,
// restSpeed: 0,
// springStrength: 300,
// to: 50
}).pipe(clamp(0, BOTTOM));
const anim = pipedPhysics.start(ballY);
ballY.subscribe(v => {
if (v >= BOTTOM) {
anim.setVelocity(-ballY.getVelocity());
};
// console.log('v, vel: ', v, ballY.getVelocity());
});
#ball {
background: #ff2420;
border-radius: 50%;
position: absolute;
left: 50%;
width: 50px;
height: 50px;
margin: 0px;
transform-origin: 50%;
}
<script src="https://unpkg.com/popmotion/dist/popmotion.global.min.js"></script>
<div id="ball"></div>

How to keep a view the same size in React Native when display size changes?

Our app includes a screen where there is a large circle in the background which changes position. It's mostly absolute positioning using this sort of style. The circle changes to use the right style and animates into the new position underneath some tutorial text.
const { height, width } = Dimensions.get('screen')
const circleRadius = isIphoneX() ? height * 0.55 : height * 0.60
export const styles = StyleSheet.create({
circleMassiveLeft: {
position: 'absolute',
backgroundColor: primary,
width: circleRadius * 2,
height: circleRadius * 2,
borderRadius: circleRadius,
left: -circleRadius + width - 50,
top: -circleRadius + height / 2
},
circleMassiveRight: {
position: 'absolute',
backgroundColor: primary,
width: circleRadius * 2,
height: circleRadius * 2,
borderRadius: circleRadius,
left: -circleRadius + 50,
top: -circleRadius + height / 2
}
})
This has been working great to display the circle in the correct position across multiple display sizes. Since it needs to be so precisely positioned, using absolute positioning seems to be a better solution than flex in this case. Our challenge is that when changing the system settings in Android to display size small, the circle becomes smaller. Of course, that makes sense in a way, but this particular element looks pretty awful because of the layout of the rest of the screen when it's resized to be smaller. Elements that used to be on top of it are now poking out! Is there a way to make sure that this element displays at the same size regardless of Android system display size settings? Poking around the docs, there doesn't seem to be a basic setting for this.
Try to use www.npmjs.com/package/react-native-responsive-dimensions
read this
In the article they using: react-native-size-matters

Stack "transform: translateY" values in GreenSock?

I just came across this wonderful product and realized this is exactly what I need! I have a huge image that is x times the window size, so I want to scroll to the very bottom of it on button click. I would do so with CSS like this:
#keyframes {
to {
transform: translateY(-100%) translateY(100vh);
}
}
This proved to be a crossbrowser way in CSS instead of:
transform: translateY(calc(-100% + 100vh));
Is there any way to do so with TweenMax? I do understand that I can calculate these values in pixels and specify them explicitly:
var value = -$('img').height() + $(window).height();
var tweenDown = TweenMax.to("img", 5, {y: value});
However the advantage of the "stacked" way is that when you resize the window, it keeps the image in the same position.
Thanks in advance!
This is what I came up with for those wondering:
TweenMax.to('img', 5, {
transform: 'translate3d(0,100vh,0)',
percentY: -100
});
[My solution to the bottom]
Actually, with current version of GSAP I think this would be
TweenMax.to('img', 5, {
y: '100vh',
yPercent: -100
});
But, the 'the notes about transforms' documentation section says
To do percentage-based translation use xPercent and yPercent (added in version 1.13.0) instead of x or y which are typically px-based
https://greensock.com/docs/Plugins/CSSPlugin
Judging by the above,
I think 100vh for y would be interpreted as 100px when added in the css matrix property. In order for this to fully work, I opted for the following:
TweenMax.to('img', 5, {
y: window.innherHeight, // or $(window).heigth()
yPercent: -100
});

Javascript Animate Values as Percentages

I have a client project I inherited that uses javascript to create various animation effects while the user scrolls down through the site (sort of like a parallax site).
The problem with it is that it changes the values in pixels, and what we want it do now is user percentages.
For example, this code brings the #location-left div in from the left, by increasing its width from 0 to 750px, when user scrolls down 1800 pixels. It does this over a 200px interval. It achieves this by writing inline CSS into the DIV tag.:
{
selector: '#location-left',
startAt: 1800,
endAt: 2000,
onEndAnimate:function( anim ) {},
keyframes: [
{
position: 0,
properties: {
"top" : 0,
"width" : 0
}
},
{
position: 1,
properties: {
"top" : 0,
"width" : 750
}
}
]
}
What I want it to do, instead, is go from 0% to 50%. My initial thought was to calculate up a set of var tags:
var a = $(document).width();
var a3= Math.floor(a * 0.3); // 30%
var a5= Math.floor(a * 0.5); // 50%
var a8= Math.floor(a * 0.8); // 80%
etc.
Before I got too far down that rabbit hole, though, I wanted to see if there was an easier approach that I was just missing.
See this question. You can just put the percentages in quotes, like:
{
position: 0,
properties: {
"top" : "10%",
"width" : "30%"
}
},

Transition.translate Easing vs SpringTransition

I'm currently experimenting a bit with Famo.us and there is actually one thing I can't yet wrap my head around.
In a small example i tried to create a HeaderFooterLayout, where the header contains a simple icon left aligned. A click on it will bounce it to the right end of the header.
Now with a simple Transform.translate this works not as smooth as expected on my Nexus4 and Nexus 7, but hell changing it to a SpringTransition rocks. Here is the code example:
var Transitionable = require('famous/transitions/Transitionable');
var SpringTransition = require('famous/transitions/SpringTransition');
Transitionable.registerMethod('spring', SpringTransition);
var logoStateModifier = new StateModifier({});
var logo = new ImageSurface({
size: [186, 43],
content: 'images/my-logo.png'
});
var posX = 0;
var adjustment = 20;
// Click event on image
logo.on('click', function() {
if(posX === 0) {
posX = (window.innerWidth - logo.size[0] - adjustment);
} else {
posX = 0;
}
var spring = {
method: 'spring',
period: 10,
dampingRatio: 0.3,
};
// transform translate with Easing
logoStateModifier.setTransform(
Transform.translate(posX,0,0),
{ duration: 1000, curve: Easing.inOutBack}
);
// spring transition
logoStateModifier.setTransform(
Transform.translate(posX, 0, 0), spring
);
});
So what I don't understand here is why Easing is so "slow" compared to the Physics driven SpringTransition?
The spring transition your requesting has a period of 10ms while the easing transition is 1000ms or 100 times slower. I tried your code "as is" and with a modification that compares more apples to apples and the transitions can run at the same speed (both laptop and devices.) First you should note that the minimum spring period is 150ms so the 10ms your asking for is actually 150. Second you are stacking the transitions so that one follows the other. The easing will take 1 second and then the spring will oscillate. You may want to try something slightly different... set the transitions to the following:
// transform translate with Easing
logoStateModifier.setTransform(
Transform.translate(posX,0,0),
{ duration: 150, curve: Easing.inOutBack}
);
// spring transition
logoStateModifier.setTransform(
Transform.translate(0, 0, 0), spring
);
This will behave slightly differently. On click (every other click actually) the logo will cross the screen at high speed and then come back. I expect you'll find that these transitions run at comparable high speeds. Of course for a slower more viewable test you can set the spring period to 1000 and the easing duration to the same and again the speeds should be comparable.

Categories