@yoozly/ngx-parallax
Version:
Use parallax effect with Angular 16-17 compatible universal (standalone and ngModule)
138 lines • 16.6 kB
JavaScript
import { Directive, Input } from '@angular/core';
import { fromEvent, of, Subject } from 'rxjs';
import { takeUntil, filter, map, debounceTime, mergeMap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "./services/windowref.service";
export class ParallaxStandaloneDirective {
hostElement;
renderer;
wr;
speed = 30;
axe = 'y';
property = 'transform';
propertyValue = 'translate3d';
active = true;
inViewport = true;
observer;
element;
initialPosition;
componentDestroy$ = new Subject();
windowScroll$;
windowResize$;
constructor(hostElement, renderer, wr) {
this.hostElement = hostElement;
this.renderer = renderer;
this.wr = wr;
}
ngAfterViewInit() {
this.element = this.hostElement.nativeElement;
if (this.element && this.wr.nativeWindow && !this.observer) {
this.initParallax();
}
}
initParallax() {
this.observer = this.createObserver(0);
this.observer.observe(this.element);
const parallax$ = of('').pipe(takeUntil(this.componentDestroy$), filter(() => this.active && this.inViewport), map(() => {
const coef = this.calculateCoef();
this.renderParallax(coef);
return coef;
}));
this.windowScroll$ = fromEvent(this.wr.nativeWindow, 'scroll').pipe(mergeMap(() => parallax$));
this.windowResize$ = fromEvent(this.wr.nativeWindow, 'resize').pipe(debounceTime(500), mergeMap(() => parallax$));
}
startParallax() {
this.inViewport = true;
if (this.wr.nativeWindow && this.initialPosition === undefined) {
this.initialPosition = this.wr.nativeWindow.pageYOffset;
this.windowScroll$.subscribe();
this.windowResize$.subscribe();
}
}
destroyParallax() {
this.inViewport = false;
}
calculateCoef() {
return ((this.wr.nativeWindow.pageYOffset - this.initialPosition) *
(this.speed / 100));
}
renderParallax(coef) {
this.renderer.setStyle(this.element, this.property, this.getPropertyValue(coef));
}
getPropertyValue(coef) {
let result = `${coef}px`;
if (this.property === 'transform') {
switch (this.propertyValue) {
case 'translate3d':
result = `translate3d(${this.getAxe(coef)})`;
break;
case 'scale':
result = `scale(${coef})`;
break;
case 'rotate':
result = `rotate(${coef}deg)`;
break;
}
}
switch (this.property) {
case 'opacity':
result = `${coef}`;
break;
}
return result;
}
getAxe(coef) {
let axe = [0, coef, 0];
if (this.axe === 'x') {
axe = [coef, 0, 0];
}
else if (this.axe === 'z') {
axe = [0, 0, coef];
}
return `${axe[0]}px, ${axe[1]}px, ${axe[2]}px`;
}
createObserver(pourcent) {
const options = {
rootMargin: '0px',
threshold: pourcent / 100
};
const isIntersecting = (entry) => entry.isIntersecting || entry.intersectionRatio > 0;
return new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (isIntersecting(entry)) {
this.startParallax();
}
else {
this.destroyParallax();
}
});
}, options);
}
ngOnDestroy() {
this.componentDestroy$.next(false);
this.componentDestroy$.complete();
if (this.wr.nativeWindow) {
this.observer.disconnect();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.3", ngImport: i0, type: ParallaxStandaloneDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.BrowserWindowRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.3", type: ParallaxStandaloneDirective, isStandalone: true, selector: "[ngx-parallax]", inputs: { speed: "speed", axe: "axe", property: "property", propertyValue: "propertyValue", active: "active" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.3", ngImport: i0, type: ParallaxStandaloneDirective, decorators: [{
type: Directive,
args: [{
selector: '[ngx-parallax]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.BrowserWindowRef }], propDecorators: { speed: [{
type: Input
}], axe: [{
type: Input
}], property: [{
type: Input
}], propertyValue: [{
type: Input
}], active: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBhcmFsbGF4LXN0YW5kYWxvbmUuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXBhcmFsbGF4L3NyYy9saWIvbmd4LXBhcmFsbGF4LXN0YW5kYWxvbmUuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUtOLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxTQUFTLEVBQWMsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFRaEYsTUFBTSxPQUFPLDJCQUEyQjtJQWdCNUI7SUFDQTtJQUNBO0lBakJELEtBQUssR0FBRyxFQUFFLENBQUM7SUFDWCxHQUFHLEdBQUcsR0FBRyxDQUFDO0lBQ1YsUUFBUSxHQUFHLFdBQVcsQ0FBQztJQUN2QixhQUFhLEdBQUcsYUFBYSxDQUFDO0lBQzlCLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFFZixVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQ2xCLFFBQVEsQ0FBdUI7SUFDL0IsT0FBTyxDQUFjO0lBQ3JCLGVBQWUsQ0FBUztJQUN4QixpQkFBaUIsR0FBRyxJQUFJLE9BQU8sRUFBVyxDQUFDO0lBQzNDLGFBQWEsQ0FBcUI7SUFDbEMsYUFBYSxDQUFxQjtJQUUxQyxZQUNVLFdBQXVCLEVBQ3ZCLFFBQW1CLEVBQ25CLEVBQW9CO1FBRnBCLGdCQUFXLEdBQVgsV0FBVyxDQUFZO1FBQ3ZCLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsT0FBRSxHQUFGLEVBQUUsQ0FBa0I7SUFDM0IsQ0FBQztJQUVKLGVBQWU7UUFDYixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDO1FB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TyxJQUFJLG9CQUFvQixDQUFDLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQ3BELE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDeEIsSUFBSSxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUN2QixDQUFDO3FCQUFNLENBQUM7b0JBQ04sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUN6QixDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDZCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xDLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzdCLENBQUM7SUFDSCxDQUFDO3VHQWxKVSwyQkFBMkI7MkZBQTNCLDJCQUEyQjs7MkZBQTNCLDJCQUEyQjtrQkFKdkMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsZ0JBQWdCO29CQUMxQixVQUFVLEVBQUUsSUFBSTtpQkFDakI7c0lBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLEdBQUc7c0JBQVgsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGlyZWN0aXZlLFxuICBJbnB1dCxcbiAgRWxlbWVudFJlZixcbiAgUmVuZGVyZXIyLFxuICBPbkRlc3Ryb3ksXG4gIEFmdGVyVmlld0luaXRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwsIGZpbHRlciwgbWFwLCBkZWJvdW5jZVRpbWUsIG1lcmdlTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBCcm93c2VyV2luZG93UmVmIH0gZnJvbSAnLi9zZXJ2aWNlcy93aW5kb3dyZWYuc2VydmljZSc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tuZ3gtcGFyYWxsYXhdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZVxufSlcbmV4cG9ydCBjbGFzcyBQYXJhbGxheFN0YW5kYWxvbmVEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuICBASW5wdXQoKSBzcGVlZCA9IDMwO1xuICBASW5wdXQoKSBheGUgPSAneSc7XG4gIEBJbnB1dCgpIHByb3BlcnR5ID0gJ3RyYW5zZm9ybSc7XG4gIEBJbnB1dCgpIHByb3BlcnR5VmFsdWUgPSAndHJhbnNsYXRlM2QnO1xuICBASW5wdXQoKSBhY3RpdmUgPSB0cnVlO1xuXG4gIHByaXZhdGUgaW5WaWV3cG9ydCA9IHRydWU7XG4gIHByaXZhdGUgb2JzZXJ2ZXI6IEludGVyc2VjdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIGluaXRpYWxQb3NpdGlvbjogbnVtYmVyO1xuICBwcml2YXRlIGNvbXBvbmVudERlc3Ryb3kkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcbiAgcHJpdmF0ZSB3aW5kb3dTY3JvbGwkOiBPYnNlcnZhYmxlPG51bWJlcj47XG4gIHByaXZhdGUgd2luZG93UmVzaXplJDogT2JzZXJ2YWJsZTxudW1iZXI+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaG9zdEVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIHByaXZhdGUgd3I6IEJyb3dzZXJXaW5kb3dSZWZcbiAgKSB7fVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICBpZiAodGhpcy5lbGVtZW50ICYmIHRoaXMud3IubmF0aXZlV2luZG93ICYmICF0aGlzLm9ic2VydmVyKSB7XG4gICAgICB0aGlzLmluaXRQYXJhbGxheCgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaW5pdFBhcmFsbGF4KCk6IHZvaWQge1xuICAgIHRoaXMub2JzZXJ2ZXIgPSB0aGlzLmNyZWF0ZU9ic2VydmVyKDApO1xuICAgIHRoaXMub2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1lbnQpO1xuXG4gICAgY29uc3QgcGFyYWxsYXgkID0gb2YoJycpLnBpcGUoXG4gICAgICB0YWtlVW50aWwodGhpcy5jb21wb25lbnREZXN0cm95JCksXG4gICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5hY3RpdmUgJiYgdGhpcy5pblZpZXdwb3J0KSxcbiAgICAgIG1hcCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNvZWYgPSB0aGlzLmNhbGN1bGF0ZUNvZWYoKTtcbiAgICAgICAgdGhpcy5yZW5kZXJQYXJhbGxheChjb2VmKTtcbiAgICAgICAgcmV0dXJuIGNvZWY7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLndpbmRvd1Njcm9sbCQgPSBmcm9tRXZlbnQodGhpcy53ci5uYXRpdmVXaW5kb3csICdzY3JvbGwnKS5waXBlKFxuICAgICAgbWVyZ2VNYXAoKCkgPT4gcGFyYWxsYXgkKVxuICAgICk7XG5cbiAgICB0aGlzLndpbmRvd1Jlc2l6ZSQgPSBmcm9tRXZlbnQodGhpcy53ci5uYXRpdmVXaW5kb3csICdyZXNpemUnKS5waXBlKFxuICAgICAgZGVib3VuY2VUaW1lKDUwMCksXG4gICAgICBtZXJnZU1hcCgoKSA9PiBwYXJhbGxheCQpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRQYXJhbGxheCgpOiB2b2lkIHtcbiAgICB0aGlzLmluVmlld3BvcnQgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMud3IubmF0aXZlV2luZG93ICYmIHRoaXMuaW5pdGlhbFBvc2l0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuaW5pdGlhbFBvc2l0aW9uID0gdGhpcy53ci5uYXRpdmVXaW5kb3cucGFnZVlPZmZzZXQ7XG4gICAgICB0aGlzLndpbmRvd1Njcm9sbCQuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLndpbmRvd1Jlc2l6ZSQuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBkZXN0cm95UGFyYWxsYXgoKTogdm9pZCB7XG4gICAgdGhpcy5pblZpZXdwb3J0ID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGNhbGN1bGF0ZUNvZWYoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKFxuICAgICAgKHRoaXMud3IubmF0aXZlV2luZG93LnBhZ2VZT2Zmc2V0IC0gdGhpcy5pbml0aWFsUG9zaXRpb24pICpcbiAgICAgICh0aGlzLnNwZWVkIC8gMTAwKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclBhcmFsbGF4KGNvZWY6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICB0aGlzLmVsZW1lbnQsXG4gICAgICB0aGlzLnByb3BlcnR5LFxuICAgICAgdGhpcy5nZXRQcm9wZXJ0eVZhbHVlKGNvZWYpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UHJvcGVydHlWYWx1ZShjb2VmOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGxldCByZXN1bHQgPSBgJHtjb2VmfXB4YDtcblxuICAgIGlmICh0aGlzLnByb3BlcnR5ID09PSAndHJhbnNmb3JtJykge1xuICAgICAgc3dpdGNoICh0aGlzLnByb3BlcnR5VmFsdWUpIHtcbiAgICAgICAgY2FzZSAndHJhbnNsYXRlM2QnOlxuICAgICAgICAgIHJlc3VsdCA9IGB0cmFuc2xhdGUzZCgke3RoaXMuZ2V0QXhlKGNvZWYpfSlgO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdzY2FsZSc6XG4gICAgICAgICAgcmVzdWx0ID0gYHNjYWxlKCR7Y29lZn0pYDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncm90YXRlJzpcbiAgICAgICAgICByZXN1bHQgPSBgcm90YXRlKCR7Y29lZn1kZWcpYDtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzd2l0Y2ggKHRoaXMucHJvcGVydHkpIHtcbiAgICAgIGNhc2UgJ29wYWNpdHknOlxuICAgICAgICByZXN1bHQgPSBgJHtjb2VmfWA7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIGdldEF4ZShjb2VmOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGxldCBheGUgPSBbMCwgY29lZiwgMF07XG5cbiAgICBpZiAodGhpcy5heGUgPT09ICd4Jykge1xuICAgICAgYXhlID0gW2NvZWYsIDAsIDBdO1xuICAgIH0gZWxzZSBpZiAodGhpcy5heGUgPT09ICd6Jykge1xuICAgICAgYXhlID0gWzAsIDAsIGNvZWZdO1xuICAgIH1cblxuICAgIHJldHVybiBgJHtheGVbMF19cHgsICR7YXhlWzFdfXB4LCAke2F4ZVsyXX1weGA7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU9ic2VydmVyKHBvdXJjZW50OiBudW1iZXIpIHtcbiAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgcm9vdE1hcmdpbjogJzBweCcsXG4gICAgICB0aHJlc2hvbGQ6IHBvdXJjZW50IC8gMTAwXG4gICAgfTtcblxuICAgIGNvbnN0IGlzSW50ZXJzZWN0aW5nID0gKGVudHJ5OiBJbnRlcnNlY3Rpb25PYnNlcnZlckVudHJ5KSA9PlxuICAgICAgZW50cnkuaXNJbnRlcnNlY3RpbmcgfHwgZW50cnkuaW50ZXJzZWN0aW9uUmF0aW8gPiAwO1xuXG4gICAgcmV0dXJuIG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcigoZW50cmllcywgb2JzZXJ2ZXIpID0+IHtcbiAgICAgIGVudHJpZXMuZm9yRWFjaCgoZW50cnkpID0+IHtcbiAgICAgICAgaWYgKGlzSW50ZXJzZWN0aW5nKGVudHJ5KSkge1xuICAgICAgICAgIHRoaXMuc3RhcnRQYXJhbGxheCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZGVzdHJveVBhcmFsbGF4KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sIG9wdGlvbnMpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5jb21wb25lbnREZXN0cm95JC5uZXh0KGZhbHNlKTtcbiAgICB0aGlzLmNvbXBvbmVudERlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgaWYgKHRoaXMud3IubmF0aXZlV2luZG93KSB7XG4gICAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==