Parallax effect Angular 8+
Parallax effects on Single Page Applications are definitely an old hat. However there’s always a first time to use something. After testing out a lot, which didn’t work like I needed it, I came up with a solution, based on a blog entry by Gaurav Foujdar. But with a different way to move the elements.
TLDR
Implement the parallax effect with an Angular directive, which works on the translate-y property of CSS3.
See the demo on Stackblitz or check out from GitHub.
angular-8-parallax-directive
hpmartini ⋅ 5 years ago
The parallax effect…
… not explained. I won’t bother you with boring explainations about that effect, which you can read for yourself on wikipedia if you feel the urge.
Prerequisites
First you have to have node.js
running on your system.
For Mac users
If you’re lucky to have a Mac, just run this:
brew install node
If you don’t have homebrew
installed already, go to homebrew.sh or run this:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
For anyone else
Sorry for that, but please visit nodejs.org for further instructions. I don’t have another system at hand right now.
Ahead with angular cli
Install Angulars command line interface with this, if you dont’t have it already:
npm install -g @angular/cli
Setup the Angular project
Go to the projects directory of your desire and run this command to create an Angular project:
ng new "my-awsome-parallax-project"
This creats your awesome parallax project in the directory called… I guess you know it already. The CLI fills up the project with everything needed to get it running. So start it up:
ng serve -o
The “-o” is not recommended, it just opens the angular app in your default browser.
Now the fun part starts
Lets generate a new directive:
Copyng generate directive common/parallax
This command puts the new directive in the sub directory common
, which is not necessary, but I like to have a clean structure.
The CLI also registers the directive in the app.modules.ts
, along with the default components and services.
parallax.directive.ts
1import { Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core';
2
3@Directive({ selector: '[appParallax]' })
4export class ParallaxDirective {
5 @Input('factor') set parallaxFactor(val) {
6 this.factor = val ? val : 1;
7 }
8 private factor: number;
9 constructor(
10 private elementRef: ElementRef,
11 private renderer: Renderer2
12 ) { }
13 @HostListener('window:scroll')
14 onWindowScroll() {
15 this.renderer.setProperty(
16 this.elementRef.nativeElement,
17 'style',
18 `transform: translateY(${this.getTranslation()}px)`);
19 }
20 private getTranslation() {
21 return window.scrollY * this.factor / 10;
22 }
23}
- The
factor
of how fast the element will move relative to the scroll position is passed through an@Input
decorator. By default (factor = 1) the effect will be just a bitt slower then a linear scrolling element. - The class
ElementRef
is the recommended way to manipulate elementes, because directly accessing the DOM could promote XSS attacs. - The
Renderer2
takes theElementRef
and sets the desired property in the DOM. - We just set the
translateY
CSS property of our element by multiplying the current scroll position with the passedfactor
. I devide that by 10, because the movement would be to fast or we could not work with integers in the HTML. - The
@HostListener('window:scroll')
will be triggered when you scroll - what a surprise - and thetranslate
propery will be updated.
app.component.html
1<div class="container">
2 <hello name=""></hello>
3 <p appParallax [factor]="11">I'm slowly inverting.</p>
4 <p appParallax [factor]="12">I'm doing it faster!</p>
5 <p appParallax [factor]="13">Me even more.</p>
6 <p appParallax [factor]="14">And I rock!</p>
7</div>
8
9<div class="container">
10 <h1 appParallax [factor]="0.3">Hello Parallax</h1>
11
12 <div id="linearScrollingText">I just scroll in linear speed</div>
13
14 <div id="slowText" appParallax [factor]="9">I'm going faaaa... not.</div>
15</div>
app.component.css
1.container {
2 height: 100vh;
3}
4
5#slowText {
6 position: absolute;
7 bottom: -30px;
8 right: 10px;
9}
10
11#linearScrollingText {
12 position: absolute;
13 bottom: 10px;
14 right: 10px;
15}
Nothing special here, the container
is set to 100vh
so we can scoll at all. The same goes for the positioning of the two strings at the bottom.
That’s it.
Just to remember, you can watch the demo on Stackblitz or check out from GitHub.
(gif from https://abetteruserexperience.com)