New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

rfx-parallax

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rfx-parallax - npm Package Compare versions

Comparing version 2.2.7 to 3.0.0

esm2015/lib/animations/index.js

943

bundles/rfx-parallax.umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs')) :
typeof define === 'function' && define.amd ? define('rfx-parallax', ['exports', '@angular/core', 'rxjs'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['rfx-parallax'] = {}, global.ng.core, global.rxjs));
}(this, (function (exports, i0, rxjs) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs'), require('@angular/animations')) :
typeof define === 'function' && define.amd ? define('rfx-parallax', ['exports', '@angular/core', 'rxjs', '@angular/animations'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['rfx-parallax'] = {}, global.ng.core, global.rxjs, global.ng.animations));
}(this, (function (exports, i0, rxjs, animations) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (Object.prototype.hasOwnProperty.call(b, p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); };
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try {
step(generator.next(value));
}
catch (e) {
reject(e);
} }
function rejected(value) { try {
step(generator["throw"](value));
}
catch (e) {
reject(e);
} }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function () { if (t[0] & 1)
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () {
return e[k];
}
});
}
catch (e) {
op = [6, e];
y = 0;
}
finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
});
}
n['default'] = e;
return Object.freeze(n);
}
var __createBinding = Object.create ? (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
}) : (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
o[k2] = m[k];
});
function __exportStar(m, o) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
__createBinding(o, m, p);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
/** @deprecated */
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/** @deprecated */
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
function __spreadArray(to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
}
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n])
i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try {
step(g[n](v));
}
catch (e) {
settle(q[0][3], e);
} }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
}
else {
cooked.raw = raw;
}
return cooked;
}
;
var __setModuleDefault = Object.create ? (function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o, v) {
o["default"] = v;
};
function __importStar(mod) {
if (mod && mod.__esModule)
return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
function __classPrivateFieldGet(receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
}
function __classPrivateFieldSet(receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
}
var RfxParallaxService = /** @class */ (function () {
function RfxParallaxService(rendererFactory) {
this.rendererFactory = rendererFactory;
this.subjectScroll = new rxjs.BehaviorSubject(undefined);
this.subjectResize = new rxjs.BehaviorSubject(undefined);
this.renderer = this.rendererFactory.createRenderer(null, null);
var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
var ResizeEventService = /** @class */ (function () {
function ResizeEventService() {
this.subjectResize = new rxjs.Subject();
this.resizeEvent = this.onResizeEvent.bind(this);
}
RfxParallaxService.prototype.ngOnDestroy = function () {
var _a;
if (this.elementScrollEvent) {
this.elementScrollEvent();
}
if (this.windowResizeEvent) {
this.windowResizeEvent();
}
(_a = this.elementHeightEvent) === null || _a === void 0 ? void 0 : _a.disconnect();
ResizeEventService.prototype.ngOnDestroy = function () {
this.destroyListener();
};
/**
* Start element scroll event, window resize event and element resize event listeners
* @param scrollElement main element with scroll property
* Create window resize listener.
*/
RfxParallaxService.prototype.initListeners = function (scrollElement) {
var _this = this;
this.elementScrollEvent = this.renderer.listen(scrollElement !== null && scrollElement !== void 0 ? scrollElement : window, 'scroll', function (event) { return _this.onMouseScroll(event); });
this.windowResizeEvent = this.renderer.listen(window, 'resize', function (event) { return _this.onWindowResize(event); });
if (scrollElement) {
this.setElementResizeEvent(scrollElement);
}
ResizeEventService.prototype.createListener = function () {
window.addEventListener('resize', this.resizeEvent, { passive: true });
};
/**
* Observe scrollElement 'scrollHeight' property change
* @param scrollElement main element with scroll property
* Destroy window resize listener.
*/
RfxParallaxService.prototype.setElementResizeEvent = function (scrollElement) {
var e_1, _b;
var _this = this;
this.elementHeightEvent = new ResizeObserver(function () { return _this.onWindowResize({ target: { innerWidth: scrollElement.clientWidth } }); });
var elementChildrenList = Array.from(scrollElement.children);
try {
for (var elementChildrenList_1 = __values(elementChildrenList), elementChildrenList_1_1 = elementChildrenList_1.next(); !elementChildrenList_1_1.done; elementChildrenList_1_1 = elementChildrenList_1.next()) {
var children = elementChildrenList_1_1.value;
this.elementHeightEvent.observe(children);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (elementChildrenList_1_1 && !elementChildrenList_1_1.done && (_b = elementChildrenList_1.return)) _b.call(elementChildrenList_1);
}
finally { if (e_1) throw e_1.error; }
}
ResizeEventService.prototype.destroyListener = function () {
window.removeEventListener('resize', this.resizeEvent);
};
/**
* Mouse scroll event
* Trigger window resize event.
*/
RfxParallaxService.prototype.onMouseScroll = function (event) {
ResizeEventService.prototype.onResizeEvent = function () {
this.subjectResize.next(undefined);
};
/**
* Get window resize event.
* @return {Observable<undefined>} - Window resize event.
*/
ResizeEventService.prototype.getResize = function () {
return this.subjectResize.asObservable();
};
return ResizeEventService;
}());
ResizeEventService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function ResizeEventService_Factory() { return new ResizeEventService(); }, token: ResizeEventService, providedIn: "root" });
ResizeEventService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] }
];
ResizeEventService.ctorParameters = function () { return []; };
var ScrollEventService = /** @class */ (function () {
function ScrollEventService() {
this.subjectScroll = new rxjs.BehaviorSubject(0);
this.mouseScrollEvent = this.onMouseScroll.bind(this);
}
ScrollEventService.prototype.ngOnDestroy = function () {
this.destroyListener();
};
/**
* Create mouse scroll listener.
* @param {HTMLElement} element - Element with scroll event.
*/
ScrollEventService.prototype.createListener = function (element) {
this.element = element;
this.element.addEventListener('scroll', this.mouseScrollEvent, { passive: true });
};
/**
* Destroy mouse scroll listener.
*/
ScrollEventService.prototype.destroyListener = function () {
var _a;
this.subjectScroll.next((_a = event.target.scrollTop) !== null && _a !== void 0 ? _a : event.target.documentElement.scrollTop);
(_a = this.element) === null || _a === void 0 ? void 0 : _a.removeEventListener('scroll', this.mouseScrollEvent);
this.element = undefined;
};
/**
* Mouse scroll event observable
* Trigger mouse scroll event.
* @param {number} event - Mouse scroll event.
*/
RfxParallaxService.prototype.getMouseScroll = function () {
ScrollEventService.prototype.onMouseScroll = function (event) {
var target = event.target instanceof Document ? event.target.documentElement : event.target;
this.subjectScroll.next(target.scrollTop);
};
/**
* Get body scroll event.
* @return {Observable<number>} - Body scroll event.
*/
ScrollEventService.prototype.getMouseScroll = function () {
return this.subjectScroll.asObservable();
};
/**
* Window resize event
* Get body scroll current value.
* @return {number} - Body scroll value.
*/
RfxParallaxService.prototype.onWindowResize = function (event) {
this.subjectResize.next(event.target.innerWidth);
ScrollEventService.prototype.getMouseScrollValue = function () {
return this.subjectScroll.value;
};
return ScrollEventService;
}());
ScrollEventService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function ScrollEventService_Factory() { return new ScrollEventService(); }, token: ScrollEventService, providedIn: "root" });
ScrollEventService.decorators = [
{ type: i0.Injectable, args: [{
providedIn: 'root'
},] }
];
ScrollEventService.ctorParameters = function () { return []; };
var RfxParallaxService = /** @class */ (function () {
function RfxParallaxService(resizeEventService, scrollEventService) {
this.resizeEventService = resizeEventService;
this.scrollEventService = scrollEventService;
}
/**
* Window resize event observable
* Start element scroll event, window resize event and element resize event listeners
* @param element main element with scroll property
*/
RfxParallaxService.prototype.getWindowResize = function () {
return this.subjectResize.asObservable();
RfxParallaxService.prototype.initListeners = function (element) {
if (element === void 0) { element = document; }
this.resizeEventService.createListener();
this.scrollEventService.createListener(element);
};
return RfxParallaxService;
}());
RfxParallaxService.ɵprov = i0.ɵɵdefineInjectable({ factory: function RfxParallaxService_Factory() { return new RfxParallaxService(i0.ɵɵinject(i0.RendererFactory2)); }, token: RfxParallaxService, providedIn: "root" });
RfxParallaxService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function RfxParallaxService_Factory() { return new RfxParallaxService(i0__namespace.ɵɵinject(ResizeEventService), i0__namespace.ɵɵinject(ScrollEventService)); }, token: RfxParallaxService, providedIn: "root" });
RfxParallaxService.decorators = [

@@ -402,10 +151,26 @@ { type: i0.Injectable, args: [{

RfxParallaxService.ctorParameters = function () { return [
{ type: i0.RendererFactory2 }
{ type: ResizeEventService },
{ type: ScrollEventService }
]; };
var RfxParallaxDirective = /** @class */ (function () {
function RfxParallaxDirective(htmlElement, renderer, rfxParallaxService) {
var visibilityAnimation = [
animations.trigger('visibility', [
animations.state('true', animations.style({
opacity: 1
})),
animations.state('false', animations.style({
opacity: 0,
}))
// transition('true <=> false', [
// animate('{{ transitionDurationMs }}ms {{ transitionDelayMs }}ms {{ transitionTimingFunction }}')
// ], { params: { transitionDurationMs: 0, transitionDelayMs: 0, transitionTimingFunction: 'ease' }})
])
];
var RfxParallaxComponent = /** @class */ (function () {
function RfxParallaxComponent(htmlElement, renderer, scrollEventService, resizeEventService) {
this.htmlElement = htmlElement;
this.renderer = renderer;
this.rfxParallaxService = rfxParallaxService;
this.scrollEventService = scrollEventService;
this.resizeEventService = resizeEventService;
this.parallaxPercentage = 40;

@@ -416,167 +181,169 @@ this.positionPercentage = 50;

this.visibleOverflow = false;
this.scrollTop = 0;
this.imageLeft = 0;
this.imageLoaded = false;
this.imageLeftPx = 0;
this.isLoaded = false;
}
RfxParallaxDirective.prototype.ngOnInit = function () {
this.setListeners();
/**
* Set container position and overflow.
* If parallax is not disabled, create listeners.
*/
RfxParallaxComponent.prototype.ngOnInit = function () {
this.setContainerPosition(this.htmlElement.nativeElement);
this.setContainerOverflow(this.htmlElement.nativeElement, this.visibleOverflow);
if (!this.isDisabled) {
this.createListeners();
}
};
RfxParallaxDirective.prototype.ngOnDestroy = function () {
var _a, _b;
(_a = this.onScrollListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
(_b = this.onResizeListener) === null || _b === void 0 ? void 0 : _b.unsubscribe();
};
RfxParallaxDirective.prototype.ngOnChanges = function (changes) {
var _a, _b;
if ((_a = changes === null || changes === void 0 ? void 0 : changes.imageUrl) === null || _a === void 0 ? void 0 : _a.currentValue) {
this.loadImage(changes.imageUrl.currentValue);
/**
* Update parallax values when some properies changed.
* - isDisabled change, enable or disable parallax and refresh image properties.
* - visibleOverflow change, show or hide image overflow on container without refresh.
* - imagerUrl, parallaxPercentage or positionPercentage change, refresh image properties.
* @param {SimpleChanges} changes - SimpleChanges object.
*/
RfxParallaxComponent.prototype.ngOnChanges = function (changes) {
if (this.hasValueChanged(changes.isDisabled, true)) {
this.destroyListeners();
}
if ((_b = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _b === void 0 ? void 0 : _b.currentValue) {
this.onMouseScroll();
else if (this.hasValueChanged(changes.isDisabled, false)) {
this.createListeners();
}
if (this.hasValueChanged(changes.visibleOverflow)) {
this.setContainerOverflow(this.htmlElement.nativeElement, changes.visibleOverflow.currentValue);
}
if (this.image && ((this.hasValueChanged(changes.imageUrl) ||
this.hasValueChanged(changes.parallaxPercentage) ||
this.hasValueChanged(changes.positionPercentage)) ||
this.hasValueChanged(changes.isDisabled))) {
this.setImageProperties(this.image);
}
};
RfxParallaxComponent.prototype.ngOnDestroy = function () {
this.destroyListeners();
};
/**
* Subscribe to scroll and resize listeners
* Check if SimpleChange value has changed.
* Eventually check if value corresponds to a new value.
* @param {SimpleChange} change - SimpleChange object.
* @param {any} newValue - New value.
* @returns {boolean} - true if value has changed.
*/
RfxParallaxDirective.prototype.setListeners = function () {
var _this = this;
this.onScrollListener = this.rfxParallaxService.getMouseScroll().subscribe(function (scroll) { return _this.onMouseScroll(scroll); });
this.onResizeListener = this.rfxParallaxService.getWindowResize().subscribe(function (width) { return _this.onWindowResize(width); });
RfxParallaxComponent.prototype.hasValueChanged = function (change, newValue) {
if (newValue === void 0) { newValue = change === null || change === void 0 ? void 0 : change.currentValue; }
return (change === null || change === void 0 ? void 0 : change.firstChange) === false && (change === null || change === void 0 ? void 0 : change.currentValue) !== undefined && (change === null || change === void 0 ? void 0 : change.currentValue) === newValue;
};
/**
* Set transform property based on the new scroll value
* @param scroll new element scroll value
* Destroy all listeners.
*/
RfxParallaxDirective.prototype.onMouseScroll = function (scroll) {
if (scroll === void 0) { scroll = undefined; }
this.scrollTop = scroll !== null && scroll !== void 0 ? scroll : 0;
if (this.imageLoaded) {
var imageTop = this.getImageTop(this.scrollTop, this.parallaxBoundaries, this.isDisabled);
this.setImageTransform(this.image, this.imageLeft, imageTop);
}
RfxParallaxComponent.prototype.destroyListeners = function () {
var _a, _b;
(_a = this.scrollEventListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
(_b = this.resizeEventListener) === null || _b === void 0 ? void 0 : _b.unsubscribe();
};
/**
* Reset parallax properties according to new window size
* @param width window new width value
* Listen to scroll and resize events.
* Destroy alreay existing listeners.
*/
RfxParallaxDirective.prototype.onWindowResize = function (width) {
if (width !== undefined && this.imageLoaded) {
var imagePosition = this.setParallaxPosition(this.htmlElement.nativeElement, this.image);
this.imageLeft = imagePosition.left;
this.setImageTransform(this.image, imagePosition.left, imagePosition.top);
}
RfxParallaxComponent.prototype.createListeners = function () {
var _this = this;
this.destroyListeners();
this.scrollEventListener = this.scrollEventService.getMouseScroll().subscribe(function (scroll) { return _this.onMouseScroll(scroll); });
this.resizeEventListener = this.resizeEventService.getResize().subscribe(function () { return _this.onResize(); });
};
/**
* Load parallax image from imageUrl
* @param imageUrl image url
* On mouse scroll event recalculate and change
* parallaxed image position.
* @param {number} scroll - Scroll value.
*/
RfxParallaxDirective.prototype.loadImage = function (imageUrl) {
var _this = this;
this.image = new Image();
this.image.src = imageUrl;
this.image.setAttribute('class', 'parallax-image');
this.renderer.setStyle(this.image, 'visibility', 'hidden');
this.removePreviousImages(this.htmlElement.nativeElement);
this.htmlElement.nativeElement.appendChild(this.image);
this.setStaticProperties(this.htmlElement.nativeElement, this.image);
this.image.onload = function () {
var imagePosition = _this.setParallaxPosition(_this.htmlElement.nativeElement, _this.image);
_this.setImageTransform(_this.image, imagePosition.left, imagePosition.top);
_this.renderer.setStyle(_this.image, 'visibility', 'visible');
_this.imageLeft = imagePosition.left;
_this.imageLoaded = true;
};
RfxParallaxComponent.prototype.onMouseScroll = function (scroll) {
if (this.parallaxBoundaries && this.image) {
var topPx = this.getImageTop(scroll, this.parallaxBoundaries);
this.setImageTransform(this.image, this.imageLeftPx, topPx);
}
};
/**
* Remove other / old parallax images
* @param container main container HTMLElement
* On window resize event reload parallax properties.
*/
RfxParallaxDirective.prototype.removePreviousImages = function (container) {
var e_1, _c;
var images = Array.from(container.getElementsByClassName('parallax-image'));
try {
for (var images_1 = __values(images), images_1_1 = images_1.next(); !images_1_1.done; images_1_1 = images_1.next()) {
var element = images_1_1.value;
if (element.classList.contains('parallax-image')) {
this.renderer.removeChild(container, element);
}
}
RfxParallaxComponent.prototype.onResize = function () {
if (this.image) {
this.setImageProperties(this.image);
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (images_1_1 && !images_1_1.done && (_c = images_1.return)) _c.call(images_1);
}
finally { if (e_1) throw e_1.error; }
}
};
/**
* Set default image size and return new parallax position
* @param container main container HTMLElement
* @param image main image HTMLElement
* Set image properties after image is fully loaded.
* @param {Event} event - Image loaded event.
*/
RfxParallaxDirective.prototype.setParallaxPosition = function (container, image) {
this.setImageSize(container.clientWidth, container.clientHeight, image, this.parallaxPercentage, this.isDisabled);
var elementTop = container.getBoundingClientRect().top + this.scrollTop;
this.parallaxBoundaries = this.getParallaxBoundaries(elementTop, container.clientHeight, this.image.height, this.parallaxPercentage);
var left = this.getImageLeft(container.clientWidth, image.width, this.positionPercentage);
var top = this.getImageTop(this.scrollTop, this.parallaxBoundaries, this.isDisabled);
return { left: left, top: top };
RfxParallaxComponent.prototype.onImageLoaded = function (event) {
this.image = event.target;
this.setImageProperties(this.image);
this.isLoaded = true;
};
/**
* Set default properties for container and image
* @param container main container HTMLElement
* @param image main image HTMLElement
* Set image properties needed for parallax effect.
* @param {HTMLImageElement} image - Image to be parallaxed.
*/
RfxParallaxDirective.prototype.setStaticProperties = function (container, image) {
if (!this.isAlreadyPositioned(container)) {
RfxParallaxComponent.prototype.setImageProperties = function (image) {
var scrollTop = this.scrollEventService.getMouseScrollValue();
this.setImageSize(image, this.htmlElement.nativeElement.clientWidth, this.htmlElement.nativeElement.clientHeight, this.parallaxPercentage, this.isDisabled);
this.parallaxBoundaries = this.getParallaxBoundaries(scrollTop, this.htmlElement.nativeElement, image.height, this.parallaxPercentage);
this.imageLeftPx = this.getImageLeft(this.htmlElement.nativeElement.clientWidth, image.width, this.positionPercentage);
var topPx = this.isDisabled ?
this.getDisabledImageTop(this.parallaxBoundaries) :
this.getImageTop(scrollTop, this.parallaxBoundaries);
this.setImageTransform(image, this.imageLeftPx, topPx);
};
/**
* Set container position to relative
* if image is not already in relative or absolute position.
* @param {HTMLElement} container
*/
RfxParallaxComponent.prototype.setContainerPosition = function (container) {
if (container.style.position !== 'relative' && container.style.position !== 'absolute') {
this.renderer.setStyle(container, 'position', 'relative');
}
this.renderer.setStyle(container, 'overflow', this.visibleOverflow ? 'visible' : 'hidden');
this.renderer.setStyle(image, 'z-index', this.imageZIndex);
this.renderer.setStyle(image, 'position', 'absolute');
this.renderer.setStyle(image, 'left', '0');
this.renderer.setStyle(image, 'top', '0');
};
/**
* Check if element has position absolute or relative
* @param element html element
* Set container overflow.
* @param {HTMLElement} container - Container element.
* @param {boolean} isOverflowVisible - true to show container overflow.
*/
RfxParallaxDirective.prototype.isAlreadyPositioned = function (element) {
return ['absolute', 'relative'].includes(window.getComputedStyle(element).position);
RfxParallaxComponent.prototype.setContainerOverflow = function (container, isOverflowVisible) {
this.renderer.setStyle(container, 'overflow', isOverflowVisible ? 'visible' : 'hidden');
};
/**
* Set default image size that match properties
* @param containerWidth main container HTMLElement width
* @param containerHeight main container HTMLElement height
* @param image main image HTMLElement
* @param parallaxPercentage parallax scroll percentage
* @param isDisabled parallax is disabled
* Set image size based on container size,
* parallax percentage and disabled state.
* @param {HTMLImageElement} image - Image element.
* @param {number} containerWidth - Container width.
* @param {number} containerHeight - Container height.
* @param {number} parallaxPercentage - Parallax percentage.
* @param {boolean} isDisabled - true to disable parallax effect.
*/
RfxParallaxDirective.prototype.setImageSize = function (containerWidth, containerHeight, image, parallaxPercentage, isDisabled) {
var minHeight = (containerHeight * (100 + (isDisabled ? 0 : parallaxPercentage))) / 100;
RfxParallaxComponent.prototype.setImageSize = function (image, containerWidth, containerHeight, parallaxPercentage, isDisabled) {
var minimumHeight = (containerHeight * (100 + (isDisabled ? 0 : parallaxPercentage))) / 100;
var ratio = image.naturalHeight / image.naturalWidth;
var minRatio = minHeight / containerWidth;
if (ratio > minRatio) {
this.image.setAttribute('width', containerWidth + "px");
this.image.setAttribute('height', "auto");
var minimumRatio = minimumHeight / containerWidth;
if (ratio > minimumRatio) {
this.renderer.setAttribute(image, 'width', containerWidth + "px");
this.renderer.setAttribute(image, 'height', "auto");
}
else {
this.image.setAttribute('height', minHeight + "px");
this.image.setAttribute('width', "auto");
this.renderer.setAttribute(image, 'width', "auto");
this.renderer.setAttribute(image, 'height', minimumHeight + "px");
}
};
/**
* Get parallax scrolling visible area.
* Use this when container overflow is hidden for better page performance
* @param elementTop main container position from the top of the document in pixels
* @param elementHeight main container height in pixels
* @param imageHeight parallax image height in pixels
* @param parallaxPercentage parallax scroll percentage
* Get parallax boundaries. This data is used
* to calculate parallax movement.
* @param {number} scrollTop - Scroll top.
* @param {HTMLElement} container - Container element.
* @param {number} imageHeight - Image height.
* @param {number} parallaxPercentage - Parallax percentage.
* @return {ParallaxBoundariesModel} - Parallax boundaries.
*/
RfxParallaxDirective.prototype.getParallaxBoundaries = function (elementTop, elementHeight, imageHeight, parallaxPercentage) {
var usablePixels = elementHeight / 100 * parallaxPercentage;
var unusablePixels = imageHeight - elementHeight - usablePixels;
RfxParallaxComponent.prototype.getParallaxBoundaries = function (scrollTop, container, imageHeight, parallaxPercentage) {
var elementTop = container.getBoundingClientRect().top + scrollTop;
var usablePixels = container.clientHeight / 100 * parallaxPercentage;
var unusablePixels = imageHeight - container.clientHeight - usablePixels;
var startPoint = elementTop - usablePixels - window.innerHeight;
var endPoint = elementTop + elementHeight + usablePixels;
var endPoint = elementTop + container.clientHeight + usablePixels;
var totalPixels = endPoint - startPoint;

@@ -586,49 +353,64 @@ return { startPoint: startPoint, endPoint: endPoint, totalPixels: totalPixels, usablePixels: usablePixels, unusablePixels: unusablePixels };

/**
* Set image transform property
* @param image image HTMLImageElement element
* @param imageLeft image left shift in pixels
* @param imageTop image top shift in pixels
* Get image left position.
* @param {number} containerWidth - Container width.
* @param {number} imageWidth - Image width.
* @param {number} positionPercentage - Position percentage.
* @return {number} - Image left position.
*/
RfxParallaxDirective.prototype.setImageTransform = function (image, imageLeft, imageTop) {
this.renderer.setStyle(image, 'transform', "translate3d(" + imageLeft + "px, " + imageTop + "px, 0)");
};
/**
* Get image left property based on positionPercentage in pixels
* @param containerWidth main container width in pixels
* @param imageWidth image width in pixels
* @param positionPercentage image position percentage
*/
RfxParallaxDirective.prototype.getImageLeft = function (containerWidth, imageWidth, positionPercentage) {
RfxParallaxComponent.prototype.getImageLeft = function (containerWidth, imageWidth, positionPercentage) {
return (containerWidth - imageWidth) / 100 * positionPercentage;
};
/**
* Get image top shift in pixels
* @param scrollTop pixels from the top of the page to the current view
* @param boundaries parallax position points inside the page
* @param isDisabled parallax is disabled
* Get image top position.
* @param {number} scrollTop - Scroll top.
* @param {ParallaxBoundariesModel} boundaries - Parallax boundaries.
* @return {number} - Image top position.
*/
RfxParallaxDirective.prototype.getImageTop = function (scrollTop, boundaries, isDisabled) {
RfxParallaxComponent.prototype.getImageTop = function (scrollTop, boundaries) {
var area = Math.max(0, Math.min(scrollTop - boundaries.startPoint, boundaries.totalPixels));
var areaPercentage = 100 / boundaries.totalPixels * area;
if (isDisabled) {
return (-boundaries.usablePixels - boundaries.unusablePixels) / 2;
}
return -boundaries.usablePixels * (1 - areaPercentage / 100) - boundaries.unusablePixels / 2;
};
return RfxParallaxDirective;
/**
* Get disabled image top position.
* @param {number} boundaries - Parallax boundaries.
* @return {number} - Image top position.
*/
RfxParallaxComponent.prototype.getDisabledImageTop = function (boundaries) {
return (-boundaries.usablePixels - boundaries.unusablePixels) / 2;
};
/**
* Set image transform properties.
* @param {HTMLImageElement} image - Image element.
* @param {number} leftPx - Image left position.
* @param {number} topPx - Image top position.
*/
RfxParallaxComponent.prototype.setImageTransform = function (image, leftPx, topPx) {
var newTranslate = "translate(" + leftPx.toFixed(1) + "px, " + topPx.toFixed(1) + "px)";
if (image.style.transform !== newTranslate) {
this.renderer.setStyle(image, 'transform', newTranslate);
}
};
return RfxParallaxComponent;
}());
RfxParallaxDirective.decorators = [
{ type: i0.Directive, args: [{
selector: '[libRfxParallax]'
RfxParallaxComponent.decorators = [
{ type: i0.Component, args: [{
selector: '[libRfxParallax]',
template: "<img\r\n [@visibility]=\"isLoaded\"\r\n libWillChange\r\n [isDisabled]=\"isDisabled\"\r\n class=\"rfx-image\"\r\n [src]=\"imageUrl\"\r\n [style.zIndex]=\"imageZIndex\"\r\n (load)=\"onImageLoaded($event)\" />\r\n\r\n<ng-content></ng-content>\r\n",
animations: [
visibilityAnimation
],
styles: [".rfx-image{position:absolute;left:0;top:0;will-change:transform;opacity:0}\n"]
},] }
];
RfxParallaxDirective.ctorParameters = function () { return [
RfxParallaxComponent.ctorParameters = function () { return [
{ type: i0.ElementRef },
{ type: i0.Renderer2 },
{ type: RfxParallaxService }
{ type: ScrollEventService },
{ type: ResizeEventService }
]; };
RfxParallaxDirective.propDecorators = {
RfxParallaxComponent.propDecorators = {
imageUrl: [{ type: i0.Input }],
parallaxPercentage: [{ type: i0.Input }],
positionPercentage: [{ type: i0.Input }],
imageUrl: [{ type: i0.Input }],
imageZIndex: [{ type: i0.Input }],

@@ -639,2 +421,106 @@ visibleOverflow: [{ type: i0.Input }],

var WillChangeDirective = /** @class */ (function () {
function WillChangeDirective(htmlElement, renderer, scrollEventService) {
this.htmlElement = htmlElement;
this.renderer = renderer;
this.scrollEventService = scrollEventService;
this.triggerArea = window.innerHeight / 4 * 6;
this.isDisabled = false;
this.willChange = true;
}
WillChangeDirective.prototype.ngOnInit = function () {
this.willChangeArea = this.getWillChangeArea();
if (!this.isDisabled) {
this.createListener();
}
};
WillChangeDirective.prototype.ngOnDestroy = function () {
this.destroyListener();
};
/**
* Create listener for scroll event.
*/
WillChangeDirective.prototype.createListener = function () {
var _this = this;
this.scrollEventListener = this.scrollEventService.getMouseScroll().subscribe(function (scroll) { return _this.checkWillChange(scroll); });
};
/**
* Destroy scroll event listener.
*/
WillChangeDirective.prototype.destroyListener = function () {
var _a;
(_a = this.scrollEventListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
};
/**
* Refresh will-change area if some properties changed.
* @param {SimpleChanges} changes - Changes.
*/
WillChangeDirective.prototype.ngOnChanges = function (changes) {
var _a, _b, _c, _d;
if ((((_a = changes === null || changes === void 0 ? void 0 : changes.triggerArea) === null || _a === void 0 ? void 0 : _a.currentValue) !== undefined && !((_b = changes === null || changes === void 0 ? void 0 : changes.triggerArea) === null || _b === void 0 ? void 0 : _b.firstChange)) ||
((((_c = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _c === void 0 ? void 0 : _c.currentValue) !== undefined && !((_d = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _d === void 0 ? void 0 : _d.firstChange)))) {
var scroll = this.scrollEventService.getMouseScrollValue();
this.willChangeArea = this.getWillChangeArea();
this.checkWillChange(scroll);
}
};
/**
* Check will-change property and
* update if needed.
* @param {number} scroll - Scroll position.
*/
WillChangeDirective.prototype.checkWillChange = function (scroll) {
if (this.willChangeArea) {
var isElementInArea = this.isElementInArea(scroll, this.willChangeArea);
if (isElementInArea !== this.willChange) {
this.setWillChange(isElementInArea);
}
}
};
/**
* Check if element is in will-change area.
* @param {number} scroll - Scroll position.
* @param {SectionAreaModel} willChangeArea - Will-change area.
* @returns {boolean} - Is element in will-change area.
*/
WillChangeDirective.prototype.isElementInArea = function (scroll, willChangeArea) {
return scroll >= willChangeArea.top && scroll <= willChangeArea.bottom;
};
/**
* Calculate area where element is probably going to be animated soon.
* @returns {number} - Will-change area.
*/
WillChangeDirective.prototype.getWillChangeArea = function () {
var elementRect = this.htmlElement.nativeElement.getBoundingClientRect();
var scroll = this.scrollEventService.getMouseScrollValue();
var elementTop = elementRect.top + scroll;
var areaTop = elementTop - this.triggerArea;
var areaBottom = elementTop + this.triggerArea;
return { top: areaTop, bottom: areaBottom };
};
/**
* Set element will-change property.
* @param {boolean} willChange - will-change enabled or disabled.
*/
WillChangeDirective.prototype.setWillChange = function (willChange) {
this.willChange = willChange;
this.renderer.setStyle(this.htmlElement.nativeElement, 'will-change', willChange ? 'transform' : 'auto');
};
return WillChangeDirective;
}());
WillChangeDirective.decorators = [
{ type: i0.Directive, args: [{
selector: '[libWillChange]'
},] }
];
WillChangeDirective.ctorParameters = function () { return [
{ type: i0.ElementRef },
{ type: i0.Renderer2 },
{ type: ScrollEventService }
]; };
WillChangeDirective.propDecorators = {
triggerArea: [{ type: i0.Input }],
isDisabled: [{ type: i0.Input }]
};
var RfxParallaxModule = /** @class */ (function () {

@@ -648,7 +534,8 @@ function RfxParallaxModule() {

declarations: [
RfxParallaxDirective
RfxParallaxComponent,
WillChangeDirective
],
imports: [],
exports: [
RfxParallaxDirective
RfxParallaxComponent
]

@@ -666,5 +553,11 @@ },] }

exports.RfxParallaxComponent = RfxParallaxComponent;
exports.RfxParallaxModule = RfxParallaxModule;
exports.RfxParallaxService = RfxParallaxService;
exports.ɵa = RfxParallaxDirective;
exports.ɵa = ResizeEventService;
exports.ɵb = ScrollEventService;
exports.ɵc = visibilityAnimation;
exports.ɵd = ScrollEventService;
exports.ɵe = ResizeEventService;
exports.ɵf = WillChangeDirective;

@@ -671,0 +564,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

import { NgModule } from '@angular/core';
import { RfxParallaxDirective } from './rfx-parallax.directive';
import { RfxParallaxComponent } from './components/rfx-parallax/rfx-parallax.component';
import { WillChangeDirective } from './directives/will-change.directive';
export class RfxParallaxModule {

@@ -8,10 +9,11 @@ }

declarations: [
RfxParallaxDirective
RfxParallaxComponent,
WillChangeDirective
],
imports: [],
exports: [
RfxParallaxDirective
RfxParallaxComponent
]
},] }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmZ4LXBhcmFsbGF4Lm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3JmeC1wYXJhbGxheC9zcmMvbGliL3JmeC1wYXJhbGxheC5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQVdoRSxNQUFNLE9BQU8saUJBQWlCOzs7WUFUN0IsUUFBUSxTQUFDO2dCQUNSLFlBQVksRUFBRTtvQkFDWixvQkFBb0I7aUJBQ3JCO2dCQUNELE9BQU8sRUFBRSxFQUFFO2dCQUNYLE9BQU8sRUFBRTtvQkFDUCxvQkFBb0I7aUJBQ3JCO2FBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBSZnhQYXJhbGxheERpcmVjdGl2ZSB9IGZyb20gJy4vcmZ4LXBhcmFsbGF4LmRpcmVjdGl2ZSc7XHJcblxyXG5ATmdNb2R1bGUoe1xyXG4gIGRlY2xhcmF0aW9uczogW1xyXG4gICAgUmZ4UGFyYWxsYXhEaXJlY3RpdmVcclxuICBdLFxyXG4gIGltcG9ydHM6IFtdLFxyXG4gIGV4cG9ydHM6IFtcclxuICAgIFJmeFBhcmFsbGF4RGlyZWN0aXZlXHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUmZ4UGFyYWxsYXhNb2R1bGUgeyB9XHJcbiJdfQ==
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmZ4LXBhcmFsbGF4Lm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3JmeC1wYXJhbGxheC9zcmMvbGliL3JmeC1wYXJhbGxheC5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrREFBa0QsQ0FBQztBQUN4RixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQVl6RSxNQUFNLE9BQU8saUJBQWlCOzs7WUFWN0IsUUFBUSxTQUFDO2dCQUNSLFlBQVksRUFBRTtvQkFDWixvQkFBb0I7b0JBQ3BCLG1CQUFtQjtpQkFDcEI7Z0JBQ0QsT0FBTyxFQUFFLEVBQUU7Z0JBQ1gsT0FBTyxFQUFFO29CQUNQLG9CQUFvQjtpQkFDckI7YUFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFJmeFBhcmFsbGF4Q29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL3JmeC1wYXJhbGxheC9yZngtcGFyYWxsYXguY29tcG9uZW50JztcclxuaW1wb3J0IHsgV2lsbENoYW5nZURpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy93aWxsLWNoYW5nZS5kaXJlY3RpdmUnO1xyXG5cclxuQE5nTW9kdWxlKHtcclxuICBkZWNsYXJhdGlvbnM6IFtcclxuICAgIFJmeFBhcmFsbGF4Q29tcG9uZW50LFxyXG4gICAgV2lsbENoYW5nZURpcmVjdGl2ZVxyXG4gIF0sXHJcbiAgaW1wb3J0czogW10sXHJcbiAgZXhwb3J0czogW1xyXG4gICAgUmZ4UGFyYWxsYXhDb21wb25lbnRcclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBSZnhQYXJhbGxheE1vZHVsZSB7IH1cclxuIl19
/*
* Public API Surface of rfx-parallax
*/
export * from './lib/rfx-parallax.service';
export * from './lib/services/rfx-parallax.service';
export * from './lib/components/rfx-parallax/rfx-parallax.component';
export * from './lib/rfx-parallax.module';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3JmeC1wYXJhbGxheC9zcmMvcHVibGljLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYywyQkFBMkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiByZngtcGFyYWxsYXhcclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9yZngtcGFyYWxsYXguc2VydmljZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3JmeC1wYXJhbGxheC5tb2R1bGUnO1xyXG4iXX0=
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3JmeC1wYXJhbGxheC9zcmMvcHVibGljLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMscUNBQXFDLENBQUM7QUFDcEQsY0FBYyxzREFBc0QsQ0FBQztBQUNyRSxjQUFjLDJCQUEyQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIHJmeC1wYXJhbGxheFxyXG4gKi9cclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3NlcnZpY2VzL3JmeC1wYXJhbGxheC5zZXJ2aWNlJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy9yZngtcGFyYWxsYXgvcmZ4LXBhcmFsbGF4LmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3JmeC1wYXJhbGxheC5tb2R1bGUnO1xyXG4iXX0=

@@ -5,3 +5,7 @@ /**

export * from './public-api';
export { RfxParallaxDirective as ɵa } from './lib/rfx-parallax.directive';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmZ4LXBhcmFsbGF4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvcmZ4LXBhcmFsbGF4L3NyYy9yZngtcGFyYWxsYXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQztBQUU3QixPQUFPLEVBQUMsb0JBQW9CLElBQUksRUFBRSxFQUFDLE1BQU0sOEJBQThCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLWFwaSc7XG5cbmV4cG9ydCB7UmZ4UGFyYWxsYXhEaXJlY3RpdmUgYXMgybVhfSBmcm9tICcuL2xpYi9yZngtcGFyYWxsYXguZGlyZWN0aXZlJzsiXX0=
export { visibilityAnimation as ɵc } from './lib/animations';
export { WillChangeDirective as ɵf } from './lib/directives/will-change.directive';
export { ResizeEventService as ɵe, ScrollEventService as ɵd } from './lib/services';
export { ResizeEventService as ɵa } from './lib/services/resize-event.service';
export { ScrollEventService as ɵb } from './lib/services/scroll-event.service';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmZ4LXBhcmFsbGF4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvcmZ4LXBhcmFsbGF4L3NyYy9yZngtcGFyYWxsYXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQztBQUU3QixPQUFPLEVBQUMsbUJBQW1CLElBQUksRUFBRSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDM0QsT0FBTyxFQUFDLG1CQUFtQixJQUFJLEVBQUUsRUFBQyxNQUFNLHdDQUF3QyxDQUFDO0FBQ2pGLE9BQU8sRUFBQyxrQkFBa0IsSUFBSSxFQUFFLEVBQUMsa0JBQWtCLElBQUksRUFBRSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDakYsT0FBTyxFQUFDLGtCQUFrQixJQUFJLEVBQUUsRUFBQyxNQUFNLHFDQUFxQyxDQUFDO0FBQzdFLE9BQU8sRUFBQyxrQkFBa0IsSUFBSSxFQUFFLEVBQUMsTUFBTSxxQ0FBcUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcblxuZXhwb3J0IHt2aXNpYmlsaXR5QW5pbWF0aW9uIGFzIMm1Y30gZnJvbSAnLi9saWIvYW5pbWF0aW9ucyc7XG5leHBvcnQge1dpbGxDaGFuZ2VEaXJlY3RpdmUgYXMgybVmfSBmcm9tICcuL2xpYi9kaXJlY3RpdmVzL3dpbGwtY2hhbmdlLmRpcmVjdGl2ZSc7XG5leHBvcnQge1Jlc2l6ZUV2ZW50U2VydmljZSBhcyDJtWUsU2Nyb2xsRXZlbnRTZXJ2aWNlIGFzIMm1ZH0gZnJvbSAnLi9saWIvc2VydmljZXMnO1xuZXhwb3J0IHtSZXNpemVFdmVudFNlcnZpY2UgYXMgybVhfSBmcm9tICcuL2xpYi9zZXJ2aWNlcy9yZXNpemUtZXZlbnQuc2VydmljZSc7XG5leHBvcnQge1Njcm9sbEV2ZW50U2VydmljZSBhcyDJtWJ9IGZyb20gJy4vbGliL3NlcnZpY2VzL3Njcm9sbC1ldmVudC5zZXJ2aWNlJzsiXX0=

@@ -1,53 +0,84 @@

import { ɵɵdefineInjectable, ɵɵinject, RendererFactory2, Injectable, Directive, ElementRef, Renderer2, Input, NgModule } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import * as i0 from '@angular/core';
import { Injectable, Component, ElementRef, Renderer2, Input, Directive, NgModule } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs';
import { trigger, state, style } from '@angular/animations';
class RfxParallaxService {
constructor(rendererFactory) {
this.rendererFactory = rendererFactory;
this.subjectScroll = new BehaviorSubject(undefined);
this.subjectResize = new BehaviorSubject(undefined);
this.renderer = this.rendererFactory.createRenderer(null, null);
class ResizeEventService {
constructor() {
this.subjectResize = new Subject();
this.resizeEvent = this.onResizeEvent.bind(this);
}
ngOnDestroy() {
var _a;
if (this.elementScrollEvent) {
this.elementScrollEvent();
}
if (this.windowResizeEvent) {
this.windowResizeEvent();
}
(_a = this.elementHeightEvent) === null || _a === void 0 ? void 0 : _a.disconnect();
this.destroyListener();
}
/**
* Start element scroll event, window resize event and element resize event listeners
* @param scrollElement main element with scroll property
* Create window resize listener.
*/
initListeners(scrollElement) {
this.elementScrollEvent = this.renderer.listen(scrollElement !== null && scrollElement !== void 0 ? scrollElement : window, 'scroll', (event) => this.onMouseScroll(event));
this.windowResizeEvent = this.renderer.listen(window, 'resize', (event) => this.onWindowResize(event));
if (scrollElement) {
this.setElementResizeEvent(scrollElement);
}
createListener() {
window.addEventListener('resize', this.resizeEvent, { passive: true });
}
/**
* Observe scrollElement 'scrollHeight' property change
* @param scrollElement main element with scroll property
* Destroy window resize listener.
*/
setElementResizeEvent(scrollElement) {
this.elementHeightEvent = new ResizeObserver(() => this.onWindowResize({ target: { innerWidth: scrollElement.clientWidth } }));
const elementChildrenList = Array.from(scrollElement.children);
for (const children of elementChildrenList) {
this.elementHeightEvent.observe(children);
}
destroyListener() {
window.removeEventListener('resize', this.resizeEvent);
}
/**
* Mouse scroll event
* Trigger window resize event.
*/
onMouseScroll(event) {
onResizeEvent() {
this.subjectResize.next(undefined);
}
/**
* Get window resize event.
* @return {Observable<undefined>} - Window resize event.
*/
getResize() {
return this.subjectResize.asObservable();
}
}
ResizeEventService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ResizeEventService_Factory() { return new ResizeEventService(); }, token: ResizeEventService, providedIn: "root" });
ResizeEventService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
ResizeEventService.ctorParameters = () => [];
class ScrollEventService {
constructor() {
this.subjectScroll = new BehaviorSubject(0);
this.mouseScrollEvent = this.onMouseScroll.bind(this);
}
ngOnDestroy() {
this.destroyListener();
}
/**
* Create mouse scroll listener.
* @param {HTMLElement} element - Element with scroll event.
*/
createListener(element) {
this.element = element;
this.element.addEventListener('scroll', this.mouseScrollEvent, { passive: true });
}
/**
* Destroy mouse scroll listener.
*/
destroyListener() {
var _a;
this.subjectScroll.next((_a = event.target.scrollTop) !== null && _a !== void 0 ? _a : event.target.documentElement.scrollTop);
(_a = this.element) === null || _a === void 0 ? void 0 : _a.removeEventListener('scroll', this.mouseScrollEvent);
this.element = undefined;
}
/**
* Mouse scroll event observable
* Trigger mouse scroll event.
* @param {number} event - Mouse scroll event.
*/
onMouseScroll(event) {
const target = event.target instanceof Document ? event.target.documentElement : event.target;
this.subjectScroll.next(target.scrollTop);
}
/**
* Get body scroll event.
* @return {Observable<number>} - Body scroll event.
*/
getMouseScroll() {

@@ -57,15 +88,32 @@ return this.subjectScroll.asObservable();

/**
* Window resize event
* Get body scroll current value.
* @return {number} - Body scroll value.
*/
onWindowResize(event) {
this.subjectResize.next(event.target.innerWidth);
getMouseScrollValue() {
return this.subjectScroll.value;
}
}
ScrollEventService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ScrollEventService_Factory() { return new ScrollEventService(); }, token: ScrollEventService, providedIn: "root" });
ScrollEventService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
ScrollEventService.ctorParameters = () => [];
class RfxParallaxService {
constructor(resizeEventService, scrollEventService) {
this.resizeEventService = resizeEventService;
this.scrollEventService = scrollEventService;
}
/**
* Window resize event observable
* Start element scroll event, window resize event and element resize event listeners
* @param element main element with scroll property
*/
getWindowResize() {
return this.subjectResize.asObservable();
initListeners(element = document) {
this.resizeEventService.createListener();
this.scrollEventService.createListener(element);
}
}
RfxParallaxService.ɵprov = ɵɵdefineInjectable({ factory: function RfxParallaxService_Factory() { return new RfxParallaxService(ɵɵinject(RendererFactory2)); }, token: RfxParallaxService, providedIn: "root" });
RfxParallaxService.ɵprov = i0.ɵɵdefineInjectable({ factory: function RfxParallaxService_Factory() { return new RfxParallaxService(i0.ɵɵinject(ResizeEventService), i0.ɵɵinject(ScrollEventService)); }, token: RfxParallaxService, providedIn: "root" });
RfxParallaxService.decorators = [

@@ -77,10 +125,26 @@ { type: Injectable, args: [{

RfxParallaxService.ctorParameters = () => [
{ type: RendererFactory2 }
{ type: ResizeEventService },
{ type: ScrollEventService }
];
class RfxParallaxDirective {
constructor(htmlElement, renderer, rfxParallaxService) {
const visibilityAnimation = [
trigger('visibility', [
state('true', style({
opacity: 1
})),
state('false', style({
opacity: 0,
}))
// transition('true <=> false', [
// animate('{{ transitionDurationMs }}ms {{ transitionDelayMs }}ms {{ transitionTimingFunction }}')
// ], { params: { transitionDurationMs: 0, transitionDelayMs: 0, transitionTimingFunction: 'ease' }})
])
];
class RfxParallaxComponent {
constructor(htmlElement, renderer, scrollEventService, resizeEventService) {
this.htmlElement = htmlElement;
this.renderer = renderer;
this.rfxParallaxService = rfxParallaxService;
this.scrollEventService = scrollEventService;
this.resizeEventService = resizeEventService;
this.parallaxPercentage = 40;

@@ -91,153 +155,167 @@ this.positionPercentage = 50;

this.visibleOverflow = false;
this.scrollTop = 0;
this.imageLeft = 0;
this.imageLoaded = false;
this.imageLeftPx = 0;
this.isLoaded = false;
}
/**
* Set container position and overflow.
* If parallax is not disabled, create listeners.
*/
ngOnInit() {
this.setListeners();
this.setContainerPosition(this.htmlElement.nativeElement);
this.setContainerOverflow(this.htmlElement.nativeElement, this.visibleOverflow);
if (!this.isDisabled) {
this.createListeners();
}
}
ngOnDestroy() {
var _a, _b;
(_a = this.onScrollListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
(_b = this.onResizeListener) === null || _b === void 0 ? void 0 : _b.unsubscribe();
}
/**
* Update parallax values when some properies changed.
* - isDisabled change, enable or disable parallax and refresh image properties.
* - visibleOverflow change, show or hide image overflow on container without refresh.
* - imagerUrl, parallaxPercentage or positionPercentage change, refresh image properties.
* @param {SimpleChanges} changes - SimpleChanges object.
*/
ngOnChanges(changes) {
var _a, _b;
if ((_a = changes === null || changes === void 0 ? void 0 : changes.imageUrl) === null || _a === void 0 ? void 0 : _a.currentValue) {
this.loadImage(changes.imageUrl.currentValue);
if (this.hasValueChanged(changes.isDisabled, true)) {
this.destroyListeners();
}
if ((_b = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _b === void 0 ? void 0 : _b.currentValue) {
this.onMouseScroll();
else if (this.hasValueChanged(changes.isDisabled, false)) {
this.createListeners();
}
if (this.hasValueChanged(changes.visibleOverflow)) {
this.setContainerOverflow(this.htmlElement.nativeElement, changes.visibleOverflow.currentValue);
}
if (this.image && ((this.hasValueChanged(changes.imageUrl) ||
this.hasValueChanged(changes.parallaxPercentage) ||
this.hasValueChanged(changes.positionPercentage)) ||
this.hasValueChanged(changes.isDisabled))) {
this.setImageProperties(this.image);
}
}
ngOnDestroy() {
this.destroyListeners();
}
/**
* Subscribe to scroll and resize listeners
* Check if SimpleChange value has changed.
* Eventually check if value corresponds to a new value.
* @param {SimpleChange} change - SimpleChange object.
* @param {any} newValue - New value.
* @returns {boolean} - true if value has changed.
*/
setListeners() {
this.onScrollListener = this.rfxParallaxService.getMouseScroll().subscribe((scroll) => this.onMouseScroll(scroll));
this.onResizeListener = this.rfxParallaxService.getWindowResize().subscribe((width) => this.onWindowResize(width));
hasValueChanged(change, newValue = change === null || change === void 0 ? void 0 : change.currentValue) {
return (change === null || change === void 0 ? void 0 : change.firstChange) === false && (change === null || change === void 0 ? void 0 : change.currentValue) !== undefined && (change === null || change === void 0 ? void 0 : change.currentValue) === newValue;
}
/**
* Set transform property based on the new scroll value
* @param scroll new element scroll value
* Destroy all listeners.
*/
onMouseScroll(scroll = undefined) {
this.scrollTop = scroll !== null && scroll !== void 0 ? scroll : 0;
if (this.imageLoaded) {
const imageTop = this.getImageTop(this.scrollTop, this.parallaxBoundaries, this.isDisabled);
this.setImageTransform(this.image, this.imageLeft, imageTop);
}
destroyListeners() {
var _a, _b;
(_a = this.scrollEventListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
(_b = this.resizeEventListener) === null || _b === void 0 ? void 0 : _b.unsubscribe();
}
/**
* Reset parallax properties according to new window size
* @param width window new width value
* Listen to scroll and resize events.
* Destroy alreay existing listeners.
*/
onWindowResize(width) {
if (width !== undefined && this.imageLoaded) {
const imagePosition = this.setParallaxPosition(this.htmlElement.nativeElement, this.image);
this.imageLeft = imagePosition.left;
this.setImageTransform(this.image, imagePosition.left, imagePosition.top);
}
createListeners() {
this.destroyListeners();
this.scrollEventListener = this.scrollEventService.getMouseScroll().subscribe((scroll) => this.onMouseScroll(scroll));
this.resizeEventListener = this.resizeEventService.getResize().subscribe(() => this.onResize());
}
/**
* Load parallax image from imageUrl
* @param imageUrl image url
* On mouse scroll event recalculate and change
* parallaxed image position.
* @param {number} scroll - Scroll value.
*/
loadImage(imageUrl) {
this.image = new Image();
this.image.src = imageUrl;
this.image.setAttribute('class', 'parallax-image');
this.renderer.setStyle(this.image, 'visibility', 'hidden');
this.removePreviousImages(this.htmlElement.nativeElement);
this.htmlElement.nativeElement.appendChild(this.image);
this.setStaticProperties(this.htmlElement.nativeElement, this.image);
this.image.onload = () => {
const imagePosition = this.setParallaxPosition(this.htmlElement.nativeElement, this.image);
this.setImageTransform(this.image, imagePosition.left, imagePosition.top);
this.renderer.setStyle(this.image, 'visibility', 'visible');
this.imageLeft = imagePosition.left;
this.imageLoaded = true;
};
onMouseScroll(scroll) {
if (this.parallaxBoundaries && this.image) {
const topPx = this.getImageTop(scroll, this.parallaxBoundaries);
this.setImageTransform(this.image, this.imageLeftPx, topPx);
}
}
/**
* Remove other / old parallax images
* @param container main container HTMLElement
* On window resize event reload parallax properties.
*/
removePreviousImages(container) {
const images = Array.from(container.getElementsByClassName('parallax-image'));
for (const element of images) {
if (element.classList.contains('parallax-image')) {
this.renderer.removeChild(container, element);
}
onResize() {
if (this.image) {
this.setImageProperties(this.image);
}
}
/**
* Set default image size and return new parallax position
* @param container main container HTMLElement
* @param image main image HTMLElement
* Set image properties after image is fully loaded.
* @param {Event} event - Image loaded event.
*/
setParallaxPosition(container, image) {
this.setImageSize(container.clientWidth, container.clientHeight, image, this.parallaxPercentage, this.isDisabled);
const elementTop = container.getBoundingClientRect().top + this.scrollTop;
this.parallaxBoundaries = this.getParallaxBoundaries(elementTop, container.clientHeight, this.image.height, this.parallaxPercentage);
const left = this.getImageLeft(container.clientWidth, image.width, this.positionPercentage);
const top = this.getImageTop(this.scrollTop, this.parallaxBoundaries, this.isDisabled);
return { left, top };
onImageLoaded(event) {
this.image = event.target;
this.setImageProperties(this.image);
this.isLoaded = true;
}
/**
* Set default properties for container and image
* @param container main container HTMLElement
* @param image main image HTMLElement
* Set image properties needed for parallax effect.
* @param {HTMLImageElement} image - Image to be parallaxed.
*/
setStaticProperties(container, image) {
if (!this.isAlreadyPositioned(container)) {
setImageProperties(image) {
const scrollTop = this.scrollEventService.getMouseScrollValue();
this.setImageSize(image, this.htmlElement.nativeElement.clientWidth, this.htmlElement.nativeElement.clientHeight, this.parallaxPercentage, this.isDisabled);
this.parallaxBoundaries = this.getParallaxBoundaries(scrollTop, this.htmlElement.nativeElement, image.height, this.parallaxPercentage);
this.imageLeftPx = this.getImageLeft(this.htmlElement.nativeElement.clientWidth, image.width, this.positionPercentage);
const topPx = this.isDisabled ?
this.getDisabledImageTop(this.parallaxBoundaries) :
this.getImageTop(scrollTop, this.parallaxBoundaries);
this.setImageTransform(image, this.imageLeftPx, topPx);
}
/**
* Set container position to relative
* if image is not already in relative or absolute position.
* @param {HTMLElement} container
*/
setContainerPosition(container) {
if (container.style.position !== 'relative' && container.style.position !== 'absolute') {
this.renderer.setStyle(container, 'position', 'relative');
}
this.renderer.setStyle(container, 'overflow', this.visibleOverflow ? 'visible' : 'hidden');
this.renderer.setStyle(image, 'z-index', this.imageZIndex);
this.renderer.setStyle(image, 'position', 'absolute');
this.renderer.setStyle(image, 'left', '0');
this.renderer.setStyle(image, 'top', '0');
}
/**
* Check if element has position absolute or relative
* @param element html element
* Set container overflow.
* @param {HTMLElement} container - Container element.
* @param {boolean} isOverflowVisible - true to show container overflow.
*/
isAlreadyPositioned(element) {
return ['absolute', 'relative'].includes(window.getComputedStyle(element).position);
setContainerOverflow(container, isOverflowVisible) {
this.renderer.setStyle(container, 'overflow', isOverflowVisible ? 'visible' : 'hidden');
}
/**
* Set default image size that match properties
* @param containerWidth main container HTMLElement width
* @param containerHeight main container HTMLElement height
* @param image main image HTMLElement
* @param parallaxPercentage parallax scroll percentage
* @param isDisabled parallax is disabled
* Set image size based on container size,
* parallax percentage and disabled state.
* @param {HTMLImageElement} image - Image element.
* @param {number} containerWidth - Container width.
* @param {number} containerHeight - Container height.
* @param {number} parallaxPercentage - Parallax percentage.
* @param {boolean} isDisabled - true to disable parallax effect.
*/
setImageSize(containerWidth, containerHeight, image, parallaxPercentage, isDisabled) {
const minHeight = (containerHeight * (100 + (isDisabled ? 0 : parallaxPercentage))) / 100;
setImageSize(image, containerWidth, containerHeight, parallaxPercentage, isDisabled) {
const minimumHeight = (containerHeight * (100 + (isDisabled ? 0 : parallaxPercentage))) / 100;
const ratio = image.naturalHeight / image.naturalWidth;
const minRatio = minHeight / containerWidth;
if (ratio > minRatio) {
this.image.setAttribute('width', `${containerWidth}px`);
this.image.setAttribute('height', `auto`);
const minimumRatio = minimumHeight / containerWidth;
if (ratio > minimumRatio) {
this.renderer.setAttribute(image, 'width', `${containerWidth}px`);
this.renderer.setAttribute(image, 'height', `auto`);
}
else {
this.image.setAttribute('height', `${minHeight}px`);
this.image.setAttribute('width', `auto`);
this.renderer.setAttribute(image, 'width', `auto`);
this.renderer.setAttribute(image, 'height', `${minimumHeight}px`);
}
}
/**
* Get parallax scrolling visible area.
* Use this when container overflow is hidden for better page performance
* @param elementTop main container position from the top of the document in pixels
* @param elementHeight main container height in pixels
* @param imageHeight parallax image height in pixels
* @param parallaxPercentage parallax scroll percentage
* Get parallax boundaries. This data is used
* to calculate parallax movement.
* @param {number} scrollTop - Scroll top.
* @param {HTMLElement} container - Container element.
* @param {number} imageHeight - Image height.
* @param {number} parallaxPercentage - Parallax percentage.
* @return {ParallaxBoundariesModel} - Parallax boundaries.
*/
getParallaxBoundaries(elementTop, elementHeight, imageHeight, parallaxPercentage) {
const usablePixels = elementHeight / 100 * parallaxPercentage;
const unusablePixels = imageHeight - elementHeight - usablePixels;
getParallaxBoundaries(scrollTop, container, imageHeight, parallaxPercentage) {
const elementTop = container.getBoundingClientRect().top + scrollTop;
const usablePixels = container.clientHeight / 100 * parallaxPercentage;
const unusablePixels = imageHeight - container.clientHeight - usablePixels;
const startPoint = elementTop - usablePixels - window.innerHeight;
const endPoint = elementTop + elementHeight + usablePixels;
const endPoint = elementTop + container.clientHeight + usablePixels;
const totalPixels = endPoint - startPoint;

@@ -247,16 +325,8 @@ return { startPoint, endPoint, totalPixels, usablePixels, unusablePixels };

/**
* Set image transform property
* @param image image HTMLImageElement element
* @param imageLeft image left shift in pixels
* @param imageTop image top shift in pixels
* Get image left position.
* @param {number} containerWidth - Container width.
* @param {number} imageWidth - Image width.
* @param {number} positionPercentage - Position percentage.
* @return {number} - Image left position.
*/
setImageTransform(image, imageLeft, imageTop) {
this.renderer.setStyle(image, 'transform', `translate3d(${imageLeft}px, ${imageTop}px, 0)`);
}
/**
* Get image left property based on positionPercentage in pixels
* @param containerWidth main container width in pixels
* @param imageWidth image width in pixels
* @param positionPercentage image position percentage
*/
getImageLeft(containerWidth, imageWidth, positionPercentage) {

@@ -266,30 +336,53 @@ return (containerWidth - imageWidth) / 100 * positionPercentage;

/**
* Get image top shift in pixels
* @param scrollTop pixels from the top of the page to the current view
* @param boundaries parallax position points inside the page
* @param isDisabled parallax is disabled
* Get image top position.
* @param {number} scrollTop - Scroll top.
* @param {ParallaxBoundariesModel} boundaries - Parallax boundaries.
* @return {number} - Image top position.
*/
getImageTop(scrollTop, boundaries, isDisabled) {
getImageTop(scrollTop, boundaries) {
const area = Math.max(0, Math.min(scrollTop - boundaries.startPoint, boundaries.totalPixels));
const areaPercentage = 100 / boundaries.totalPixels * area;
if (isDisabled) {
return (-boundaries.usablePixels - boundaries.unusablePixels) / 2;
}
return -boundaries.usablePixels * (1 - areaPercentage / 100) - boundaries.unusablePixels / 2;
}
/**
* Get disabled image top position.
* @param {number} boundaries - Parallax boundaries.
* @return {number} - Image top position.
*/
getDisabledImageTop(boundaries) {
return (-boundaries.usablePixels - boundaries.unusablePixels) / 2;
}
/**
* Set image transform properties.
* @param {HTMLImageElement} image - Image element.
* @param {number} leftPx - Image left position.
* @param {number} topPx - Image top position.
*/
setImageTransform(image, leftPx, topPx) {
const newTranslate = `translate(${leftPx.toFixed(1)}px, ${topPx.toFixed(1)}px)`;
if (image.style.transform !== newTranslate) {
this.renderer.setStyle(image, 'transform', newTranslate);
}
}
}
RfxParallaxDirective.decorators = [
{ type: Directive, args: [{
selector: '[libRfxParallax]'
RfxParallaxComponent.decorators = [
{ type: Component, args: [{
selector: '[libRfxParallax]',
template: "<img\r\n [@visibility]=\"isLoaded\"\r\n libWillChange\r\n [isDisabled]=\"isDisabled\"\r\n class=\"rfx-image\"\r\n [src]=\"imageUrl\"\r\n [style.zIndex]=\"imageZIndex\"\r\n (load)=\"onImageLoaded($event)\" />\r\n\r\n<ng-content></ng-content>\r\n",
animations: [
visibilityAnimation
],
styles: [".rfx-image{position:absolute;left:0;top:0;will-change:transform;opacity:0}\n"]
},] }
];
RfxParallaxDirective.ctorParameters = () => [
RfxParallaxComponent.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 },
{ type: RfxParallaxService }
{ type: ScrollEventService },
{ type: ResizeEventService }
];
RfxParallaxDirective.propDecorators = {
RfxParallaxComponent.propDecorators = {
imageUrl: [{ type: Input }],
parallaxPercentage: [{ type: Input }],
positionPercentage: [{ type: Input }],
imageUrl: [{ type: Input }],
imageZIndex: [{ type: Input }],

@@ -300,2 +393,104 @@ visibleOverflow: [{ type: Input }],

class WillChangeDirective {
constructor(htmlElement, renderer, scrollEventService) {
this.htmlElement = htmlElement;
this.renderer = renderer;
this.scrollEventService = scrollEventService;
this.triggerArea = window.innerHeight / 4 * 6;
this.isDisabled = false;
this.willChange = true;
}
ngOnInit() {
this.willChangeArea = this.getWillChangeArea();
if (!this.isDisabled) {
this.createListener();
}
}
ngOnDestroy() {
this.destroyListener();
}
/**
* Create listener for scroll event.
*/
createListener() {
this.scrollEventListener = this.scrollEventService.getMouseScroll().subscribe((scroll) => this.checkWillChange(scroll));
}
/**
* Destroy scroll event listener.
*/
destroyListener() {
var _a;
(_a = this.scrollEventListener) === null || _a === void 0 ? void 0 : _a.unsubscribe();
}
/**
* Refresh will-change area if some properties changed.
* @param {SimpleChanges} changes - Changes.
*/
ngOnChanges(changes) {
var _a, _b, _c, _d;
if ((((_a = changes === null || changes === void 0 ? void 0 : changes.triggerArea) === null || _a === void 0 ? void 0 : _a.currentValue) !== undefined && !((_b = changes === null || changes === void 0 ? void 0 : changes.triggerArea) === null || _b === void 0 ? void 0 : _b.firstChange)) ||
((((_c = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _c === void 0 ? void 0 : _c.currentValue) !== undefined && !((_d = changes === null || changes === void 0 ? void 0 : changes.isDisabled) === null || _d === void 0 ? void 0 : _d.firstChange)))) {
const scroll = this.scrollEventService.getMouseScrollValue();
this.willChangeArea = this.getWillChangeArea();
this.checkWillChange(scroll);
}
}
/**
* Check will-change property and
* update if needed.
* @param {number} scroll - Scroll position.
*/
checkWillChange(scroll) {
if (this.willChangeArea) {
const isElementInArea = this.isElementInArea(scroll, this.willChangeArea);
if (isElementInArea !== this.willChange) {
this.setWillChange(isElementInArea);
}
}
}
/**
* Check if element is in will-change area.
* @param {number} scroll - Scroll position.
* @param {SectionAreaModel} willChangeArea - Will-change area.
* @returns {boolean} - Is element in will-change area.
*/
isElementInArea(scroll, willChangeArea) {
return scroll >= willChangeArea.top && scroll <= willChangeArea.bottom;
}
/**
* Calculate area where element is probably going to be animated soon.
* @returns {number} - Will-change area.
*/
getWillChangeArea() {
const elementRect = this.htmlElement.nativeElement.getBoundingClientRect();
const scroll = this.scrollEventService.getMouseScrollValue();
const elementTop = elementRect.top + scroll;
const areaTop = elementTop - this.triggerArea;
const areaBottom = elementTop + this.triggerArea;
return { top: areaTop, bottom: areaBottom };
}
/**
* Set element will-change property.
* @param {boolean} willChange - will-change enabled or disabled.
*/
setWillChange(willChange) {
this.willChange = willChange;
this.renderer.setStyle(this.htmlElement.nativeElement, 'will-change', willChange ? 'transform' : 'auto');
}
}
WillChangeDirective.decorators = [
{ type: Directive, args: [{
selector: '[libWillChange]'
},] }
];
WillChangeDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 },
{ type: ScrollEventService }
];
WillChangeDirective.propDecorators = {
triggerArea: [{ type: Input }],
isDisabled: [{ type: Input }]
};
class RfxParallaxModule {

@@ -306,7 +501,8 @@ }

declarations: [
RfxParallaxDirective
RfxParallaxComponent,
WillChangeDirective
],
imports: [],
exports: [
RfxParallaxDirective
RfxParallaxComponent
]

@@ -324,3 +520,3 @@ },] }

export { RfxParallaxModule, RfxParallaxService, RfxParallaxDirective as ɵa };
export { RfxParallaxComponent, RfxParallaxModule, RfxParallaxService, ResizeEventService as ɵa, ScrollEventService as ɵb, visibilityAnimation as ɵc, ScrollEventService as ɵd, ResizeEventService as ɵe, WillChangeDirective as ɵf };
//# sourceMappingURL=rfx-parallax.js.map
{
"name": "rfx-parallax",
"version": "2.2.7",
"version": "3.0.0",
"description": "RfxParallax - parallax made easy",

@@ -5,0 +5,0 @@ "author": {

@@ -1,2 +0,3 @@

export * from './lib/rfx-parallax.service';
export * from './lib/services/rfx-parallax.service';
export * from './lib/components/rfx-parallax/rfx-parallax.component';
export * from './lib/rfx-parallax.module';

@@ -5,2 +5,6 @@ /**

export * from './public-api';
export { RfxParallaxDirective as ɵa } from './lib/rfx-parallax.directive';
export { visibilityAnimation as ɵc } from './lib/animations';
export { WillChangeDirective as ɵf } from './lib/directives/will-change.directive';
export { ResizeEventService as ɵe, ScrollEventService as ɵd } from './lib/services';
export { ResizeEventService as ɵa } from './lib/services/resize-event.service';
export { ScrollEventService as ɵb } from './lib/services/scroll-event.service';

@@ -1,1 +0,1 @@

{"__symbolic":"module","version":4,"metadata":{"RfxParallaxService":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":11,"character":1},"arguments":[{"providedIn":"root"}]}],"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"RendererFactory2","line":25,"character":29}]}],"ngOnDestroy":[{"__symbolic":"method"}],"initListeners":[{"__symbolic":"method"}],"setElementResizeEvent":[{"__symbolic":"method"}],"onMouseScroll":[{"__symbolic":"method"}],"getMouseScroll":[{"__symbolic":"method"}],"onWindowResize":[{"__symbolic":"method"}],"getWindowResize":[{"__symbolic":"method"}]},"statics":{"ɵprov":{}}},"RfxParallaxModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":3,"character":1},"arguments":[{"declarations":[{"__symbolic":"reference","name":"ɵa"}],"imports":[],"exports":[{"__symbolic":"reference","name":"ɵa"}]}]}],"members":{}},"ɵa":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive","line":5,"character":1},"arguments":[{"selector":"[libRfxParallax]"}]}],"members":{"parallaxPercentage":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":9,"character":3}}]}],"positionPercentage":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":10,"character":3}}]}],"imageUrl":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":11,"character":3}}]}],"imageZIndex":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":12,"character":3}}]}],"visibleOverflow":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":13,"character":3}}]}],"isDisabled":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":14,"character":3}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":26,"character":25},{"__symbolic":"reference","module":"@angular/core","name":"Renderer2","line":27,"character":22},{"__symbolic":"reference","name":"RfxParallaxService"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnDestroy":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"setListeners":[{"__symbolic":"method"}],"onMouseScroll":[{"__symbolic":"method"}],"onWindowResize":[{"__symbolic":"method"}],"loadImage":[{"__symbolic":"method"}],"removePreviousImages":[{"__symbolic":"method"}],"setParallaxPosition":[{"__symbolic":"method"}],"setStaticProperties":[{"__symbolic":"method"}],"isAlreadyPositioned":[{"__symbolic":"method"}],"setImageSize":[{"__symbolic":"method"}],"getParallaxBoundaries":[{"__symbolic":"method"}],"setImageTransform":[{"__symbolic":"method"}],"getImageLeft":[{"__symbolic":"method"}],"getImageTop":[{"__symbolic":"method"}]}}},"origins":{"RfxParallaxService":"./lib/rfx-parallax.service","RfxParallaxModule":"./lib/rfx-parallax.module","ɵa":"./lib/rfx-parallax.directive"},"importAs":"rfx-parallax"}
{"__symbolic":"module","version":4,"metadata":{"RfxParallaxService":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":4,"character":1},"arguments":[{"providedIn":"root"}]}],"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","name":"ɵa"},{"__symbolic":"reference","name":"ɵb"}]}],"initListeners":[{"__symbolic":"method"}]},"statics":{"ɵprov":{}}},"RfxParallaxComponent":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":6,"character":1},"arguments":[{"selector":"[libRfxParallax]","animations":[{"__symbolic":"reference","name":"ɵc"}],"template":"<img\r\n [@visibility]=\"isLoaded\"\r\n libWillChange\r\n [isDisabled]=\"isDisabled\"\r\n class=\"rfx-image\"\r\n [src]=\"imageUrl\"\r\n [style.zIndex]=\"imageZIndex\"\r\n (load)=\"onImageLoaded($event)\" />\r\n\r\n<ng-content></ng-content>\r\n","styles":[".rfx-image{position:absolute;left:0;top:0;will-change:transform;opacity:0}\n"]}]}],"members":{"imageUrl":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":21,"character":3}}]}],"parallaxPercentage":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":30,"character":3}}]}],"positionPercentage":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":39,"character":3}}]}],"imageZIndex":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":47,"character":3}}]}],"visibleOverflow":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":55,"character":3}}]}],"isDisabled":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":64,"character":3}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":107,"character":25},{"__symbolic":"reference","module":"@angular/core","name":"Renderer2","line":108,"character":22},{"__symbolic":"reference","name":"ɵd"},{"__symbolic":"reference","name":"ɵe"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"ngOnDestroy":[{"__symbolic":"method"}],"hasValueChanged":[{"__symbolic":"method"}],"destroyListeners":[{"__symbolic":"method"}],"createListeners":[{"__symbolic":"method"}],"onMouseScroll":[{"__symbolic":"method"}],"onResize":[{"__symbolic":"method"}],"onImageLoaded":[{"__symbolic":"method"}],"setImageProperties":[{"__symbolic":"method"}],"setContainerPosition":[{"__symbolic":"method"}],"setContainerOverflow":[{"__symbolic":"method"}],"setImageSize":[{"__symbolic":"method"}],"getParallaxBoundaries":[{"__symbolic":"method"}],"getImageLeft":[{"__symbolic":"method"}],"getImageTop":[{"__symbolic":"method"}],"getDisabledImageTop":[{"__symbolic":"method"}],"setImageTransform":[{"__symbolic":"method"}]}},"RfxParallaxModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":4,"character":1},"arguments":[{"declarations":[{"__symbolic":"reference","name":"RfxParallaxComponent"},{"__symbolic":"reference","name":"ɵf"}],"imports":[],"exports":[{"__symbolic":"reference","name":"RfxParallaxComponent"}]}]}],"members":{}},"ɵa":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":3,"character":1},"arguments":[{"providedIn":"root"}]}],"members":{"__ctor__":[{"__symbolic":"constructor"}],"ngOnDestroy":[{"__symbolic":"method"}],"createListener":[{"__symbolic":"method"}],"destroyListener":[{"__symbolic":"method"}],"onResizeEvent":[{"__symbolic":"method"}],"getResize":[{"__symbolic":"method"}]},"statics":{"ɵprov":{}}},"ɵb":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":3,"character":1},"arguments":[{"providedIn":"root"}]}],"members":{"__ctor__":[{"__symbolic":"constructor"}],"ngOnDestroy":[{"__symbolic":"method"}],"createListener":[{"__symbolic":"method"}],"destroyListener":[{"__symbolic":"method"}],"onMouseScroll":[{"__symbolic":"method"}],"getMouseScroll":[{"__symbolic":"method"}],"getMouseScrollValue":[{"__symbolic":"method"}]},"statics":{"ɵprov":{}}},"ɵf":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive","line":5,"character":1},"arguments":[{"selector":"[libWillChange]"}]}],"members":{"triggerArea":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":14,"character":3}}]}],"isDisabled":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input","line":22,"character":3}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":45,"character":25},{"__symbolic":"reference","module":"@angular/core","name":"Renderer2","line":46,"character":22},{"__symbolic":"reference","name":"ɵd"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnDestroy":[{"__symbolic":"method"}],"createListener":[{"__symbolic":"method"}],"destroyListener":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"checkWillChange":[{"__symbolic":"method"}],"isElementInArea":[{"__symbolic":"method"}],"getWillChangeArea":[{"__symbolic":"method"}],"setWillChange":[{"__symbolic":"method"}]}}},"origins":{"RfxParallaxService":"./lib/services/rfx-parallax.service","RfxParallaxComponent":"./lib/components/rfx-parallax/rfx-parallax.component","RfxParallaxModule":"./lib/rfx-parallax.module","ɵa":"./lib/services/resize-event.service","ɵb":"./lib/services/scroll-event.service","ɵc":"./lib/animations","ɵd":"./lib/services","ɵe":"./lib/services","ɵf":"./lib/directives/will-change.directive"},"importAs":"rfx-parallax"}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc