Repository: dixonandmoe/rellax
Branch: master
Commit: 9ed6cb0aae03
Files: 20
Total size: 101.4 KB
Directory structure:
gitextract__z1v1247/
├── .gitignore
├── LICENSE
├── README.md
├── absolute.html
├── bower.json
├── css/
│ └── main.css
├── demo.html
├── option.js
├── package.json
├── rellax.js
└── tests/
├── center.html
├── destroy.html
├── directions.html
├── horizontal.html
├── percentage.html
├── range.html
├── responsive-speeds.html
├── speed.html
├── style.html
└── wrapper.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
rellax-build.js
npm-debug.log
debug.log
# Latest bootstrap version
bootstrap.min_v4.css
# demo file with new bootstrap file
demo1.html
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2016 Dixon & Moe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# RELLAX
[](https://www.npmjs.org/package/rellax)
[](https://bundlephobia.com/result?p=rellax)
[](https://bundlephobia.com/result?p=rellax)
Rellax is a buttery smooth, super lightweight, vanilla javascript parallax library. **Update:** Rellax now works on mobile (v1.0.0).
* [Demo Website](https://dixonandmoe.com/rellax/)
## Getting Started
### Using npm
`npm install rellax --save`
### Using yarn
`yarn add rellax`
### CDN
``
### Download Locally
if you're old school like us download and insert `rellax.min.js` in your html
```html
I’m that default chill speed of "-2"
I’m super fast!!
I’m extra slow and smooth
```
```html
```
## Features
### Speed
Use the `data-rellax-speed` attribute to set the speed of a `.rellax` element to something other than the default value (which is `-2`). A negative value will make it move slower than regular scrolling, and a positive value will make it move faster. We recommend keeping the speed between `-10` and `10`.
#### Responsive Speed
Use responsive speed attributes for breakpoint levels that require a different speed. Defaults to the `data-rellax-speed` setting in unspecified breakpoints.
```html
I parallax at all different speeds depending on your screen width.
```
Pass an array of breakpoints. Each breakpoint value represents the resolution for mobile, tablet, desktop respectively. Checkout the responsiveness of the [`demo`](https://dixonandmoe.com/rellax/)
```html
```
### Centering
After some fantastic work from [@p-realinho](https://github.com/p-realinho), we just released the ability to center parallax elements in your viewport! We'll be building a nice demo website, but for now check out the tests folder for several examples of how it works.
There's two ways to implement centering, either on specific elements or as a global option.
1. #### Element-wise Centering
- Add the ```data-rellax-percentage="0.5"``` to a specific html element
```html
I’m that default chill speed of "-2" and "centered"
I’m super fast!! And super centered!!
I’m extra slow and smooth, and hella centered.
```
2. #### Global Centering
- To activate the center feature in your whole html, add the code your `
```
### Z-index
If you want to sort your elements properly in the Z space, you can use the data-rellax-zindex property
```html
I’m that default chill speed of "-2" and default z-index of 0
I’m super fast!! And on top of the previous element, I'm z-index 5!!
```
### Horizontal Parallax
Horizontal parallax is disabled by default. You can enable it by passing `horizontal: true` in the settings block.
This feature is intended for panoramic style websites, where users scroll horizontally instead of vertically.
Note that this can work together at the same time with the default vertical parallax. If you do not want this, pass `vertical: false` in the settings block.
```html
```
### Custom Wrapper
By default, the position of parallax elements is determined via the scroll position of the body. Passing in the `wrapper` property will tell Rellax to watch that element instead.
```html
```
### Refresh
```html
```
### Destroy
```html
```
### Callback
```html
```
### Target node
Instead of using a className you can use a node, handy when using React and you want to use `refs` instead of `className`.
```jsx
{ this.rellaxRef = ref }}>
I’m that default chill speed of "-2"
var rellax = new Rellax(this.rellaxRef)
```
## In the Wild
If you're using Rellax in production, we'd love to list you here! Let us know: moe@dixonandmoe.com
- [Bowmore Scotch](https://www.bowmore.com/)
- [Generated Photos](https://generated.photos/)
- [How Much Does a Website Cost](https://designagency.io/)
- [Linux Man Pages](https://dashdash.io/)
- [Laws of UX](https://lawsofux.com/)
- [Finch](https://finch.io/)
- [Embedded Payroll](https://robotist.com/embedded-payroll-api)
- [Product Designer in San Francisco](https://moeamaya.com/)
- [EthWorks](http://ethworks.io/)
- [Lorem Ipsum Generator](https://loremipsumgenerator.com/)
- [Deeson](https://www.deeson.co.uk/)
## Development
In the spirit of lightweight javascript, the build processes (thus far) is lightweight also.
1. Open demo.html
2. Make code changes and refresh browser
3. Once feature is finished or bug fixed, use [jshint](http://jshint.com/) to lint code
4. Fix lint issues then use [Google Closure Compiler](https://closure-compiler.appspot.com/home) to minify
5. 🍻
## Changelog
- 1.7.1: Remove animation on destory [PR](https://github.com/dixonandmoe/rellax/pull/132)
- 1.7.0: Scroll position set relative to the wrapper [PR](https://github.com/dixonandmoe/rellax/pull/125)
================================================
FILE: absolute.html
================================================
SERIOUSLY, WHY?!
Come on, how boring is the internet without excessive javascript? We
made this library since too many github repos are abandoned (RIP
skrollr) or feature creepy. You got some beef or caught us slippin
on unit tests, send rants and 10mb gifs to
moe@dixonandmoe.com
BUT ACTUALLY
We've benefitted so much from open source projects that we're
actively trying to give back. As designers, we're starting by
releasing our own quirky js code.
or if you're old school like us, download and insert
file in your project folder.
JavaScript (`accepts any class name`)
var rellax = newRellax('.rellax');
Basic Markup (Default Speed: -2)
<div class="rellax"> I’m slow and smooth
</div>
Optional Speed (-10 to +10)
<div class="rellax" data-rellax-speed="-3"> I’m slow and smooth
</div>
<div class="rellax" data-rellax-speed="7"> I’m super fast!!
</div>
<div class="rellax" data-rellax-speed="-5"> I’m extra slow and smooth
</div>
Speed
Use the data-rellax-speed attribute to set the speed of a
.rellax element to something other than the default value
(which is -2). A negative value will make it move slower
than regular scrolling, and a positive value will make it move faster.
We recommend keeping the speed between -10 and +10.
Responsive Speed
Use responsive speed attributes for breakpoint levels that require a
different speed. Defaults to the data-rellax-speed setting
in unspecified breakpoints.
<div
class="rellax"
data-rellax-speed="7"
data-rellax-xs-speed="-5"
data-rellax-mobile-speed="3"
data-rellax-tablet-speed="-8"
data-rellax-desktop-speed="1"> I parallax at all different speeds depending on your screen width.
</div>
Pass an array of breakpoints. Each breakpoint value represents the
resolution for mobile, tablet, desktop respectively. Checkout the
responsiveness of the demo.
After some fantastic work from @p-realinho, we
just released the ability to center parallax elements in your viewport!
We'll be building a nice demo website, but for now check out the tests
folder for several examples of how it works via our tests folder on
GitHub.
There's two ways to implement centering, either on specific elements or as a global option.
<div class="rellax" data-rellax-percentage="0.5"> I’m that default chill speed of "-2" and "centered"
</div>
<div class="rellax" data-rellax-speed="7"
data-rellax-percentage="0.5"> I’m super fast!! And super centered!!
</div>
<div class="rellax" data-rellax-speed="-4"
data-rellax-percentage="0.5"> I’m extra slow and smooth, and hella centered.
</div>
If you want to sort your elements properly in the Z space,
you can use the data-rellax-zindex property.
<div class="rellax"> I’m that default chill speed of "-2" and default z-index of 0
</div>
<div class="rellax" data-rellax-speed="7"
data-rellax-zindex="5"> I’m super fast!! And on top of the previous element, I'm z-index 5!!
</div>
Horizontal Parallax
Horizontal parallax is disabled by default. You can enable it by passing
horizontal: true in the settings
block. This feature is intended for panoramic style websites, where users
scroll horizontally instead of vertically. Note that this can work together
at the same time with the default vertical parallax. If you do not want this,
pass vertical: false.
By default, the position of parallax elements is determined via the scroll
position of the body. Passing in the wrapper
property in the settings block will tell Rellax to watch that element instead.
<script>
//Set wrapper to .custom-element instead of the body var rellax = newRellax('.rellax',
{ wrapper:'.custom-element' });
</script>
Target Node
Instead of using a className you can use a node, handy when using
React and you want to use refs
instead of className
<div ref = {ref => { this.rellaxRef = ref}}> I’m that default chill speed of "-2"
</div>
<script>
var rellax = newRellax(this.rellaxRef);
</script>
Refresh
<script>
// Start Rellax var rellax = newRellax('.rellax');
// Destroy and create again parallax with previous settings rellax.refresh();
</script>
Destroy
<script>
// Start Rellax var rellax = newRellax('.rellax');
// End Rellax and reset parallax elements to their original positions rellax.refresh();
</script>
================================================
FILE: option.js
================================================
// ============================================================
// To activate the active class on the links
// ============================================================
// Get the options menu element
var optnCard = document.getElementById("optnCard");
// Get all links with class="option" inside the menu
var optns = optnCard.getElementsByClassName("option");
// Loop through the links and add the active class to the current/clicked link
for (var i = 0; i < optns.length; i++) {
optns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
================================================
FILE: package.json
================================================
{
"name": "rellax",
"version": "1.12.1",
"description": "Lightweight, vanilla javascript parallax library",
"main": "rellax.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/dixonandmoe/rellax.git"
},
"keywords": [
"parallax"
],
"author": "Moe Amaya (https://dixonandmoe.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/dixonandmoe/rellax/issues"
},
"homepage": "https://dixonandmoe.com/rellax/"
}
================================================
FILE: rellax.js
================================================
// ------------------------------------------
// Rellax.js
// Buttery smooth parallax library
// Copyright (c) 2016 Moe Amaya (@moeamaya)
// MIT license
//
// Thanks to Paraxify.js and Jaime Cabllero
// for parallax concepts
// ------------------------------------------
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.Rellax = factory();
}
}(typeof window !== "undefined" ? window : global, function () {
var Rellax = function(el, options){
"use strict";
var self = Object.create(Rellax.prototype);
var posY = 0;
var screenY = 0;
var posX = 0;
var screenX = 0;
var blocks = [];
var pause = true;
// check what requestAnimationFrame to use, and if
// it's not supported, use the onscroll event
var loop = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ return setTimeout(callback, 1000 / 60); };
// store the id for later use
var loopId = null;
// Test via a getter in the options object to see if the passive property is accessed
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("testPassive", null, opts);
window.removeEventListener("testPassive", null, opts);
} catch (e) {}
// check what cancelAnimation method to use
var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
// check which transform property to use
var transformProp = window.transformProp || (function(){
var testEl = document.createElement('div');
if (testEl.style.transform === null) {
var vendors = ['Webkit', 'Moz', 'ms'];
for (var vendor in vendors) {
if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
return vendors[vendor] + 'Transform';
}
}
}
return 'transform';
})();
// Default Settings
self.options = {
speed: -2,
verticalSpeed: null,
horizontalSpeed: null,
breakpoints: [576, 768, 1201],
center: false,
wrapper: null,
relativeToWrapper: false,
round: true,
vertical: true,
horizontal: false,
verticalScrollAxis: "y",
horizontalScrollAxis: "x",
callback: function() {},
};
// User defined options (might have more in the future)
if (options){
Object.keys(options).forEach(function(key){
self.options[key] = options[key];
});
}
function validateCustomBreakpoints () {
if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
var isAscending = true;
var isNumerical = true;
var lastVal;
self.options.breakpoints.forEach(function (i) {
if (typeof i !== 'number') isNumerical = false;
if (lastVal !== null) {
if (i < lastVal) isAscending = false;
}
lastVal = i;
});
if (isAscending && isNumerical) return;
}
// revert defaults if set incorrectly
self.options.breakpoints = [576, 768, 1201];
console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
}
if (options && options.breakpoints) {
validateCustomBreakpoints();
}
// By default, rellax class
if (!el) {
el = '.rellax';
}
// check if el is a className or a node
var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
// Now query selector
if (elements.length > 0) {
self.elems = elements;
}
// The elements don't exist
else {
console.warn("Rellax: The elements you're trying to select don't exist.");
return;
}
// Has a wrapper and it exists
if (self.options.wrapper) {
if (!self.options.wrapper.nodeType) {
var wrapper = document.querySelector(self.options.wrapper);
if (wrapper) {
self.options.wrapper = wrapper;
} else {
console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
return;
}
}
}
// set a placeholder for the current breakpoint
var currentBreakpoint;
// helper to determine current breakpoint
var getCurrentBreakpoint = function (w) {
var bp = self.options.breakpoints;
if (w < bp[0]) return 'xs';
if (w >= bp[0] && w < bp[1]) return 'sm';
if (w >= bp[1] && w < bp[2]) return 'md';
return 'lg';
};
// Get and cache initial position of all elements
var cacheBlocks = function() {
for (var i = 0; i < self.elems.length; i++){
var block = createBlock(self.elems[i]);
blocks.push(block);
}
};
// Let's kick this script off
// Build array for cached element values
var init = function() {
for (var i = 0; i < blocks.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
blocks = [];
screenY = window.innerHeight;
screenX = window.innerWidth;
currentBreakpoint = getCurrentBreakpoint(screenX);
setPosition();
cacheBlocks();
animate();
// If paused, unpause and set listener for window resizing events
if (pause) {
window.addEventListener('resize', init);
pause = false;
// Start the loop
update();
}
};
// We want to cache the parallax blocks'
// values: base, top, height, speed
// el: is dom object, return: el cache values
var createBlock = function(el) {
var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
var dataSpeed = el.getAttribute( 'data-rellax-speed' );
var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
var dataVerticalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
var dataMin = el.getAttribute( 'data-rellax-min' );
var dataMax = el.getAttribute( 'data-rellax-max' );
var dataMinX = el.getAttribute('data-rellax-min-x');
var dataMaxX = el.getAttribute('data-rellax-max-x');
var dataMinY = el.getAttribute('data-rellax-min-y');
var dataMaxY = el.getAttribute('data-rellax-max-y');
var mapBreakpoints;
var breakpoints = true;
if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
breakpoints = false;
} else {
mapBreakpoints = {
'xs': dataXsSpeed,
'sm': dataMobileSpeed,
'md': dataTabletSpeed,
'lg': dataDesktopSpeed
};
}
// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
// ensures elements are positioned based on HTML layout.
//
// If the element has the percentage attribute, the posY and posX needs to be
// the current scroll position's value, so that the elements are still positioned based on HTML layout
var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
if (self.options.relativeToWrapper) {
var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
}
var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
var posX = self.options.horizontal ? ( dataPercentage || self.options.center ? self.options.wrapper ? self.options.wrapper.scrollLeft : (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft) : 0 ) : 0;
var blockTop = posY + el.getBoundingClientRect().top;
var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
var blockLeft = posX + el.getBoundingClientRect().left;
var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
// apparently parallax equation everyone uses
var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
// Optional individual block speed as data attr, otherwise global speed
var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
// Optional individual block movement axis direction as data attr, otherwise global movement direction
var verticalScrollAxis = dataVerticalScrollAxis ? dataVerticalScrollAxis : self.options.verticalScrollAxis;
var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
// ~~Store non-translate3d transforms~~
// Store inline styles and extract transforms
var style = el.style.cssText;
var transform = '';
// Check if there's an inline styled transform
var searchResult = /transform\s*:/i.exec(style);
if (searchResult) {
// Get the index of the transform
var index = searchResult.index;
// Trim the style to the transform point and get the following semi-colon index
var trimmedStyle = style.slice(index);
var delimiter = trimmedStyle.indexOf(';');
// Remove "transform" string and save the attribute
if (delimiter) {
transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
} else {
transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
}
}
return {
baseX: bases.x,
baseY: bases.y,
top: blockTop,
left: blockLeft,
height: blockHeight,
width: blockWidth,
speed: speed,
verticalSpeed: verticalSpeed,
horizontalSpeed: horizontalSpeed,
verticalScrollAxis: verticalScrollAxis,
horizontalScrollAxis: horizontalScrollAxis,
style: style,
transform: transform,
zindex: dataZindex,
min: dataMin,
max: dataMax,
minX: dataMinX,
maxX: dataMaxX,
minY: dataMinY,
maxY: dataMaxY
};
};
// set scroll position (posY, posX)
// side effect method is not ideal, but okay for now
// returns true if the scroll changed, false if nothing happened
var setPosition = function() {
var oldY = posY;
var oldX = posX;
posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
// If option relativeToWrapper is true, use relative wrapper value instead.
if (self.options.relativeToWrapper) {
var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posY = scrollPosY - self.options.wrapper.offsetTop;
}
if (oldY != posY && self.options.vertical) {
// scroll changed, return true
return true;
}
if (oldX != posX && self.options.horizontal) {
// scroll changed, return true
return true;
}
// scroll did not change
return false;
};
// Ahh a pure function, gets new transform value
// based on scrollPosition and speed
// Allow for decimal pixel values
var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
var result = {};
var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
return result;
};
// Remove event listeners and loop again
var deferredUpdate = function() {
window.removeEventListener('resize', deferredUpdate);
window.removeEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
// loop again
loopId = loop(update);
};
// Loop
var update = function() {
if (setPosition() && pause === false) {
animate();
// loop again
loopId = loop(update);
} else {
loopId = null;
// Don't animate until we get a position updating event
window.addEventListener('resize', deferredUpdate);
window.addEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
}
};
// Transform3d on parallax element
var animate = function() {
var positions;
for (var i = 0; i < self.elems.length; i++){
// Determine relevant movement directions
var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
// Subtracting initialize value, so element stays in same spot as HTML
positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
var positionY = positions.y - blocks[i].baseY;
var positionX = positions.x - blocks[i].baseX;
// The next two "if" blocks go like this:
// Check if a limit is defined (first "min", then "max");
// Check if we need to change the Y or the X
// (Currently working only if just one of the axes is enabled)
// Then, check if the new position is inside the allowed limit
// If so, use new position. If not, set position to limit.
// Check if a min limit is defined
if (blocks[i].min !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
}
}
// Check if directional min limits are defined
if (blocks[i].minY != null) {
positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
}
if (blocks[i].minX != null) {
positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
}
// Check if a max limit is defined
if (blocks[i].max !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
}
}
// Check if directional max limits are defined
if (blocks[i].maxY != null) {
positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
}
if (blocks[i].maxX != null) {
positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
}
var zindex = blocks[i].zindex;
// Move that element
// (Set the new translation and append initial inline transforms.)
var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
self.elems[i].style[transformProp] = translate;
}
self.options.callback(positions);
};
self.destroy = function() {
for (var i = 0; i < self.elems.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
// Remove resize event listener if not pause, and pause
if (!pause) {
window.removeEventListener('resize', init);
pause = true;
}
// Clear the animation loop to prevent possible memory leak
clearLoop(loopId);
loopId = null;
};
// Init
init();
// Allow to recalculate the initial values whenever we want
self.refresh = init;
return self;
};
return Rellax;
}));
================================================
FILE: tests/center.html
================================================