Repository: wagerfield/parallax
Branch: master
Commit: 04e53e94665d
Files: 18
Total size: 47.9 KB
Directory structure:
gitextract_9v95jqid/
├── .gitignore
├── .npmignore
├── .nvmrc
├── LICENSE
├── README.md
├── examples/
│ ├── assets/
│ │ └── styles.scss
│ └── pages/
│ ├── callback.html
│ ├── destroy.html
│ ├── hoveronly.html
│ ├── input_element.html
│ ├── interactive.html
│ ├── relative.html
│ ├── selector.html
│ ├── separate_axis_data.html
│ └── simple.html
├── gulpfile.js
├── package.json
└── src/
└── parallax.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.DS_Store
node_modules
dist
**/*.css
npm-debug.log
================================================
FILE: .npmignore
================================================
examples
logo.png
================================================
FILE: .nvmrc
================================================
8
================================================
FILE: LICENSE
================================================
//============================================================
//
// The MIT License
//
// Copyright (C) 2014 Matthew Wagerfield - @wagerfield
//
// 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
================================================

[](https://cdnjs.com/libraries/parallax)
Parallax Engine that reacts to the orientation of a smart device. Where no gyroscope or motion detection hardware is available, the position of the cursor is used instead.
Check out the **[demo](https://matthew.wagerfield.com/parallax/)** to see it in action!
# Table of Contents
- [1. Getting started](#1-getting-started)
- [1.1 Installation](#11-installation)
- [1.2 Preparations](#12-preparations)
- [1.3 Run Parallax](#13-run-parallax)
- [2. Configuration](#2-configuration)
- [2.1 Programmatic vs Declarative](#21-programmatic-vs-declarative)
- [2.2 Configuration Options](#22-configuration-options)
- [3. Methods](#3-methods)
- [4. Development](#4-development)
- [4.1 Running the Project](#41-running-the-project)
- [4.2 Opening an Issue](#42-opening-an-issue)
- [4.3 Known Issues](#43-known-issues)
- [5. FAQ](#5-faq)
- [6. Information](#6-information)
- [6.1 License](#61-license)
- [6.2 Contributors](#62-authors)
# 1. Getting started
## 1.1 Installation
### 1.1 a) Using the CDN
1. Add `<script src="https://cdnjs.cloudflare.com/ajax/libs/parallax/3.1.0/parallax.min.js"></script>` to your markup
2. Done!
Many thanks to the fine folks over at [cdnjs](https://cdnjs.com/) for hosting our library.
### 1.1 b) Beginners
1. Head over to the [releases](https://github.com/wagerfield/parallax/releases) Section
2. Download `compiled.zip` from the latest release
3. Extract the ZIP archive and locate the `parallax.js` and `parallax.min.js` files
- Use `parallax.js` if you want to snoop around in the code
- Use `parallax.min.js` for deployment, because it has a smaller file size
4. Copy the file of your choice into your project directory
5. So far, so good!
### 1.1 c) Professionals
`npm i -s parallax-js`
You will then find the source code in `node_modules/parallax-js/src/parallax.js` and the browserified, babelified, uglified, production-ready version in `node_modules/parallax-js/dist/parallax.min.js`
## 1.2 Preparations
### Include the Script
If you use the compiled version, either downloaded from the releases page, or copied from the `dist` folder, include the script like any other Javascript library:
`<script src="path/to/parallax.js"></script>`
Of course, when you've installed via npm, and use browserify/babel, you can also simply do:
`import Parallax from 'parallax-js'` or
`const Parallax = require('parallax-js')`
### Create your HTML elements
Each Parallax.js instance needs a container element, the scene. You're free to identify it by any means you want, but for now, let's use an ID:
```html
<div id="scene">
</div>
```
Per default, all direct child elements of the scene will become moving objects, the layers. You can change this to a custom query selector, but again, we're going with the easiest approach for now:
```html
<div id="scene">
<div>My first Layer!</div>
<div>My second Layer!</div>
</div>
```
While all other options and parameters are optional, with sane defaults, and can be set programatically, each layer needs a `data-depth` attribute. The movement applied to each layer will be multiplied by its depth attribute.
```html
<div id="scene">
<div data-depth="0.2">My first Layer!</div>
<div data-depth="0.6">My second Layer!</div>
</div>
```
## 1.3 Run Parallax
As soon as your DOM is ready and loaded, you can create a new Parallax.js instance, providing your scene element as first parameter.
```javascript
var scene = document.getElementById('scene');
var parallaxInstance = new Parallax(scene);
```
That's it, you're running Parallax.js now!
# 2. Configuration
## 2.1 Programmatic vs Declarative
Most configuration settings can be declared either as data-value attribute of the scene element, or property of the configuration object. The programmatic approach will take priority over the data-value attributes set in the HTML.
Some options can also be set at run-time via instance methods.
Declarative:
```html
<div data-relative-input="true" id="scene">
<div data-depth="0.2">My first Layer!</div>
<div data-depth="0.6">My second Layer!</div>
</div>
```
Programmatic:
```javascript
var scene = document.getElementById('scene');
var parallaxInstance = new Parallax(scene, {
relativeInput: true
});
```
Using Methods at Runtime:
```javascript
parallaxInstance.friction(0.2, 0.2);
```
## 2.2 Configuration Options
### relativeInput
Property: **relativeInput**
Attribute: **data-relative-input**
Value: *boolean*
Default: *false*
Makes mouse input relative to the position of the scene element.
No effect when gyroscope is used.
### clipRelativeInput
Property: **clipRelativeInput**
Attribute: **data-clip-relative-input**
Value: *boolean*
Default: *false*
Clips mouse input to the bounds of the scene. This means the movement stops as soon as the edge of the scene element is reached by the cursor.
No effect when gyroscope is used, or `hoverOnly` is active.
### hoverOnly
Property: **hoverOnly**
Attribute: **data-hover-only**
Value: *boolean*
Default: *false*
Parallax will only be in effect while the cursor is over the scene element, otherwise all layers move back to their initial position. Works best in combination with `relativeInput`.
No effect when gyroscope is used.
### inputElement
Property: **inputElement**
Attribute: **data-input-element**
Method: **setInputElement(HTMLElement)**
Value: *null* or *HTMLElement* / *String*
Default: *null*
Allows usage of a different element for cursor input.
The configuration property expects an HTMLElement, the data value attribute a query selector string.
Will only work in combination with `relativeInput`, setting `hoverOnly` might make sense too.
No effect when gyroscope is used.
### calibrateX & calibrateY
Property: **calibrateX** & **calibrateY**
Attribute: **data-calibrate-x** & **data-calibrate-y**
Method: **calibrate(x, y)**
Value: *boolean*
Default: *false* for X, *true* for Y
Caches the initial X/Y axis value on initialization and calculates motion relative to this.
No effect when cursor is used.
### invertX & invertY
Property: **invertX** & **invertY**
Attribute: **data-invert-x** & **data-invert-y**
Method: **invert(x, y)**
Value: *boolean*
Default: *true*
Inverts the movement of the layers relative to the input. Setting both of these values to *false* will cause the layers to move with the device motion or cursor.
### limitX & limitY
Property: **limitX** & **limitY**
Attribute: **data-limit-x** & **data-limit-y**
Method: **limit(x, y)**
Value: *false* or *integer*
Default: *false*
Limits the movement of layers on the respective axis. Leaving this value at false gives complete freedom to the movement.
### scalarX & scalarY
Property: **scalarX** & **scalarY**
Attribute: **data-scalar-x** & **data-scalar-y**
Method: **scalar(x, y)**
Value: *float*
Default: *10.0*
Multiplies the input motion by this value, increasing or decreasing the movement speed and range.
### frictionX & frictionY
Property: **frictionX** & **frictionY**
Attribute: **data-friction-x** & **data-friction-y**
Method: **friction(x, y)**
Value: *float* between *0* and *1*
Default: *0.1*
Amount of friction applied to the layers. At *1* the layers will instantly go to their new positions, everything below 1 adds some easing.
The default value of *0.1* adds some sensible easing. Try *0.15* or *0.075* for some difference.
### originX & originY
Property: **originX** & **originY**
Attribute: **data-origin-x** & **data-origin-y**
Method: **origin(x, y)**
Value: *float* between *0* and *1*
Default: *0.5*
X and Y origin of the mouse input. The default of *0.5* refers to the center of the screen or element, *0* is the left (X axis) or top (Y axis) border, 1 the right or bottom.
No effect when gyroscope is used.
### precision
Property: **precision**
Attribute: **data-precision**
Value: *integer*
Default: *1*
Decimals the element positions will be rounded to. *1* is a sensible default which you should not need to change in the next few years, unless you have a very interesting and unique setup.
### selector
Property: **selector**
Attribute: **data-selector**
Value: *null* or *string*
Default: *null*
String that will be fed to querySelectorAll on the scene element to select the layer elements. When *null*, will simply select all direct child elements.
Use `.layer` for legacy behaviour, selecting only child elements having the class name *layer*.
### pointerEvents
Property: **pointerEvents**
Attribute: **data-pointer-events**
Value: *boolean*
Default: *false*
Set to *true* to enable interactions with the scene and layer elements. When set to the default of *false*, the CSS attribute `pointer-events: none` will be applied for performance reasons.
Setting this to *true* alone will not be enough to fully interact with all layers, since they will be overlapping. You have to either set `position: absolute` on all layer child elements, or keep **pointerEvents** at *false* and set `pointer-events: all` for the interactable elements only.
### onReady
Property: **onReady**
Value: *null* or *function*
Default: *null*
Callback function that will be called as soon as the Parallax instance has finished its setup. This might currently take up to 1000ms (`calibrationDelay * 2`).
# 3. Methods
In addition to the configuration methods outlined in the section above, there are a few more publicly accessible methods:
### enable()
Enables a disabled Parallax instance.
### disable()
Disables a running Parallax instance.
### destroy()
Completely destroys a Parallax instance, allowing it to be garbage collected.
### version()
Returns the version number of the Parallax library.
# 4. Development
## 4.1 Running the Project
1. Clone the Repository `git clone git@github.com:wagerfield/parallax.git`
2. Open the working directory `cd parallax`
3. Install dependencies `npm install`
4. Run development server `gulp watch`
5. Open [http://localhost:9000/](http://localhost:9000/) in browser
## 4.2 Opening an Issue
If you need help relating the direct usage of this library in a project of yours, provide us with a working, running example of your work. This can be a GitHub repository, a ZIP file containing your work, a project on CodePen or JSFiddle, you name it.
*Do not complain about something not working without giving us some way to help you.* Thank you!
## 4.3 Known Issues
### SVG-Bug in MS Edge
It seems MS Edge does not support the `children` or `querySelectorAll` methods for SVG elements.
### Animation running really slow
Depending on your site, the GPU might have a bit too much to do. You can try adding the CSS definition `will-change: transform` to the layer elements to speed things up. Use sparingly!
### Gyroscope not working on Android
Android will only allow access to the gyroscope o secure origins (that is, with `https` protocol).
### Gyroscope not working on iOS
Because gyroscope data had been abused to track users, it's disabled on iDevices by default and needs to be enabled by the users. You can try asking for permission via [DeviceOrientationEvent.requestPermission](https://www.w3.org/TR/orientation-event/#dom-deviceorientationevent-requestpermission).
Do something like:
```js
DeviceOrientationEvent
.requestPermission()
.then(() => {
new Parallax(scene)
})
```
### Unable to manually set position of layers
Since this often lead to issues, this library forces the positioning of the layers to be absolute. If you need to override this, add `!important` to your CSS positioning.
# 5. FAQ
### How can I use this Library with jQuery?
jQuery will not prevent you from using this library in any way. If you want to use jQuery for selecting your Parallax scene element, you can do so too.
```javascript
var scene = $('#scene').get(0);
var parallaxInstance = new Parallax(scene);
```
### How can I interact with my layers?
Check out the section on the configuration option `pointerEvents` above.
### How do I get the demo files to work?
Either download compiled_with_examples.zip from the [GitHub Releases](https://github.com/wagerfield/parallax/releases) section, or follow section 4.1
# 6. Information
## 6.1 License
This project is licensed under the terms of the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Enjoy!
## 6.2 Authors
Matthew Wagerfield: [@wagerfield](http://twitter.com/wagerfield)
René Roth: [Website](http://reneroth.xyz/)
================================================
FILE: examples/assets/styles.scss
================================================
$color-green: #00ffaa;
$color-background: #111;
$color-text: #555;
body {
background: $color-background;
color: $color-text;
font-family: monospace;
font-size: 18px;
margin: 0;
}
img {
display: block;
width: 100%;
}
input[type=checkbox] {
display: none;
}
label {
cursor: pointer;
display: inline-block;
margin-right: 1em;
padding: 0.4em 0;
}
input[type=checkbox] + label:before {
background: $color-text;
content: '';
display: inline-block;
height: 16px;
margin-right: 8px;
position: relative;
top: 1px;
width: 16px;
}
input[type=checkbox]:checked + label:before {
background: $color-green;
}
.container {
margin: 0 auto;
max-width: 600px;
padding: 10px;
position: relative;
}
.container--offset {
margin-left: 0;
}
button {
background: $color-text;
border: 10px solid $color-green;
cursor: pointer;
display: block;
font-family: monospace;
font-size: 24px;
height: 80px;
line-height: 60px;
margin: 0;
outline: none;
padding: 0 1.2em;
text-align: right;
&:hover {
background: $color-green;
}
&#deleteme {
margin: 2rem;
}
}
.scene {
margin: 0;
padding: 0;
button {
left: 10%;
top: 260px;
width: 80%;
position: absolute;
}
}
.fill {
bottom: 5%;
left: 5%;
position: absolute;
right: 5%;
top: 5%;
}
.expand-width {
width: 100%;
}
.border {
border: 2px dashed $color-green;
}
.aspect {
opacity: 0.2;
}
@for $i from 1 through 6 {
.scene > *:nth-child(#{$i}) {
opacity: #{0.15 * $i};
button {
transform: rotate(#{180 - 30 * $i}deg)
}
}
}
================================================
FILE: examples/pages/callback.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Callback Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<div id="scene" class="scene">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
function myAwesomeCallback() {
alert('Parallax is ready to go now!');
}
// the onReady function is called as soon as Parallax knows what input method to use. This might take up to 1000ms (supportDelay * 2) after initialisation
var scene = document.getElementById('scene');
var parallax = new Parallax(scene, {
onReady: myAwesomeCallback
});
</script>
</body>
</html>
================================================
FILE: examples/pages/destroy.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Instance Destruction Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<button id="deleteme">Delete me!</button>
<div id="container" class="container">
<div id="scene" class="scene">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
document.getElementById('deleteme').onclick = function() {
parallax.destroy();
parallax = null;
this.onclick = null;
this.style.display = 'none';
};
</script>
</body>
</html>
================================================
FILE: examples/pages/hoveronly.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Hover Only Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<div id="scene" data-hover-only="true" data-relative-input="true" class="scene border">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
</script>
</body>
</html>
================================================
FILE: examples/pages/input_element.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Input Element Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div class="container" style="float:left">
<div id="scene" class="scene border" data-input-element="#scene-input">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
</div>
<div class="container" style="float:right">
<div id="scene-input" class="scene border">
<div><img src="images/layer6.png"></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
// Elements
var scene = document.getElementById('scene');
var input = document.getElementById('scene-input');
// Pretty simple huh?
var parallax = new Parallax(scene, {
hoverOnly: true,
relativeInput: true,
inputElement: input
});
</script>
</body>
</html>
================================================
FILE: examples/pages/interactive.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Interactive Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<img class="aspect" src="images/layer2.png">
<div id="scene" class="scene border fill" data-pointer-events="true">
<div class="expand-width" data-depth="1.00"><button>layer[6]</button></div>
<div class="expand-width" data-depth="0.80"><button>layer[5]</button></div>
<div class="expand-width" data-depth="0.60"><button>layer[4]</button></div>
<div class="expand-width" data-depth="0.40"><button>layer[3]</button></div>
<div class="expand-width" data-depth="0.20"><button>layer[2]</button></div>
<div class="expand-width" data-depth="0.00"><button>layer[1]</button></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
// Nothing new here...it's all in the CSS!
// And don't forget to activate the pointerEvents option
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
</script>
</body>
</html>
================================================
FILE: examples/pages/relative.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Relative Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container container--offset">
<div id="scene" class="scene border">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
<br>
<input type="checkbox" id="relative" checked>
<label for="relative">relativeInput</label>
<input type="checkbox" id="clip">
<label for="clip">clipRelativeInput</label>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
// Elements
var scene = document.getElementById('scene');
var clipCheckbox = document.getElementById('clip');
var relativeCheckbox = document.getElementById('relative');
// Pretty simple huh?
var parallax = new Parallax(scene, {
relativeInput: relativeCheckbox.checked,
clipRelativeInput: clipCheckbox.checked
});
relativeCheckbox.addEventListener('change', function(event) {
parallax.relativeInput = relativeCheckbox.checked;
});
clipCheckbox.addEventListener('change', function(event) {
parallax.clipRelativeInput = clipCheckbox.checked;
});
</script>
</body>
</html>
================================================
FILE: examples/pages/selector.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Selector Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<div id="scene" class="scene">
<div class="layer" data-depth="1.00"><img src="images/layer1.png"></div>
<div class="layer" data-depth="0.80"><img src="images/layer4.png"></div>
<div class="layer" data-depth="0.60"><img src="images/layer6.png"></div>
<div data-depth="0.40">I am not a Parallax Layer</div>
<div data-depth="0.20">I am not a Parallax Layer</div>
<div data-depth="0.00">I am not a Parallax Layer</div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
var scene = document.getElementById('scene');
var parallax = new Parallax(scene, {
selector: '.layer'
});
</script>
</body>
</html>
================================================
FILE: examples/pages/separate_axis_data.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Separate Axis Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<div id="scene" class="scene">
<div data-depth="1.00">
<img src="images/layer1.png">
</div>
<div data-depth-x="0.80" data-depth-y="-0.80">
<img src="images/layer2.png">
</div>
<div data-depth-x="-0.60" data-depth-y="-0.20">
<img src="images/layer3.png">
</div>
<div data-depth="0.40" data-depth-y="-0.30">
<img src="images/layer4.png">
</div>
<div data-depth="0.20">
<img src="images/layer5.png">
</div>
<div data-depth="0.00">
<img src="images/layer6.png">
</div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
// Pretty simple huh?
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
</script>
</body>
</html>
================================================
FILE: examples/pages/simple.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Parallax.js | Simple Example</title>
<!-- Behavioral Meta Data -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<div id="container" class="container">
<div id="scene" class="scene">
<div data-depth="1.00"><img src="images/layer1.png"></div>
<div data-depth="0.80"><img src="images/layer2.png"></div>
<div data-depth="0.60"><img src="images/layer3.png"></div>
<div data-depth="0.40"><img src="images/layer4.png"></div>
<div data-depth="0.20"><img src="images/layer5.png"></div>
<div data-depth="0.00"><img src="images/layer6.png"></div>
</div>
</div>
<!-- Scripts -->
<script src="./parallax.js"></script>
<script>
// Pretty simple huh?
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
</script>
</body>
</html>
================================================
FILE: gulpfile.js
================================================
const gulp = require('gulp')
const path = require('path')
const autoprefixer = require('autoprefixer')
const babelify = require('babelify')
const browserify = require('browserify')
const browsersync = require('browser-sync').create()
const buffer = require('vinyl-buffer')
const notifier = require('node-notifier')
const postcss = require('gulp-postcss')
const rename = require('gulp-rename');
const rimraf = require('rimraf')
const sass = require('gulp-sass')
const source = require('vinyl-source-stream')
const sourcemaps = require('gulp-sourcemaps')
const uglify = require('gulp-uglify')
const util = require('gulp-util')
gulp.task('clean', (cb) => {
rimraf('./dist', cb)
})
gulp.task('build', ['clean'], () => {
gulp.start('build:js', 'build:scss')
})
function showError(arg) {
notifier.notify({
title: 'Error',
message: '' + arg,
sound: 'Basso'
})
console.log(arg)
this.emit('end')
}
gulp.task('build:scss', () => {
return gulp.src(path.join('examples', 'assets', 'styles.scss'))
.pipe(sass({
outputStyle: 'nested',
precision: 10,
includePaths: ['.', 'node_modules'],
onError: showError
}).on('error', function(error) {
showError(error)
this.emit('end')
}))
.pipe(postcss([
autoprefixer({
browsers: ['last 2 versions', 'Firefox ESR', 'Explorer >= 9', 'Android >= 4.0', '> 2%']
})
]))
.pipe(gulp.dest(path.join('examples', 'assets')))
.pipe(browsersync.stream({match: '**/*.css'}))
})
gulp.task('build:js', () => {
return browserify({entries: path.join('src', 'parallax.js'), debug: false, standalone: 'Parallax'})
.transform("babelify", {presets: ["es2015"]})
.bundle()
.on('error', showError)
.pipe(source('parallax.js'))
.pipe(buffer())
.pipe(gulp.dest('dist'))
.pipe(rename('parallax.min.js'))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.on('error', showError)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'))
.pipe(browsersync.stream({match: path.join('**','*.js')}))
})
gulp.task('watch', ['build'], () => {
browsersync.init({
notify: false,
port: 9000,
server: {
baseDir: [path.join('examples', 'pages'), path.join('examples', 'assets'), 'dist'],
directory: true
}
})
gulp.watch(path.join('src', '*.js'), ['build:js'])
gulp.watch(path.join('examples', 'assets', '*.scss'), ['build:scss'])
gulp.watch(path.join('examples', 'pages', '*.html'), browsersync.reload)
})
gulp.task('default', ['watch'])
================================================
FILE: package.json
================================================
{
"name": "parallax-js",
"description": "Parallax Engine that reacts to the orientation of a smart device.",
"version": "3.1.0",
"license": "MIT",
"main": "dist/parallax.js",
"homepage": "http://wagerfield.github.io/parallax/",
"author": "Matthew Wagerfield <matthew@wagerfield.com>, René Roth <mail@reneroth.org>",
"directories": {
"example": "examples"
},
"scripts": {},
"repository": {
"type": "git",
"url": "git://github.com/wagerfield/parallax.git"
},
"keywords": [
"parallax",
"gyroscope",
"jquery",
"javascript",
"library"
],
"bugs": {
"url": "https://github.com/wagerfield/parallax/issues"
},
"devDependencies": {
"autoprefixer": "^7.1.4",
"babel-preset-es2015": "^6.24.1",
"babelify": "^7.3.0",
"browser-sync": "^2.18.13",
"browserify": "^14.0.0",
"gulp": "^3.9.1",
"gulp-postcss": "^7.0.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^3.1.0",
"gulp-sourcemaps": "^2.6.1",
"gulp-uglify": "^3.0.0",
"gulp-util": "^3.0.8",
"node-notifier": "^5.0.2",
"rimraf": "^2.5.4",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
},
"dependencies": {
"object-assign": "^4.1.1",
"raf": "^3.3.0"
}
}
================================================
FILE: src/parallax.js
================================================
/**
* Parallax.js
* @author Matthew Wagerfield - @wagerfield, René Roth - mail@reneroth.org
* @description Creates a parallax effect between an array of layers,
* driving the motion from the gyroscope output of a smartdevice.
* If no gyroscope is available, the cursor position is used.
*/
const rqAnFr = require('raf')
const objectAssign = require('object-assign')
const helpers = {
propertyCache: {},
vendors: [null, ['-webkit-','webkit'], ['-moz-','Moz'], ['-o-','O'], ['-ms-','ms']],
clamp(value, min, max) {
return min < max
? (value < min ? min : value > max ? max : value)
: (value < max ? max : value > min ? min : value)
},
data(element, name) {
return helpers.deserialize(element.getAttribute('data-'+name))
},
deserialize(value) {
if (value === 'true') {
return true
} else if (value === 'false') {
return false
} else if (value === 'null') {
return null
} else if (!isNaN(parseFloat(value)) && isFinite(value)) {
return parseFloat(value)
} else {
return value
}
},
camelCase(value) {
return value.replace(/-+(.)?/g, (match, character) => {
return character ? character.toUpperCase() : ''
})
},
accelerate(element) {
helpers.css(element, 'transform', 'translate3d(0,0,0) rotate(0.0001deg)')
helpers.css(element, 'transform-style', 'preserve-3d')
helpers.css(element, 'backface-visibility', 'hidden')
},
transformSupport(value) {
let element = document.createElement('div'),
propertySupport = false,
propertyValue = null,
featureSupport = false,
cssProperty = null,
jsProperty = null
for (let i = 0, l = helpers.vendors.length; i < l; i++) {
if (helpers.vendors[i] !== null) {
cssProperty = helpers.vendors[i][0] + 'transform'
jsProperty = helpers.vendors[i][1] + 'Transform'
} else {
cssProperty = 'transform'
jsProperty = 'transform'
}
if (element.style[jsProperty] !== undefined) {
propertySupport = true
break
}
}
switch(value) {
case '2D':
featureSupport = propertySupport
break
case '3D':
if (propertySupport) {
let body = document.body || document.createElement('body'),
documentElement = document.documentElement,
documentOverflow = documentElement.style.overflow,
isCreatedBody = false
if (!document.body) {
isCreatedBody = true
documentElement.style.overflow = 'hidden'
documentElement.appendChild(body)
body.style.overflow = 'hidden'
body.style.background = ''
}
body.appendChild(element)
element.style[jsProperty] = 'translate3d(1px,1px,1px)'
propertyValue = window.getComputedStyle(element).getPropertyValue(cssProperty)
featureSupport = propertyValue !== undefined && propertyValue.length > 0 && propertyValue !== 'none'
documentElement.style.overflow = documentOverflow
body.removeChild(element)
if ( isCreatedBody ) {
body.removeAttribute('style')
body.parentNode.removeChild(body)
}
}
break
}
return featureSupport
},
css(element, property, value) {
let jsProperty = helpers.propertyCache[property]
if (!jsProperty) {
for (let i = 0, l = helpers.vendors.length; i < l; i++) {
if (helpers.vendors[i] !== null) {
jsProperty = helpers.camelCase(helpers.vendors[i][1] + '-' + property)
} else {
jsProperty = property
}
if (element.style[jsProperty] !== undefined) {
helpers.propertyCache[property] = jsProperty
break
}
}
}
element.style[jsProperty] = value
}
}
const MAGIC_NUMBER = 30,
DEFAULTS = {
relativeInput: false,
clipRelativeInput: false,
inputElement: null,
hoverOnly: false,
calibrationThreshold: 100,
calibrationDelay: 500,
supportDelay: 500,
calibrateX: false,
calibrateY: true,
invertX: true,
invertY: true,
limitX: false,
limitY: false,
scalarX: 10.0,
scalarY: 10.0,
frictionX: 0.1,
frictionY: 0.1,
originX: 0.5,
originY: 0.5,
pointerEvents: false,
precision: 1,
onReady: null,
selector: null
}
class Parallax {
constructor(element, options) {
this.element = element
const data = {
calibrateX: helpers.data(this.element, 'calibrate-x'),
calibrateY: helpers.data(this.element, 'calibrate-y'),
invertX: helpers.data(this.element, 'invert-x'),
invertY: helpers.data(this.element, 'invert-y'),
limitX: helpers.data(this.element, 'limit-x'),
limitY: helpers.data(this.element, 'limit-y'),
scalarX: helpers.data(this.element, 'scalar-x'),
scalarY: helpers.data(this.element, 'scalar-y'),
frictionX: helpers.data(this.element, 'friction-x'),
frictionY: helpers.data(this.element, 'friction-y'),
originX: helpers.data(this.element, 'origin-x'),
originY: helpers.data(this.element, 'origin-y'),
pointerEvents: helpers.data(this.element, 'pointer-events'),
precision: helpers.data(this.element, 'precision'),
relativeInput: helpers.data(this.element, 'relative-input'),
clipRelativeInput: helpers.data(this.element, 'clip-relative-input'),
hoverOnly: helpers.data(this.element, 'hover-only'),
inputElement: document.querySelector(helpers.data(this.element, 'input-element')),
selector: helpers.data(this.element, 'selector')
}
for (let key in data) {
if (data[key] === null) {
delete data[key]
}
}
objectAssign(this, DEFAULTS, data, options)
if(!this.inputElement) {
this.inputElement = this.element
}
this.calibrationTimer = null
this.calibrationFlag = true
this.enabled = false
this.depthsX = []
this.depthsY = []
this.raf = null
this.bounds = null
this.elementPositionX = 0
this.elementPositionY = 0
this.elementWidth = 0
this.elementHeight = 0
this.elementCenterX = 0
this.elementCenterY = 0
this.elementRangeX = 0
this.elementRangeY = 0
this.calibrationX = 0
this.calibrationY = 0
this.inputX = 0
this.inputY = 0
this.motionX = 0
this.motionY = 0
this.velocityX = 0
this.velocityY = 0
this.onMouseMove = this.onMouseMove.bind(this)
this.onDeviceOrientation = this.onDeviceOrientation.bind(this)
this.onDeviceMotion = this.onDeviceMotion.bind(this)
this.onOrientationTimer = this.onOrientationTimer.bind(this)
this.onMotionTimer = this.onMotionTimer.bind(this)
this.onCalibrationTimer = this.onCalibrationTimer.bind(this)
this.onAnimationFrame = this.onAnimationFrame.bind(this)
this.onWindowResize = this.onWindowResize.bind(this)
this.windowWidth = null
this.windowHeight = null
this.windowCenterX = null
this.windowCenterY = null
this.windowRadiusX = null
this.windowRadiusY = null
this.portrait = false
this.desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i)
this.motionSupport = !!window.DeviceMotionEvent && !this.desktop
this.orientationSupport = !!window.DeviceOrientationEvent && !this.desktop
this.orientationStatus = 0
this.motionStatus = 0
this.initialise()
}
initialise() {
if (this.transform2DSupport === undefined) {
this.transform2DSupport = helpers.transformSupport('2D')
this.transform3DSupport = helpers.transformSupport('3D')
}
// Configure Context Styles
if (this.transform3DSupport) {
helpers.accelerate(this.element)
}
let style = window.getComputedStyle(this.element)
if (style.getPropertyValue('position') === 'static') {
this.element.style.position = 'relative'
}
// Pointer events
if(!this.pointerEvents) {
this.element.style.pointerEvents = 'none'
}
// Setup
this.updateLayers()
this.updateDimensions()
this.enable()
this.queueCalibration(this.calibrationDelay)
}
doReadyCallback() {
if(this.onReady) {
this.onReady()
}
}
updateLayers() {
if(this.selector) {
this.layers = this.element.querySelectorAll(this.selector)
} else {
this.layers = this.element.children
}
if(!this.layers.length) {
console.warn('ParallaxJS: Your scene does not have any layers.')
}
this.depthsX = []
this.depthsY = []
for (let index = 0; index < this.layers.length; index++) {
let layer = this.layers[index]
if (this.transform3DSupport) {
helpers.accelerate(layer)
}
layer.style.position = index ? 'absolute' : 'relative'
layer.style.display = 'block'
layer.style.left = 0
layer.style.top = 0
let depth = helpers.data(layer, 'depth') || 0
this.depthsX.push(helpers.data(layer, 'depth-x') || depth)
this.depthsY.push(helpers.data(layer, 'depth-y') || depth)
}
}
updateDimensions() {
this.windowWidth = window.innerWidth
this.windowHeight = window.innerHeight
this.windowCenterX = this.windowWidth * this.originX
this.windowCenterY = this.windowHeight * this.originY
this.windowRadiusX = Math.max(this.windowCenterX, this.windowWidth - this.windowCenterX)
this.windowRadiusY = Math.max(this.windowCenterY, this.windowHeight - this.windowCenterY)
}
updateBounds() {
this.bounds = this.inputElement.getBoundingClientRect()
this.elementPositionX = this.bounds.left
this.elementPositionY = this.bounds.top
this.elementWidth = this.bounds.width
this.elementHeight = this.bounds.height
this.elementCenterX = this.elementWidth * this.originX
this.elementCenterY = this.elementHeight * this.originY
this.elementRangeX = Math.max(this.elementCenterX, this.elementWidth - this.elementCenterX)
this.elementRangeY = Math.max(this.elementCenterY, this.elementHeight - this.elementCenterY)
}
queueCalibration(delay) {
clearTimeout(this.calibrationTimer)
this.calibrationTimer = setTimeout(this.onCalibrationTimer, delay)
}
enable() {
if (this.enabled) {
return
}
this.enabled = true
if (this.orientationSupport) {
this.portrait = false
window.addEventListener('deviceorientation', this.onDeviceOrientation)
this.detectionTimer = setTimeout(this.onOrientationTimer, this.supportDelay)
} else if (this.motionSupport) {
this.portrait = false
window.addEventListener('devicemotion', this.onDeviceMotion)
this.detectionTimer = setTimeout(this.onMotionTimer, this.supportDelay)
} else {
this.calibrationX = 0
this.calibrationY = 0
this.portrait = false
window.addEventListener('mousemove', this.onMouseMove)
this.doReadyCallback()
}
window.addEventListener('resize', this.onWindowResize)
this.raf = rqAnFr(this.onAnimationFrame)
}
disable() {
if (!this.enabled) {
return
}
this.enabled = false
if (this.orientationSupport) {
window.removeEventListener('deviceorientation', this.onDeviceOrientation)
} else if (this.motionSupport) {
window.removeEventListener('devicemotion', this.onDeviceMotion)
} else {
window.removeEventListener('mousemove', this.onMouseMove)
}
window.removeEventListener('resize', this.onWindowResize)
rqAnFr.cancel(this.raf)
}
calibrate(x, y) {
this.calibrateX = x === undefined ? this.calibrateX : x
this.calibrateY = y === undefined ? this.calibrateY : y
}
invert(x, y) {
this.invertX = x === undefined ? this.invertX : x
this.invertY = y === undefined ? this.invertY : y
}
friction(x, y) {
this.frictionX = x === undefined ? this.frictionX : x
this.frictionY = y === undefined ? this.frictionY : y
}
scalar(x, y) {
this.scalarX = x === undefined ? this.scalarX : x
this.scalarY = y === undefined ? this.scalarY : y
}
limit(x, y) {
this.limitX = x === undefined ? this.limitX : x
this.limitY = y === undefined ? this.limitY : y
}
origin(x, y) {
this.originX = x === undefined ? this.originX : x
this.originY = y === undefined ? this.originY : y
}
setInputElement(element) {
this.inputElement = element
this.updateDimensions()
}
setPosition(element, x, y) {
x = x.toFixed(this.precision) + 'px'
y = y.toFixed(this.precision) + 'px'
if (this.transform3DSupport) {
helpers.css(element, 'transform', 'translate3d(' + x + ',' + y + ',0)')
} else if (this.transform2DSupport) {
helpers.css(element, 'transform', 'translate(' + x + ',' + y + ')')
} else {
element.style.left = x
element.style.top = y
}
}
onOrientationTimer() {
if (this.orientationSupport && this.orientationStatus === 0) {
this.disable()
this.orientationSupport = false
this.enable()
} else {
this.doReadyCallback()
}
}
onMotionTimer() {
if (this.motionSupport && this.motionStatus === 0) {
this.disable()
this.motionSupport = false
this.enable()
} else {
this.doReadyCallback()
}
}
onCalibrationTimer() {
this.calibrationFlag = true
}
onWindowResize() {
this.updateDimensions()
}
onAnimationFrame() {
this.updateBounds()
let calibratedInputX = this.inputX - this.calibrationX,
calibratedInputY = this.inputY - this.calibrationY
if ((Math.abs(calibratedInputX) > this.calibrationThreshold) || (Math.abs(calibratedInputY) > this.calibrationThreshold)) {
this.queueCalibration(0)
}
if (this.portrait) {
this.motionX = this.calibrateX ? calibratedInputY : this.inputY
this.motionY = this.calibrateY ? calibratedInputX : this.inputX
} else {
this.motionX = this.calibrateX ? calibratedInputX : this.inputX
this.motionY = this.calibrateY ? calibratedInputY : this.inputY
}
this.motionX *= this.elementWidth * (this.scalarX / 100)
this.motionY *= this.elementHeight * (this.scalarY / 100)
if (!isNaN(parseFloat(this.limitX))) {
this.motionX = helpers.clamp(this.motionX, -this.limitX, this.limitX)
}
if (!isNaN(parseFloat(this.limitY))) {
this.motionY = helpers.clamp(this.motionY, -this.limitY, this.limitY)
}
this.velocityX += (this.motionX - this.velocityX) * this.frictionX
this.velocityY += (this.motionY - this.velocityY) * this.frictionY
for (let index = 0; index < this.layers.length; index++) {
let layer = this.layers[index],
depthX = this.depthsX[index],
depthY = this.depthsY[index],
xOffset = this.velocityX * (depthX * (this.invertX ? -1 : 1)),
yOffset = this.velocityY * (depthY * (this.invertY ? -1 : 1))
this.setPosition(layer, xOffset, yOffset)
}
this.raf = rqAnFr(this.onAnimationFrame)
}
rotate(beta, gamma){
// Extract Rotation
let x = (beta || 0) / MAGIC_NUMBER, // -90 :: 90
y = (gamma || 0) / MAGIC_NUMBER // -180 :: 180
// Detect Orientation Change
let portrait = this.windowHeight > this.windowWidth
if (this.portrait !== portrait) {
this.portrait = portrait
this.calibrationFlag = true
}
if (this.calibrationFlag) {
this.calibrationFlag = false
this.calibrationX = x
this.calibrationY = y
}
this.inputX = x
this.inputY = y
}
onDeviceOrientation(event) {
let beta = event.beta
let gamma = event.gamma
if (beta !== null && gamma !== null) {
this.orientationStatus = 1
this.rotate(beta, gamma)
}
}
onDeviceMotion(event) {
let beta = event.rotationRate.beta
let gamma = event.rotationRate.gamma
if (beta !== null && gamma !== null) {
this.motionStatus = 1
this.rotate(beta, gamma)
}
}
onMouseMove(event) {
let clientX = event.clientX,
clientY = event.clientY
// reset input to center if hoverOnly is set and we're not hovering the element
if(this.hoverOnly &&
((clientX < this.elementPositionX || clientX > this.elementPositionX + this.elementWidth) ||
(clientY < this.elementPositionY || clientY > this.elementPositionY + this.elementHeight))) {
this.inputX = 0
this.inputY = 0
return
}
if (this.relativeInput) {
// Clip mouse coordinates inside element bounds.
if (this.clipRelativeInput) {
clientX = Math.max(clientX, this.elementPositionX)
clientX = Math.min(clientX, this.elementPositionX + this.elementWidth)
clientY = Math.max(clientY, this.elementPositionY)
clientY = Math.min(clientY, this.elementPositionY + this.elementHeight)
}
// Calculate input relative to the element.
if(this.elementRangeX && this.elementRangeY) {
this.inputX = (clientX - this.elementPositionX - this.elementCenterX) / this.elementRangeX
this.inputY = (clientY - this.elementPositionY - this.elementCenterY) / this.elementRangeY
}
} else {
// Calculate input relative to the window.
if(this.windowRadiusX && this.windowRadiusY) {
this.inputX = (clientX - this.windowCenterX) / this.windowRadiusX
this.inputY = (clientY - this.windowCenterY) / this.windowRadiusY
}
}
}
destroy() {
this.disable()
clearTimeout(this.calibrationTimer)
clearTimeout(this.detectionTimer)
this.element.removeAttribute('style')
for (let index = 0; index < this.layers.length; index++) {
this.layers[index].removeAttribute('style')
}
delete this.element
delete this.layers
}
version() {
return '3.1.0'
}
}
module.exports = Parallax
gitextract_9v95jqid/
├── .gitignore
├── .npmignore
├── .nvmrc
├── LICENSE
├── README.md
├── examples/
│ ├── assets/
│ │ └── styles.scss
│ └── pages/
│ ├── callback.html
│ ├── destroy.html
│ ├── hoveronly.html
│ ├── input_element.html
│ ├── interactive.html
│ ├── relative.html
│ ├── selector.html
│ ├── separate_axis_data.html
│ └── simple.html
├── gulpfile.js
├── package.json
└── src/
└── parallax.js
SYMBOL INDEX (39 symbols across 2 files)
FILE: gulpfile.js
function showError (line 27) | function showError(arg) {
FILE: src/parallax.js
method clamp (line 16) | clamp(value, min, max) {
method data (line 22) | data(element, name) {
method deserialize (line 26) | deserialize(value) {
method camelCase (line 40) | camelCase(value) {
method accelerate (line 46) | accelerate(element) {
method transformSupport (line 52) | transformSupport(value) {
method css (line 108) | css(element, property, value) {
constant MAGIC_NUMBER (line 128) | const MAGIC_NUMBER = 30,
constant DEFAULTS (line 128) | const MAGIC_NUMBER = 30,
class Parallax (line 155) | class Parallax {
method constructor (line 156) | constructor(element, options) {
method initialise (line 250) | initialise() {
method doReadyCallback (line 278) | doReadyCallback() {
method updateLayers (line 284) | updateLayers() {
method updateDimensions (line 316) | updateDimensions() {
method updateBounds (line 325) | updateBounds() {
method queueCalibration (line 337) | queueCalibration(delay) {
method enable (line 342) | enable() {
method disable (line 368) | disable() {
method calibrate (line 386) | calibrate(x, y) {
method invert (line 391) | invert(x, y) {
method friction (line 396) | friction(x, y) {
method scalar (line 401) | scalar(x, y) {
method limit (line 406) | limit(x, y) {
method origin (line 411) | origin(x, y) {
method setInputElement (line 416) | setInputElement(element) {
method setPosition (line 421) | setPosition(element, x, y) {
method onOrientationTimer (line 434) | onOrientationTimer() {
method onMotionTimer (line 444) | onMotionTimer() {
method onCalibrationTimer (line 454) | onCalibrationTimer() {
method onWindowResize (line 458) | onWindowResize() {
method onAnimationFrame (line 462) | onAnimationFrame() {
method rotate (line 497) | rotate(beta, gamma){
method onDeviceOrientation (line 519) | onDeviceOrientation(event) {
method onDeviceMotion (line 528) | onDeviceMotion(event) {
method onMouseMove (line 537) | onMouseMove(event) {
method destroy (line 572) | destroy() {
method version (line 587) | version() {
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (53K chars).
[
{
"path": ".gitignore",
"chars": 52,
"preview": "*.DS_Store\nnode_modules\ndist\n**/*.css\nnpm-debug.log\n"
},
{
"path": ".npmignore",
"chars": 18,
"preview": "examples\nlogo.png\n"
},
{
"path": ".nvmrc",
"chars": 2,
"preview": "8\n"
},
{
"path": "LICENSE",
"chars": 1299,
"preview": "//============================================================\n//\n// The MIT License\n//\n// Copyright (C) 2014 Matthew Wa"
},
{
"path": "README.md",
"chars": 12610,
"preview": "\n\n[](https://cdnjs.com/libraries/parallax)\n"
},
{
"path": "examples/assets/styles.scss",
"chars": 1605,
"preview": "$color-green: #00ffaa;\n$color-background: #111;\n$color-text: #555;\n\n\nbody {\n background: $color-background;\n color: $c"
},
{
"path": "examples/pages/callback.html",
"chars": 1305,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Callback Example</title>\n\n\t<!-- Behavioral"
},
{
"path": "examples/pages/destroy.html",
"chars": 1254,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Instance Destruction Example</title>\n\n\t<!-"
},
{
"path": "examples/pages/hoveronly.html",
"chars": 1096,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Hover Only Example</title>\n\n\t<!-- Behavior"
},
{
"path": "examples/pages/input_element.html",
"chars": 1457,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n <meta charset=\"utf-8\">\n\n <title>Parallax.js | Input Element Example</title>\n\n <!-- Be"
},
{
"path": "examples/pages/interactive.html",
"chars": 1371,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n <meta charset=\"utf-8\">\n\n <title>Parallax.js | Interactive Example</title>\n\n <!-- Beha"
},
{
"path": "examples/pages/relative.html",
"chars": 1791,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n <meta charset=\"utf-8\">\n\n <title>Parallax.js | Relative Example</title>\n\n <!-- Behavio"
},
{
"path": "examples/pages/selector.html",
"chars": 1097,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Selector Example</title>\n\n\t<!-- Behavioral"
},
{
"path": "examples/pages/separate_axis_data.html",
"chars": 1187,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Separate Axis Example</title>\n\n\t<!-- Behav"
},
{
"path": "examples/pages/simple.html",
"chars": 1058,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\n\t<meta charset=\"utf-8\">\n\n\t<title>Parallax.js | Simple Example</title>\n\n\t<!-- Behavioral M"
},
{
"path": "gulpfile.js",
"chars": 2597,
"preview": "const gulp = require('gulp')\nconst path = require('path')\n\nconst autoprefixer = require('autoprefixer')\nconst babelify ="
},
{
"path": "package.json",
"chars": 1247,
"preview": "{\n \"name\": \"parallax-js\",\n \"description\": \"Parallax Engine that reacts to the orientation of a smart device.\",\n \"vers"
},
{
"path": "src/parallax.js",
"chars": 17996,
"preview": "/**\n* Parallax.js\n* @author Matthew Wagerfield - @wagerfield, René Roth - mail@reneroth.org\n* @description Creates a par"
}
]
About this extraction
This page contains the full source code of the wagerfield/parallax GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 18 files (47.9 KB), approximately 13.4k tokens, and a symbol index with 39 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.