61 Commits
v1.0 ... v1.2.0

Author SHA1 Message Date
Alex Fox
877bb3ec1a Update README.md 2019-03-26 08:51:01 +00:00
Alex Fox
b7d32ace26 Update README.md 2019-03-26 08:49:30 +00:00
Alex Fox
3813e8d486 Merge pull request #30 from alexfoxy/dev
Merge 1.2 dev to master
2019-03-26 08:48:40 +00:00
Alex Fox
b4cfc8d6b4 tweaked backface visibility 2019-03-26 08:47:24 +00:00
Alex Fox
f2d3dc0977 readme tweak 2019-03-26 08:40:51 +00:00
Alex Fox
a9a5d6a216 Merge branch 'dev' of https://github.com/alexfoxy/laxx into dev 2019-03-26 08:39:39 +00:00
Alex Fox
f035230a56 tweak readme 2019-03-26 08:39:37 +00:00
Alex Fox
fddfeaabeb Update README.md 2019-03-26 08:38:37 +00:00
Alex Fox
51dac49553 rc for 1.2 2019-03-26 08:17:49 +00:00
Alex Fox
eb0a1b4230 Merge branch 'spriteanimation' into responsive 2019-03-26 08:16:39 +00:00
Alex Fox
7965234d87 sprite sheet and other changes 2019-03-26 08:16:21 +00:00
Alex Fox
278168414b x 2019-03-23 16:34:46 +00:00
Alex Fox
25ac2b5497 added sprite sheet animation 2019-03-23 16:31:25 +00:00
Alex Fox
9c9038a3ea merged master 2019-03-23 13:24:02 +00:00
Alex Fox
bb6133ea2b Merge pull request #24 from alexfoxy/revert-23-feature-this-bugs
Revert "fix "this" bugs"
2019-03-23 13:10:58 +00:00
Alex Fox
0d36e901d7 Revert "fix "this" bugs" 2019-03-23 13:10:36 +00:00
Alex Fox
49c45d8e4f changed breakpoint seperator and fixed demo 2019-03-23 10:28:43 +00:00
Alex Fox
1247463303 Merge branch 'responsive' of https://github.com/alexfoxy/laxx into responsive 2019-03-23 10:09:15 +00:00
Alex Fox
a587813c1e x 2019-03-23 10:09:12 +00:00
Alex Fox
08dd1ceb6e Merge pull request #23 from flycsqaq/feature-this-bugs
fix "this" bugs
2019-03-23 10:07:44 +00:00
Alex Fox
f9074ee5e6 Merge pull request #17 from afanjul/responsive
Using a class for identify lax elements, and using mobile-first breakpoints
2019-03-23 10:06:42 +00:00
zhoufeiyu
8684fb8ee3 fix this bugs 2019-03-23 13:51:48 +08:00
Alejandro Fanjul
9589627ed7 Using "--" as default separator for breakpoints, but the user could change it for "." or "_", etc.
Fixed some coding regarding finding "presets" to avoid looping multiple times. Now we just discover the presets attribute and traverse in another loop.
  -In the original loop (through attributes), if a preset add another attributes (ie. data-lax-translate-x) the added attributes get traverse in the loop... (as part of the elements attributes).
2019-03-22 17:57:11 +01:00
Alejandro Fanjul
692ff93731 Fixed possible namespace problems using ':' for breakpoints, better to stick to '#' it seems safe to use 2019-03-22 14:04:58 +01:00
Alejandro Fanjul
cf77d95f0e Merge remote-tracking branch 'upstream/responsive' into responsive
Conflicts:
	src/lax.js
2019-03-22 13:59:27 +01:00
Alejandro Fanjul
1dd3bebbdd Using a class for identify lax elements, by default ".lax", but the user could define custom one in options
Using breakpoints with "mobile-first" approach as latest css frameworks does (ie. bootstrap 4, semantic-ui, etc.)
2019-03-22 13:48:41 +01:00
Alex Fox
33bd72d825 tweak to lax update functio 2019-03-22 12:48:06 +00:00
Alex Fox
b461e7b1cf fixes and added support for responsive presets 2019-03-22 12:37:43 +00:00
Alex Fox
fee90b3a82 added error for no default setting 2019-03-22 08:38:23 +00:00
Alex Fox
7431ff3840 added support for screen size breakpoints 2019-03-22 08:27:13 +00:00
Alex Fox
07899d3443 Merge branch 'master' into dev 2019-03-20 17:37:45 +00:00
Alex Fox
b99389f388 Update index.html 2019-03-20 10:36:10 +00:00
Alex Fox
027772e364 Merge branch 'dev' 2019-03-19 15:36:26 +00:00
Alex Fox
802fa7592c added optmize, new presets, background position 2019-03-19 15:36:02 +00:00
Alex Fox
f9395c6c27 Merge branch 'master' into dev 2019-03-19 07:05:54 +00:00
Alex Fox
e8b68c246a Merge branch 'master' of https://github.com/alexfoxy/laxx 2019-03-18 17:04:07 +00:00
Alex Fox
e2a30f53b5 improved demo performance 2019-03-18 17:03:34 +00:00
Alex Fox
c96ff53460 Update README.md 2019-03-18 16:44:40 +00:00
Alex Fox
9790b42b2e changes to make usage with react and vue easier 2019-03-18 16:44:08 +00:00
Alex Fox
25d890421b Merge branch 'master' of https://github.com/alexfoxy/laxx 2019-03-17 11:46:32 +00:00
Alex Fox
842b7d40d6 added populateElements function to call when dom is updated 2019-03-17 11:46:25 +00:00
Alex Fox
4657e7adff Update README.md 2019-03-17 10:51:07 +00:00
Alex Fox
d768100817 Update README.md 2019-03-17 10:49:44 +00:00
Alex Fox
d274614a28 Create LICENSE 2019-03-17 10:42:33 +00:00
Alex Fox
298f29e188 Merge branch 'master' of https://github.com/alexfoxy/laxx 2019-03-17 10:15:20 +00:00
Alex Fox
4791239fd3 tweaked css in demo 2019-03-17 10:15:13 +00:00
Alex Fox
793a9bb36e Merge pull request #4 from 0xflotus/patch-1
fixed implement dependency
2019-03-16 17:36:48 +00:00
0xflotus
afe3114f9b fixed implement dependency 2019-03-16 17:53:40 +01:00
Alex Fox
08e3719a29 Merge pull request #3 from antonreshetov/pr-npm-install
NPM install
2019-03-16 14:12:08 +00:00
Anton Reshetov
525038a120 docs: add npm install example 2019-03-16 17:03:02 +03:00
Anton Reshetov
486fba4f73 chore: add main script path 2019-03-16 17:02:36 +03:00
Alex Fox
3f5f639a0a moved babel to dev dependancies 2019-03-16 13:48:44 +00:00
Alex Fox
a7d0dc2786 Merge branch 'master' of https://github.com/alexfoxy/laxx 2019-03-16 13:43:45 +00:00
Alex Fox
1cf990e757 tweaks for npm release 2019-03-16 13:43:37 +00:00
Alex Fox
152f4cfea2 tweaks for npm release 2019-03-16 13:43:25 +00:00
Alex Fox
ebebf08233 Added gif to readme 2019-03-16 10:17:03 +00:00
Alex Fox
12fd8e0a95 Merge branch 'master' of https://github.com/alexfoxy/laxx 2019-03-15 10:39:58 +00:00
Alex Fox
a7792fea66 fixed link from demo page 2019-03-15 10:39:54 +00:00
Alex Fox
86741cce86 Update README.md 2019-03-15 10:21:44 +00:00
Alex Fox
2b0aad1eaf Update README.md 2019-03-15 10:11:57 +00:00
Alex Fox
b50e688197 Merge branch 'master' into dev 2019-03-13 15:52:47 +00:00
37 changed files with 1800 additions and 682 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Alex Fox
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.

178
README.md
View File

@@ -1,52 +1,76 @@
# lax.js
Simple & light weight (2kb minified & zipped) vanilla javascript plugin to create beautiful animations when you scrolllll! Harness the power of the most intuitive interaction and make your websites come alive!
Simple & light weight (<3kb gzipped) vanilla javascript plugin to create *smooth* & beautiful animations when you scrolllll! Harness the power of the most intuitive interaction and make your websites come alive!
[>>> DEMO <<<](https://alexfox.dev/lax/)
[>>> DEMO <<<](https://alexfox.dev/laxxx/)
![](https://i.imgur.com/Jbkna80.gif)
## Getting started
[>>> MARIO DEMO <<<](https://alexfox.dev/laxxx/sprite.html)
![](https://i.imgur.com/GGQFucZ.gif)
## Getting Started
### NPM Setup
```bash
npm install lax.js
```
```js
import lax from 'lax.js'
```
### Basic Browser Betup
1) Add lax.js to your html
```html
<script src="lib/lax.min.js" >
```
2) Initialize the plugin
2) Initialize the plugin
```javascript
window.onload = function() {
lax.setup({ /* opts */ }) // init
document.addEventListener('scroll', function(e) {
lax.update(window.scrollY) // update every scroll
}, false)
lax.setup() // init
lax.update(window.scrollY) // set initial positions
const updateLax = () => {
lax.update(window.scrollY)
window.requestAnimationFrame(updateLax)
}
window.requestAnimationFrame(updateLax)
}
```
3) Add attributes to the HTML tags you want to animate e.g.
3) Add class and attributes to the HTML tags you want to animate e.g.
```html
<p data-lax-preset="spin fadeInOut">Look at me goooooo!</p>
<p class="lax" data-lax-preset="spin fadeInOut">Look at me goooooo!</p>
```
4) Scroll and enjoy!
## Presets
### Usage With React, Vue.js & DOM Changes
To increase performance lax.js indexes the list of elements to animate when the page loads. If you're using a library like React or vue.js, it is likely that you are adding elements after the initial `window.onload`. Because of this you will need to call `lax.addElement(domElement)` when you add components to the DOM that you want to animate.
The easiest way to get started is to use the presets via the `data-lax-preset` attribute. You can chain multiple presetes together for e.g. `data-lax-preset="blurOut fadeOut spin"`. Some presets also support an optional strength e.g. `data-lax-preset="blurOut-50"`
See below for working examples:
* [react](https://codepen.io/alexfoxy/pen/PLaKaE)
* [vue](https://codepen.io/alexfoxy/pen/ZPRZBq)
You can also call `lax.removeElement(domElement)` when the component unmounts.
## Presets
The easiest way to get started is to use the presets via the `data-lax-preset` attribute. You can chain multiple presets together for e.g. `data-lax-preset="blurOut fadeOut spin"`. Some presets also support an optional strength e.g. `data-lax-preset="blurOut-50"`.
See the list of [Supported Presets](#supported-presets) for details.
## Custom Animations
You can easily create your own effects. Just add an attribute to your HTML tag (see [Supported Attribute Keys](#supported-attribute-keys)) with an array of values. These arrays take the format of `scrollPos val, scrollPos val, ...` e.g:
You can easily create your own effects. Just add an attribute to your HTML tag (see [Supported Attribute Keys](#supported-attribute-keys)) with an array of values. These arrays take the format of `scrollPos val, scrollPos val, ... | option=val` e.g:
```html
<p data-lax-opacity="0 1, 100 1, 200 0">
<p class="lax" data-lax-opacity="0 1, 100 1, 200 0 | loop=200">
I start to fade out after the window scrolls 100px
and then I'm gone by 200px!
</p>
@@ -54,36 +78,76 @@ You can easily create your own effects. Just add an attribute to your HTML tag (
By default the `scrollPos` is `window.scrollY` but you can use an element distance from the top of the screen instead. You can either pass in a selector `data-lax-anchor="#bio"` or set it to use itself `data-lax-anchor="self"` (this is the default for all presets) e.g.
```html
<p data-lax-opacity="200 1, 100 1, 0 0" data-lax-anchor="self">
<p class="lax" data-lax-opacity="200 1, 100 1, 0 0" data-lax-anchor="self">
I start to fade out after I'm 100px away from the top of the window
and then I'm gone by the time I reach the top!
</p>
```
There are also some shortcuts for useful values:
### Special Values
| Key | Value |
| ------------- | ------------- |
| vw | window.innerWidth |
| vh | window.innerHeight |
| elw | targetElement.clientHeight |
| elh | targetElement.clientWidth |
| elw | targetElement.clientWidth |
| elh | targetElement.clientHeight |
You can use these instead of integer values for the scrollPos e.g.
```html
<p data-lax-opacity="0 1, vh 0">
<p class="lax" data-lax-opacity="0 1, vh 0">
I fade out as the page scrolls down and
I'm gone when the page has scrolled the view port height!
</p>
```
You can also do calculations using `( )` e.g.
### Calculated Values
You can also use vanilla JS within `( )` for calculations and access to more variables e.g.
```html
<p data-lax-opacity="0 1, (vh*0.5) 0">
<p class="lax" data-lax-opacity="0 1, (document.body.scrollHeight*0.5) 0">
I fade out as the page scrolls down and
I'm gone when the page has scrolled half the view port height!
I'm gone when the page has scrolled 50%
down the entire page height!
</p>
```
### Options
You can pass options into your custom animations for more control e.g.
```html
<p class="lax" data-lax-opacity="0 1, 100 0, 200 100 | loop=200 offset=100 speed=2">
I start at 0 opacity and
fade in and out every 50px
</p>
```
| Option | Effect |
| ------------- | ------------- |
| loop | modulus the input scrollY position so the animation will loop every `loop` pixels |
| offset | add `offset` to scrollY position so the animation will begin at this point |
| speed | multiplies the input scrollY position by `speed` to change the speed of the animation |
## Responsive Design
You can set multiple presets and animations for different screen widths. When setting up lax you need to pass in your screen width breakpoints e.g.
```javascript
lax.setup({
breakpoints: { small: 0, large: 992 }
})
```
Then you can define presets or transforms per breakpoint.
```html
<p class="lax" data-lax-preset_small="spin">
I only spin when the screen is smaller than 992px.
</p>
<p class="lax" data-lax-scale_small="0 1, 500 0" data-lax-scale_large="0 1, 500 2">
I shrink when the screen is smaller than 992px but grow when the screen is larger 992px.
</p>
```
## Supported Presets
| Preset | Default Strength |
@@ -111,7 +175,8 @@ You can also do calculations using `( )` e.g.
| zoomInOut | 0.2 |
| zoomIn | 0.2 |
| zoomOut | 0.2 |
| swing | 30 |
| speedy | 30 |
## Supported Attribute Keys
@@ -143,6 +208,33 @@ Filters (note - these may be unperformant on low powered machines)
| saturate | data-lax-saturate |
| grayscale | data-lax-grayscale |
Other
| Filter | Key |
| ------------- | ------------- |
| background position | data-lax-bg-pos |
| background position-x | data-lax-bg-pos-x |
| background position-y | data-lax-bg-pos-y |
## Sprite Sheet Animations
You can create animations using sprite sheets. See a demo [here](https://alexfox.dev/laxxx/sprite.html).
The `data-lax-sprite-data` is required and formated like so `[frameWidth, frameHeight, frameCount, columnCount, scrollStep]`. You can either set the image using CSS or the `data-lax-sprite-image` attribute. e.g.
```html
<div
class="lax"
data-lax-sprite-data="500,500,36,36,10"
data-lax-sprite-image="./spritesheet.png"
/>
```
You can turn a gif or a video into a sprite sheet with this tool: https://ezgif.com/gif-to-sprite
Note: current implimentation requires the element to be the same size as the frame width & height.
## Custom Presets
To avoid duplicate code you can define your own presets with a list of attributes e.g.
```javascript
@@ -155,24 +247,38 @@ lax.addPreset("myCoolPreset", function() {
```
You can then access this preset like this:
```html
<p data-lax-preset="myCoolPreset">
<p class="lax" data-lax-preset="myCoolPreset">
I'm the coolest preset in the world 😎
</p>
```
## Performance Tips
* Avoid nesting lax enabled elements within each other, you'll get better performance using lax with smaller elements in the dom tree.
* Avoid transforms on large elements, e.g. full screen backgrounds.
* By default elements that have opacity 0 aren't updated. You can either manually set up a `data-lax-opacity` to control this yourself or use `data-lax-optimize` which will set the elements opacity to 0 when it goes off -screen.
* By default `-webkit-backface-visibility: hidden;` is added to your elements style to encourage the browser to render that object as a layer on the GPU and increase performance. To turn this off add `data-lax-use-gpu="false"` to your element.
## Notes
### Performance
By default `-webkit-backface-visibility: hidden;` is added to your elements style to encourage the browser to render that object as a layer on the GPU and increase performance. To turn this off add `lax-optimize="false"` to your element.
### Screen Rotating & Resizing
As some values (vh, vw, elh, elw) are calculated on load, when the screen size changes or rotates you might want to recalculate these. E.g.
```
window.addEventListener("resize", function() {
lax.populateElements()
});
```
Be warned, on mobile, a resize event is fired when you scroll and the toolbar is hidden so you might want to check if the width or orientation has changed.
### Scroll Wheels
Scroll wheels only icrement the scroll position in steps which can cause the animations to look janky. You can use the SmoothScroll (http://www.smoothscroll.net/) plugin to smooth this out, however there maybe performance implications that need investigating.
Scroll wheels only increment the scroll position in steps which can cause the animations to look janky. You can use the SmoothScroll (http://www.smoothscroll.net/) plugin to smooth this out, however there maybe performance implications that need investigating.
### Merging Existing Styles
Only inline styles for transforms and filters will be merged in to the animation. Transforms and filters derived from CSS will be overwritten.
## To Do / Ideas
* Add debug mode
* Elastic bouncing values
* Optimise elements that go off screen
* Impliment a tween for scroll wheels to remove dependancy on smoothscroll
* Better error reporting
* Add "momentum" as option for anchor & presets
* Implement a tween for scroll wheels to remove reliance on smoothscroll
* A way to add weight/momentum to moving objecs
* ~~Support for sprite sheet animations~~

13
changelog Normal file
View File

@@ -0,0 +1,13 @@
- Added responsive stuff
- Changed demo to use window.animationFrame
- breaking change - now have to add lax class to elements
- Now merges in elements original transform and filter // inline
- Can add options into e.g. | loop=360 offset=1000 speed=2
- performance improvements
todo
- update change log
- usage with vue/react
- add link to my personal site

69
dev/inertia.html Normal file
View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.75, maximum-scale=0.75, minimum-scale=0.75">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,600,800" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<script src="./lib/lax.min.js"></script>
<!-- <script src="../src/lax.js"></script> -->
<script type="text/javascript">
window.onload = function() {
document.getElementById("main").classList.add("loaded")
lax.setup()
let toAdd = 0
let lastY = 0
const scrolls = [0,0,0,0,0]
const update = () => {
scrolls.unshift()
if(lastY !== window.scrollY) scrolls.push(window.scrollY)
lastY = window.scrollY
const sum = scrolls.reduce(function(a, b) { return a + b; });
const y = sum / scrolls.length
lax.update(y)
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
}
</script>
<style>
body,html {
margin:0;
padding:0;
color: #F3F4F5;
background: #191818;
overflow-x: hidden;
height: 10000vh;
font-family: 'Montserrat', sans-serif;
}
#letter {
width: 10vw;
margin-left: 10vw;
position: fixed;
top: 20vh;
}
</style>
</head>
<body>
<div id="main">
<div id="header" class="section">
<img src="./img/a.png" id="letter" data-lax-translate-x="0 0, 1000 1000" />
</div>
</div>
</body>

5
dev/js/stats.js Normal file
View File

@@ -0,0 +1,5 @@
// stats.js - http://github.com/mrdoob/stats.js
(function(f,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"block":"none";l=a}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();
u(++l%c.children.length)},!1);var k=(performance||Date).now(),g=k,a=0,r=e(new f.Panel("FPS","#0ff","#002")),h=e(new f.Panel("MS","#0f0","#020"));if(self.performance&&self.performance.memory)var t=e(new f.Panel("MB","#f08","#201"));u(0);return{REVISION:16,dom:c,addPanel:e,showPanel:u,begin:function(){k=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();h.update(c-k,200);if(c>g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/
1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);
b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});

65
dev/performance.html Normal file
View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.75, maximum-scale=0.75, minimum-scale=0.75">
<script src="../src/lax.js"></script>
<script src="./js/stats.js"></script>
<script type="text/javascript">
window.onload = function() {
var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom );
for(let i=0; i<1000; i++) {
const el = document.createElement("img")
el.src="../docs/img/a.png"
el.className="lax"
el.style.width = 50 + 'px'
el.style.height = 50 + 'px'
el.style.left = 50*(i%25) + 'px'
el.style.top = 50*Math.floor(i/25) + 'px'
el.setAttribute("data-lax-rotate","0 0, 500 1000")
el.setAttribute("data-lax-opacity","0 1, 500 0")
el.setAttribute("data-lax-scale","0 1, 500 0.5")
document.body.appendChild(el)
}
lax.setup()
let i = 0
const update = () => {
stats.begin();
lax.update(i%500)
i++
stats.end();
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
}
</script>
<style>
body,html {
margin:0;
padding:0;
color: #F3F4F5;
background: #191818;
overflow-x: hidden;
height: 500vh;
font-family: 'Montserrat', sans-serif;
}
img {
position: fixed;
}
</style>
</head>
<body>
</body>

90
dev/reactive.html Normal file
View File

@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.75, maximum-scale=0.75, minimum-scale=0.75">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,600,800" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<!-- <script src="./lib/lax.min.js"></script> -->
<script src="../src/lax.js"></script>
<script type="text/javascript">
window.onload = function() {
document.getElementById("main").classList.add("loaded")
lax.setup({
breakpoints: { xs: 0, s: 576, m: 768, l: 992 }
})
const update = () => {
lax.update(window.scrollY)
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
let w = window.innerWidth
window.addEventListener("resize", function() {
if(w !== window.innerWidth) {
lax.populateElements()
}
});
}
</script>
<style>
body,html {
margin:0;
padding:0;
color: #F3F4F5;
background: #191818;
overflow-x: hidden;
height: 500vh;
font-family: 'Montserrat', sans-serif;
}
#main {
opacity: 0;
transition: opacity 200ms;
}
#main.loaded {
opacity: 1;
}
#header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100vw;
z-index: 2;
height: 100vh;
}
#header img {
width: 78pt;
margin-top: 12pt;
position: fixed;
transform: scale(0.5)
}
</style>
</head>
<body>
<div id="main">
<div id="header" class="section">
<img src="./img/a.png"
class="lax"
data-lax-scale="0 1, vh 5"
data-lax-scale_s="0 1, vh 1"
data-lax-preset_s="fadeInOut"
data-lax-scale_xs="0 1, vh 0"
/>
</div>
</div>
</body>

158
docs/demo.html Normal file
View File

@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,600,800" rel="stylesheet">
<style>
body,html {
margin:0;
padding:0;
color: rgb(10,10,10);
background: white;
overflow-x: hidden;
height: 10000vh;
font-family: "Raleway", "HelveticaNeue", sans-serif;
}
h4 {
font-size: 2rem;
line-height: 1.35;
letter-spacing: -.08rem;
}
#main {
opacity: 0;
transition: opacity 200ms;
}
#main.loaded {
opacity: 1;
}
#background {
position: fixed;
}
.leaf1 {
width: 200pt;
height: 80pt;
position: absolute;
background: url('img/leaf1.svg') no-repeat;
mix-blend-mode: multiply;
opacity: 0.7;
}
.leaf {
width: 200pt;
height: 100pt;
position: absolute;
mix-blend-mode: multiply;
opacity: 0.7;
}
#center {
display: flex;
flex-direction: column;
align-items: center;
width: 100vw;
}
#avatar {
width: 150pt;
height: 150pt;
background: gray;
border-radius: 75pt;
margin-top: 50pt
}
#bio {
width: 400pt;
position: fixed;
}
#bio p {
font-size: 14pt;
line-height: 26pt;
font-weight: 100;
}
.github-corner {
z-index: 1000;
display: block;
position: fixed;
top: 0;
right: 0;
transform: scale(1.2);
}
</style>
<!-- <script src="./lib/lax.min.js"></script> -->
<script src="../src/lax.js"></script>
<script type="text/javascript">
window.onload = function() {
document.getElementById("main").classList.add("loaded")
lax.setup()
const update = () => {
lax.update(window.scrollY)
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
}
</script>
</head>
<body>
<div id="main">
<div id="background">
<div
class="lax leaf"
style="transform: scale(1.5); background: url('img/leaf1.svg') no-repeat;"
data-lax-rotate= "0 -20, 900 20, 2000 -20 | loop=2000 offset=200"
data-lax-translate-x= "0 110, 800 -100, 900 -110, 1900 100, 2000 110 | loop=2000 offset=200"
data-lax-translate-y= "0 -elh, (vh*10) (vh+elh) | loop=(vh*10) offset=1000 speed=1"
></div>
<div
class="lax leaf"
style="transform: scale(2); background: url('img/leaf2.svg') no-repeat;"
data-lax-rotate= "0 -20, 900 20, 2000 -20 | loop=2000 offset=500 speed=1.5"
data-lax-translate-x= "0 110, 800 -100, 900 -110, 1900 100, 2000 110 | loop=2000 offset=500 speed=1.5"
data-lax-translate-y= "0 -elh, (vh*10) (vh+elh) | loop=(vh*10) offset=1000 speed=1"
></div>
<div
class="lax leaf"
style="transform: scale(1.2); background: url('img/leaf3.svg') no-repeat;"
data-lax-rotate= "0 -20, 900 20, 2000 -20 | loop=2000 offset=1000"
data-lax-translate-x= "0 110, 800 -100, 900 -110, 1900 100, 2000 110 | loop=2000 offset=1000"
data-lax-translate-y= "0 -elh, (vh*10) (vh+elh) | loop=(vh*10) offset=400 speed=1"
></div>
</div>
<div id="center">
<div
id="avatar"
class="lax"
/></div>
<div id="bio">
<h4>Scroll Dowwwnn...</h4>
</div>
</div>
</div>
<a href="https://github.com/alexfoxy/laxxx" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#000000; color:#ffffff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
</body>

BIN
docs/img/a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52.22 46.64"><defs><style>.cls-1{fill:#f3f4f5;}</style></defs><title>a</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M1,32.73H6.43C2.55,29.23,0,24.41,0,17.41,0,7.85,5.49,0,15.52,0h.18C26.77,0,31.88,8.42,31.88,20.43a36.09,36.09,0,0,1-2.08,12.4h.85c6,0,9.27-3.69,9.27-10.88A37.31,37.31,0,0,0,37.18,8l11-3.6A44.74,44.74,0,0,1,52.22,24c0,15.7-8.13,22.61-21.85,22.61H1ZM21.38,33a22.24,22.24,0,0,0,1.89-9.18c0-6.15-2.46-9.93-7-9.93h-.19c-3.88,0-6.15,3.21-6.15,7.85,0,6.72,3.69,11.26,8.9,11.26Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 615 B

BIN
docs/img/bart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
docs/img/bball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
docs/img/bowser-sprite.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/img/button-bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
docs/img/l.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.06 14.38"><defs><style>.cls-1{fill:#f3f4f5;}</style></defs><title>l</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,0H69.06V14.38H0Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 264 B

1
docs/img/leaf1.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 155.56 54.07"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="17.69" y1="36.08" x2="165.43" y2="35.97" gradientTransform="translate(-20.45 21.43) rotate(-18.21)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#c135d4"/><stop offset="1" stop-color="#6c56e3"/></linearGradient></defs><title>leaf1</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M155.56,27c-17.91,16.44-46.08,27-77.77,27S17.91,43.47,0,27C17.91,10.59,46.09,0,77.79,0S137.65,10.59,155.56,27Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 684 B

1
docs/img/leaf2.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 155.56 54.07"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="-18.84" y1="30.22" x2="128.9" y2="30.11" gradientTransform="translate(16.08 15.58) rotate(-18.21)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#d4b43d"/><stop offset="1" stop-color="#ff309e"/></linearGradient></defs><title>leaf2</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M155.56,27c-17.91,16.44-46.08,27-77.77,27S17.91,43.47,0,27C17.91,10.59,46.09,0,77.79,0S137.65,10.59,155.56,27Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 683 B

1
docs/img/leaf3.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 155.56 54.07"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="-0.57" y1="33.15" x2="147.16" y2="33.04" gradientTransform="translate(-2.19 18.5) rotate(-18.21)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#008ad4"/><stop offset="1" stop-color="#57ffb6"/></linearGradient></defs><title>leaf3</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M155.56,27c-17.91,16.44-46.08,27-77.77,27S17.91,43.47,0,27C17.91,10.59,46.09,0,77.79,0S137.65,10.59,155.56,27Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 682 B

1
docs/img/leaf4.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 155.56 54.07"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="-17.27" y1="74.53" x2="130.46" y2="74.42" gradientTransform="translate(0.75 -26.02) rotate(-18.21)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#393fe3"/><stop offset="1" stop-color="#16d7de"/></linearGradient></defs><title>leaf4</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M155.56,27c-17.91,16.44-46.08,27-77.77,27S17.91,43.47,0,27C17.91,10.59,46.09,0,77.79,0S137.65,10.59,155.56,27Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 684 B

1
docs/img/leaf5.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 155.56 54.07"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="0.99" y1="77.45" x2="148.73" y2="77.34" gradientTransform="translate(-17.52 -23.09) rotate(-18.21)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#cce371"/><stop offset="1" stop-color="#37e310"/></linearGradient></defs><title>leaf5</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M155.56,27c-17.91,16.44-46.08,27-77.77,27S17.91,43.47,0,27C17.91,10.59,46.09,0,77.79,0S137.65,10.59,155.56,27Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 684 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/img/mario-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/img/mario-sprite.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
docs/img/mario-stars.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/img/nyan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/img/x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50.71 50.9"><defs><style>.cls-1{fill:#f3f4f5;}</style></defs><title>x</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,35.48,15.8,25.26,0,15V0L25.73,17.79,50.71.66V16.08L36,25.54,50.71,35.1v15L26,33,0,50.9Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 334 B

View File

@@ -11,13 +11,23 @@
<script type="text/javascript">
window.onload = function() {
lax.setup()
document.addEventListener('scroll', function(x) {
lax.update(window.scrollY)
}, false)
document.getElementById("main").classList.add("loaded")
lax.update(window.scrollY)
lax.setup()
const update = () => {
lax.update(window.scrollY)
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
let w = window.innerWidth
window.addEventListener("resize", function() {
if(w !== window.innerWidth) {
lax.populateElements()
}
});
}
</script>
@@ -30,6 +40,15 @@
overflow-x: hidden;
font-family: 'Montserrat', sans-serif;
}
#main {
opacity: 0;
transition: opacity 200ms;
}
#main.loaded {
opacity: 1;
}
#header {
display: flex;
@@ -37,8 +56,8 @@
align-items: center;
justify-content: center;
width: 100vw;
margin-top: 20vh;
z-index: 2;
height: 100vh;
}
.bg {
@@ -50,12 +69,12 @@
}
#header img {
width: 14vh;
margin-top: 2vh;
width: 78pt;
margin-top: 12pt;
}
#header h2 {
margin-top: 12vh;
margin-top: 60pt;
font-size: 24pt;
font-weight: 600;
text-align: center;
@@ -165,16 +184,12 @@
}
.button {
padding: 10pt 20pt;
background: #35D5E5;
padding: 10pt 50pt;
background: url(img/button-bg.jpg);
background-size: 100pt;
border-radius: 10pt;
font-weight: 600;
}
.button:hover {
background: white;
color: #35D5E5;
cursor: pointer;
color: black !important;
}
a {
@@ -182,7 +197,22 @@
}
a:visited {
color: white !important;
color: black !important;
}
.button:hover {
background: white;
color: black !important;
cursor: pointer;
}
.github-corner {
z-index: 1000;
display: block;
position: absolute;
top: 0;
right: 0;
transform: scale(1.2);
}
</style>
@@ -190,152 +220,158 @@
<body>
<div id="header" class="section" data-lax-opacity="0 1, (0.8*vh) 0">
<img src="./img/l.svg" style="width: 19vh; margin-left: 5vh;" data-lax-translate-x="0 0, vh 200" />
<img src="./img/a.svg" data-lax-translate-x="0 0, vh -200" />
<img src="./img/x.svg" />
<img src="./img/x.svg" style="margin-top: -14vh" data-lax-translate-y="0 0, vh 200" />
<img src="./img/x.svg" style="margin-top: -14vh" data-lax-translate-y="0 0, vh 400" />
<img src="./img/x.svg" style="margin-top: -14vh" data-lax-translate-y="0 0, vh 600" />
<img src="./img/x.svg" style="margin-top: -14vh" data-lax-translate-y="0 0, vh 800" />
<img src="./img/x.svg" style="margin-top: -14vh" data-lax-translate-y="0 0, vh 1000" />
<h2 data-lax-scale="0 1, vh 0.2" data-lax-translate-y="0 0, vh 1200" data-lax-opacity="0 1, (vh*0.5) 0">awesum scroll effects</h2>
<h4 data-lax-opacity="0 1, (vh*0.05) 0">scroll down</h4>
<i class="fas fa-chevron-down"
data-lax-opacity="0 1, (vh*0.1) 0"
data-lax-translate-y="0 0, 200 100">
</i>
</div>
<div id="main">
<div id="header" class="section">
<img src="./img/l.png" class="lax" style="width: 103pt; margin-left: 26pt; margin-bottom: -4pt;" data-lax-translate-x="0 0, vh 200" data-lax-optimize=true />
<img src="./img/a.png" class="lax" data-lax-translate-x="0 0, vh -200" data-lax-optimize=true />
<img src="./img/x.png" class="lax" data-lax-opacity="0 1, (0.8*vh) 0" />
<img src="./img/x.png" class="lax" style="margin-top: -79pt" data-lax-translate-y="0 0, vh 200" data-lax-opacity="0 1, (0.8*vh) 0" />
<img class="lax" src="./img/x.png" style="margin-top: -79pt" data-lax-translate-y="0 0, vh 400" data-lax-opacity="0 1, (0.8*vh) 0" />
<img class="lax" src="./img/x.png" style="margin-top: -79pt" data-lax-translate-y="0 0, vh 600" data-lax-opacity="0 1, (0.8*vh) 0" />
<img class="lax" src="./img/x.png" style="margin-top: -79pt" data-lax-translate-y="0 0, vh 800" data-lax-opacity="0 1, (0.8*vh) 0" />
<img class="lax" src="./img/x.png" style="margin-top: -79pt" data-lax-translate-y="0 0, vh 1000" data-lax-opacity="0 1, (0.8*vh) 0" />
<h2 class="lax" data-lax-scale="0 1, vh 0.2" data-lax-translate-y="0 0, vh 1200" data-lax-opacity="0 1, (vh*0.5) 0">awesum scroll effects</h2>
<div id="section1" class="section">
<div class="left">
<div class="bubble a"
style="background: #EDD943"
data-lax-preset="lazy-250"
></div>
<div class="bubble c"
style="background: #ED2471; margin-left: 80pt"
data-lax-preset="lazy-100"
></div>
<div class="bubble b"
style="background: #35D5E5; margin-left: 160pt"
data-lax-preset="lazy-300"
></div>
<h3 data-lax-preset="driftRight" class="chunkyText" style="color: #35D5E5;">oooh!</h3>
<h4 class="lax" data-lax-opacity="0 1, (vh*0.05) 0">scroll down</h4>
<i class="lax fas fa-chevron-down"
data-lax-opacity="0 1, (vh*0.1) 0"
data-lax-translate-y="0 0, 200 100">
</i>
</div>
<div class="right">
<div class="bubble a"
style="background: #35D5E5; margin-left: 120pt"
data-lax-preset="lazy-200"
<div id="section1" class="section">
<div class="left">
<div class="lax bubble a"
style="background: #EDD943"
data-lax-preset="lazy-250"
></div>
<div class="bubble c"
style="background: #EDD943; margin-left: -20pt"
data-lax-preset="lazy-150"
<div class="lax bubble c"
style="background: #ED2471; margin-left: 80pt"
data-lax-preset="lazy-100"
></div>
<div class="bubble b"
style="background: #ED2471; margin-left: 20pt; margin-top: 200pt"
data-lax-preset="lazy-350"
<div class="lax bubble b"
style="background: #35D5E5; margin-left: 160pt"
data-lax-preset="lazy-300"
></div>
<h3 data-lax-preset="driftLeft" class="chunkyText" style="color: #ED2471; margin-top: 200pt;">aaah!</h3>
<h3 data-lax-preset="driftRight" data-lax-optimize=true class="lax chunkyText" style="color: #35D5E5;">oooh!</h3>
</div>
<div class="right">
<div class="lax bubble a"
style="background: #35D5E5; margin-left: 120pt"
data-lax-preset="lazy-200"
></div>
<div class="lax bubble c"
style="background: #EDD943; margin-left: -20pt"
data-lax-preset="lazy-150"
></div>
<div class="lax bubble b"
style="background: #ED2471; margin-left: 20pt; margin-top: 200pt"
data-lax-preset="lazy-350"
></div>
<h3 data-lax-optimize=true data-lax-preset="driftLeft" class="lax chunkyText" style="color: #ED2471; margin-top: 200pt;">aaah!</h3>
</div>
<h3 data-lax-preset="crazy zoomInOut" class="lax crazyText" data-lax-optimize=true>sooo crazy</h3>
</div>
<h3 data-lax-preset="crazy zoomInOut" class="crazyText">sooo crazy</h3>
<div id="section2" class="section">
<div class="lax blockContainer" data-lax-preset="leftToRight-1.1 fadeInOut">
<div class="lax block"
style="background: #35D5E5;"
data-lax-preset="spin"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.2 fadeInOut">
<div class="lax block"
style="background: #EDD943; margin-top: -50pt; margin-left: -50pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.4 fadeInOut">
<div class="lax block"
style="background: #ED2471; margin-top: -90pt; margin-left: -0pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
<div class="lax block"
style="background: #EDD943; margin-top: 70pt; margin-left: -150pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.3 fadeInOut">
<div class="lax block"
style="background: #EDD943; margin-top: 100pt; margin-left: -60pt; width: 25pt; height: 25pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.05 fadeInOut">
<div class="lax block"
style="background: #ED2471; margin-top: -30pt; margin-left: -70pt;"
data-lax-preset="spin"
></div>
</div>
<h3 data-lax-preset="leftToRight-0.8 speedy" data-lax-optimize=true class="lax chunkyText" style="
color: #white; position: absolute; margin-top: -20pt; margin-left: -100pt">
wheee!
</h3>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.15 fadeInOut">
<div class="lax block"
style="background: #35D5E5; margin-top: -70pt; margin-left: -20pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.45 fadeInOut">
<div class="lax block"
style="background: #ED2471; margin-top: -50pt; margin-left: -50pt; width: 25pt; height: 25pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
<div class="lax block"
style="background: #35D5E5; margin-top: 30pt; margin-left: -20pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="lax blockContainer" data-lax-preset="leftToRight-1.25 fadeInOut">
<div class="lax block"
style="background: #ED2471; margin-top: 80pt; margin-left: -10pt;"
data-lax-preset="spin-500"
></div>
</div>
</div>
<div id="section3" class="lax section">
<p class="lax" data-lax-preset="linger" data-lax-optimize=true>
Harness the power of scrolling and make your websites come alive!
</p>
<a class="lax button" data-lax-preset="linger" data-lax-optimize=true data-lax-bg-pos-x="0 0, 3000 1000" href="https://github.com/alexfoxy/laxxx">
Get lax.js
</a>
</div>
</div>
<div id="section2" class="section">
<div class="blockContainer" data-lax-preset="leftToRight-1.1 fadeInOut">
<div class="block"
style="background: #35D5E5;"
data-lax-preset="spin"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.2 fadeInOut">
<div class="block"
style="background: #EDD943; margin-top: -50pt; margin-left: -50pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.4 fadeInOut">
<div class="block"
style="background: #ED2471; margin-top: -90pt; margin-left: -0pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
<div class="block"
style="background: #EDD943; margin-top: 70pt; margin-left: -150pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.3 fadeInOut">
<div class="block"
style="background: #EDD943; margin-top: 100pt; margin-left: -60pt; width: 25pt; height: 25pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.05 fadeInOut">
<div class="block"
style="background: #ED2471; margin-top: -30pt; margin-left: -70pt;"
data-lax-preset="spin"
></div>
</div>
<h3 data-lax-preset="leftToRight-0.8 fadeInOut" class="chunkyText" style="
color: #white; position: absolute; margin-top: -20pt; margin-left: -100pt">
wheee!
</h3>
<div class="blockContainer" data-lax-preset="leftToRight-1.15 fadeInOut">
<div class="block"
style="background: #35D5E5; margin-top: -70pt; margin-left: -20pt; width: 40pt; height: 40pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.45 fadeInOut">
<div class="block"
style="background: #ED2471; margin-top: -50pt; margin-left: -50pt; width: 25pt; height: 25pt;"
data-lax-preset="spin-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
<div class="block"
style="background: #35D5E5; margin-top: 30pt; margin-left: -20pt;"
data-lax-preset="spinRev-500"
></div>
</div>
<div class="blockContainer" data-lax-preset="leftToRight-1.25 fadeInOut">
<div class="block"
style="background: #ED2471; margin-top: 80pt; margin-left: -10pt;"
data-lax-preset="spin-500"
></div>
</div>
</div>
<div id="section3" class="section">
<p data-lax-preset="linger">
Harness the power of scrolling and make your websites come alive!
</p>
<a class="button" data-lax-preset="linger" href="https://github.com/alexfoxy/lax">
Get lax.js
</a>
</div>
<a href="https://github.com/alexfoxy/laxxx" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#fff; color:#151513; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
</body>

2
docs/lib/lax.min.js vendored

File diff suppressed because one or more lines are too long

206
docs/sprite.html Normal file
View File

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
<style>
body,html {
margin:0;
padding:0;
color: #F3F4F5;
background: #3c2d7f;
overflow-x: hidden;
height: 10000vh;
font-family: 'Montserrat', sans-serif;
}
#main {
opacity: 0;
transition: opacity 200ms;
}
#main.loaded {
opacity: 1;
}
#mario {
width: 256px;
height: 256px;
/*left: 0;*/
position: fixed;
top: calc(70vh - 256px)
}
#bowser {
width: 524px;
height: 350px;
/*left: 100vw;*/
position: fixed;
top: calc(70vh - 330px)
}
#stars {
width: 100vw;
height: 70vh;
background: url("img/mario-stars.gif");
background-size: 800px;
position: fixed;
opacity: 0.7;
top: 0;
}
#foreground {
width: 100vw;
height: 30vh;
background: url("img/mario-foreground.png");
background-size: 15vh;
position: fixed;
top: 70vh;
}
#nyan {
width: 300px;
height: 119px;
position: fixed;
top: 20vh;
left: 0;
}
#logo {
width: 300pt;
height: 100pt;
background: url(img/mario-logo.png) no-repeat center top;
background-size: contain;
position: fixed;
top: 10vh;
left: calc(50vw - 150pt);
z-index: 200;
}
#scrolltext {
width: 300pt;
height: 50pt;
background: url(img/mario-scrolldown.png) no-repeat center top;
background-size: contain;
position: fixed;
top: 83vh;
left: calc(50vw - 150pt);
}
#planet1 {
width: 30vw;
height: 30vw;
position: fixed;
left: 100vw;
bottom: 29vh;
}
#planet2 {
width: 20vw;
height: 20vw;
top: 10vh;
left: 30pt;
position: fixed;
}
.github-corner {
z-index: 1000;
display: block;
position: fixed;
top: 0;
right: 0;
transform: scale(1.2);
}
</style>
<script src="./lib/lax.min.js"></script>
<!-- <script src="../src/lax.js"></script> -->
<script type="text/javascript">
window.onload = function() {
document.getElementById("main").classList.add("loaded")
lax.setup()
const update = () => {
lax.update(window.scrollY)
window.requestAnimationFrame(update)
}
window.requestAnimationFrame(update)
}
</script>
</head>
<body>
<div id="main">
<div id="header" class="section">
<div
id="stars"
class="lax"
data-lax-bg-pos-x="0 0, 10000 -800 | loop=10000"
></div>
<div
id="planet1"
class="lax"
data-lax-translate-x="0 0, 5000 (-vw-elw)"
data-lax-sprite-data="382,382,15,5,10"
data-lax-sprite-image="./img/bart.png"
></div>
<div
id="foreground"
class="lax"
data-lax-bg-pos-x="0 0, 7000 (-15*vh) | loop=7000"
></div>
<div
id="logo"
></div>
<div
id="scrolltext"
data-lax-translate-y="0 0, 360 350"
class="lax"
></div>
<div
id="nyan"
data-lax-sprite-data="300,119,12,4,10"
data-lax-translate-x="0 vw, 600 -elw | loop=600"
data-lax-sprite-image="./img/nyan.png"
class="lax"
></div>
<div
id="mario"
class="lax"
data-lax-translate-x="0 -elw, 720 (vw+elw) | loop=720"
data-lax-translate-y="0 0, 240 0, 300 -500, 420 0, 720 0 | loop=720"
data-lax-sprite-data="256,256,12,4,5"
data-lax-sprite-image="./img/mario-sprite.png"
></div>
<div
id="bowser"
class="lax"
data-lax-translate-x="0 vw, 720 -elw | loop=720"
data-lax-sprite-data="524,350,8,4,10"
data-lax-sprite-image="./img/bowser-sprite.png"
></div>
</div>
</div>
<a href="https://github.com/alexfoxy/laxxx" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#fff; color:#151513; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
</body>

View File

@@ -1,5 +1,13 @@
"use strict";
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
//
// lax v0.0.1 (Alex Fox)
// Simple & light weight vanilla javascript plugin to create beautiful animations things when you scrolllll!!
@@ -15,319 +23,504 @@
// without getting a written permission first.
//
(function () {
var lax = {};
window.lax = lax;
var parallaxObjects = [];
var transforms = {
"data-lax-opacity": function dataLaxOpacity(style, v) {
style.opacity = v;
},
"data-lax-translate": function dataLaxTranslate(style, v) {
style.transform += " translate(".concat(v, "px, ").concat(v, "px)");
},
"data-lax-translate-x": function dataLaxTranslateX(style, v) {
style.transform += " translateX(".concat(v, "px)");
},
"data-lax-translate-y": function dataLaxTranslateY(style, v) {
style.transform += " translateY(".concat(v, "px)");
},
"data-lax-scale": function dataLaxScale(style, v) {
style.transform += " scale(".concat(v, ")");
},
"data-lax-scale-x": function dataLaxScaleX(style, v) {
style.transform += " scaleX(".concat(v, ")");
},
"data-lax-scale-y": function dataLaxScaleY(style, v) {
style.transform += " scaleY(".concat(v, ")");
},
"data-lax-skew": function dataLaxSkew(style, v) {
style.transform += " skew(".concat(v, "deg, ").concat(v, "deg)");
},
"data-lax-skew-x": function dataLaxSkewX(style, v) {
style.transform += " skewX(".concat(v, "deg)");
},
"data-lax-skew-y": function dataLaxSkewY(style, v) {
style.transform += " skewY(".concat(v, "deg)");
},
"data-lax-rotate": function dataLaxRotate(style, v) {
style.transform += " rotate(".concat(v, "deg)");
},
"data-lax-brightness": function dataLaxBrightness(style, v) {
style.filter += " brightness(".concat(v, "%)");
},
"data-lax-contrast": function dataLaxContrast(style, v) {
style.filter += " contrast(".concat(v, "%)");
},
"data-lax-hue-rotate": function dataLaxHueRotate(style, v) {
style.filter += " hue-rotate(".concat(v, "deg)");
},
"data-lax-blur": function dataLaxBlur(style, v) {
style.filter += " blur(".concat(v, "px)");
},
"data-lax-invert": function dataLaxInvert(style, v) {
style.filter += " invert(".concat(v, "%)");
},
"data-lax-saturate": function dataLaxSaturate(style, v) {
style.filter += " saturate(".concat(v, "%)");
},
"data-lax-grayscale": function dataLaxGrayscale(style, v) {
style.filter += " grayscale(".concat(v, "%)");
}
};
var _crazy = "";
var lax = function () {
var lax = {
elements: []
};
var lastY = 0;
var currentBreakpoint = 'default';
var breakpointsSeparator = "_";
var transformFns = {
"data-lax-opacity": function dataLaxOpacity(style, v) {
style.opacity = v;
},
"data-lax-translate": function dataLaxTranslate(style, v) {
style.transform += " translate(".concat(v, "px, ").concat(v, "px)");
},
"data-lax-translate-x": function dataLaxTranslateX(style, v) {
style.transform += " translateX(".concat(v, "px)");
},
"data-lax-translate-y": function dataLaxTranslateY(style, v) {
style.transform += " translateY(".concat(v, "px)");
},
"data-lax-scale": function dataLaxScale(style, v) {
style.transform += " scale(".concat(v, ")");
},
"data-lax-scale-x": function dataLaxScaleX(style, v) {
style.transform += " scaleX(".concat(v, ")");
},
"data-lax-scale-y": function dataLaxScaleY(style, v) {
style.transform += " scaleY(".concat(v, ")");
},
"data-lax-skew": function dataLaxSkew(style, v) {
style.transform += " skew(".concat(v, "deg, ").concat(v, "deg)");
},
"data-lax-skew-x": function dataLaxSkewX(style, v) {
style.transform += " skewX(".concat(v, "deg)");
},
"data-lax-skew-y": function dataLaxSkewY(style, v) {
style.transform += " skewY(".concat(v, "deg)");
},
"data-lax-rotate": function dataLaxRotate(style, v) {
style.transform += " rotate(".concat(v, "deg)");
},
"data-lax-brightness": function dataLaxBrightness(style, v) {
style.filter += " brightness(".concat(v, "%)");
},
"data-lax-contrast": function dataLaxContrast(style, v) {
style.filter += " contrast(".concat(v, "%)");
},
"data-lax-hue-rotate": function dataLaxHueRotate(style, v) {
style.filter += " hue-rotate(".concat(v, "deg)");
},
"data-lax-blur": function dataLaxBlur(style, v) {
style.filter += " blur(".concat(v, "px)");
},
"data-lax-invert": function dataLaxInvert(style, v) {
style.filter += " invert(".concat(v, "%)");
},
"data-lax-saturate": function dataLaxSaturate(style, v) {
style.filter += " saturate(".concat(v, "%)");
},
"data-lax-grayscale": function dataLaxGrayscale(style, v) {
style.filter += " grayscale(".concat(v, "%)");
},
"data-lax-bg-pos": function dataLaxBgPos(style, v) {
style.backgroundPosition = "".concat(v, "px ").concat(v, "px");
},
"data-lax-bg-pos-x": function dataLaxBgPosX(style, v) {
style.backgroundPositionX = "".concat(v, "px");
},
"data-lax-bg-pos-y": function dataLaxBgPosY(style, v) {
style.backgroundPositionY = "".concat(v, "px");
}
};
var _crazy = "";
for (var i = 0; i < 100; i++) {
_crazy += " " + window.innerHeight * (i / 100) + " " + Math.random() * 360 + ", ";
}
lax.presets = {
linger: function linger(v) {
return {
"data-lax-translate-y": "(vh*0.7) 0, 0 200, -500 0"
};
},
lazy: function lazy() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-y": "(vh) 0, (-elh) ".concat(v)
};
},
eager: function eager() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-y": "(vh) 0, (-elh) -".concat(v)
};
},
slalom: function slalom() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50;
return {
"data-lax-translate-x": "vh ".concat(v, ", (vh*0.8) ").concat(-v, ", (vh*0.6) ").concat(v, ", (vh*0.4) ").concat(-v, ", (vh*0.2) ").concat(v, ", (vh*0) ").concat(-v, ", (-elh) ").concat(v)
};
},
crazy: function crazy(v) {
return {
"data-lax-hue-rotate": _crazy
};
},
spin: function spin() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh) 0, (-elh) ".concat(v)
};
},
spinRev: function spinRev() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh) 0, (-elh) ".concat(-v)
};
},
spinIn: function spinIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "vh ".concat(v, ", (vh*0.5) 0")
};
},
spinOut: function spinOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh*0.5) 0, -elh ".concat(v)
};
},
blurInOut: function blurInOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh) ".concat(v, ", (vh*0.8) 0, (vh*0.2) 0, 0 ").concat(v)
};
},
blurIn: function blurIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh) ".concat(v, ", (vh*0.7) 0")
};
},
blurOut: function blurOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh*0.3) 0, 0 ".concat(v)
};
},
fadeInOut: function fadeInOut() {
return {
"data-lax-opacity": "(vh) 0, (vh*0.8) 1, (vh*0.2) 1, 0 0"
};
},
fadeIn: function fadeIn() {
return {
"data-lax-opacity": "(vh) 0, (vh*0.7) 1"
};
},
fadeOut: function fadeOut() {
return {
"data-lax-opacity": "(vh*0.3) 1, 0 0"
};
},
driftLeft: function driftLeft() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-x": "vh ".concat(v, ", -elh ").concat(-v)
};
},
driftRight: function driftRight() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-x": "vh ".concat(-v, ", -elh ").concat(v)
};
},
leftToRight: function leftToRight() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
"data-lax-translate-x": "vh 0, -elh (vw*".concat(v, ")")
};
},
rightToLeft: function rightToLeft() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
"data-lax-translate-x": "vh 0, -elh (vw*".concat(-v, ")")
};
},
zoomInOut: function zoomInOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh) ".concat(v, ", (vh*0.8) 1, (vh*0.2) 1, -elh ").concat(v)
};
},
zoomIn: function zoomIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh) ".concat(v, ", (vh*0.7) 1")
};
},
zoomOut: function zoomOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh*0.3) 1, -elh ".concat(v)
};
}
};
lax.addPreset = function (name, o) {
lax.presets[name] = o;
};
function intrp(table, v) {
var i = 0;
while (table[i][0] <= v && table[i + 1] !== undefined) {
i += 1;
for (var i = 0; i < 20; i++) {
_crazy += " " + i * 5 + " " + i * 47 % 360 + ", ";
}
var x = table[i][0];
var prevX = table[i - 1] === undefined ? x : table[i - 1][0];
var y = table[i][1];
var prevY = table[i - 1] === undefined ? y : table[i - 1][1];
var xPoint = Math.min(Math.max((v - prevX) / (x - prevX), 0), 1);
var yPoint = xPoint * (y - prevY) + prevY;
return yPoint;
}
lax.presets = {
linger: function linger(v) {
return {
"data-lax-translate-y": "(vh*0.7) 0, 0 200, -500 0"
};
},
lazy: function lazy() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-y": "(vh) 0, (-elh) ".concat(v)
};
},
eager: function eager() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-y": "(vh) 0, (-elh) -".concat(v)
};
},
slalom: function slalom() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50;
return {
"data-lax-translate-x": "vh ".concat(v, ", (vh*0.8) ").concat(-v, ", (vh*0.6) ").concat(v, ", (vh*0.4) ").concat(-v, ", (vh*0.2) ").concat(v, ", (vh*0) ").concat(-v, ", (-elh) ").concat(v)
};
},
crazy: function crazy(v) {
return {
"data-lax-hue-rotate": "".concat(_crazy, " | loop=20")
};
},
spin: function spin() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh) 0, (-elh) ".concat(v)
};
},
spinRev: function spinRev() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh) 0, (-elh) ".concat(-v)
};
},
spinIn: function spinIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "vh ".concat(v, ", (vh*0.5) 0")
};
},
spinOut: function spinOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 360;
return {
"data-lax-rotate": "(vh*0.5) 0, -elh ".concat(v)
};
},
blurInOut: function blurInOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh) ".concat(v, ", (vh*0.8) 0, (vh*0.2) 0, 0 ").concat(v)
};
},
blurIn: function blurIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh) ".concat(v, ", (vh*0.7) 0")
};
},
blurOut: function blurOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 40;
return {
"data-lax-blur": "(vh*0.3) 0, 0 ".concat(v)
};
},
fadeInOut: function fadeInOut() {
return {
"data-lax-opacity": "(vh) 0, (vh*0.8) 1, (vh*0.2) 1, 0 0"
};
},
fadeIn: function fadeIn() {
return {
"data-lax-opacity": "(vh) 0, (vh*0.7) 1"
};
},
fadeOut: function fadeOut() {
return {
"data-lax-opacity": "(vh*0.3) 1, 0 0"
};
},
driftLeft: function driftLeft() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-x": "vh ".concat(v, ", -elh ").concat(-v)
};
},
driftRight: function driftRight() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
return {
"data-lax-translate-x": "vh ".concat(-v, ", -elh ").concat(v)
};
},
leftToRight: function leftToRight() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
"data-lax-translate-x": "vh 0, -elh (vw*".concat(v, ")")
};
},
rightToLeft: function rightToLeft() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
"data-lax-translate-x": "vh 0, -elh (vw*".concat(-v, ")")
};
},
zoomInOut: function zoomInOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh) ".concat(v, ", (vh*0.8) 1, (vh*0.2) 1, -elh ").concat(v)
};
},
zoomIn: function zoomIn() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh) ".concat(v, ", (vh*0.7) 1")
};
},
zoomOut: function zoomOut() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.2;
return {
"data-lax-scale": "(vh*0.3) 1, -elh ".concat(v)
};
},
speedy: function speedy() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30;
return {
"data-lax-skew-x": "(vh) ".concat(v, ", -elh ").concat(-v)
};
},
swing: function swing() {
var v = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30;
return {
"data-lax-skew-y": "(vh) ".concat(v, ", -elh ").concat(-v)
};
}
};
lax.setup = function (o) {
lax.populateParallaxObjects();
};
lax.addPreset = function (p, o) {
lax.presets[p] = o;
};
lax.populateParallaxObjects = function () {
var selector = Object.keys(transforms).map(function (t) {
return "[".concat(t, "]");
}).join(",");
selector += ",[data-lax-preset]";
document.querySelectorAll(selector).forEach(function (el) {
function intrp(t, v) {
var i = 0;
while (t[i][0] <= v && t[i + 1] !== undefined) {
i += 1;
}
var x = t[i][0];
var prevX = t[i - 1] === undefined ? x : t[i - 1][0];
var y = t[i][1];
var prevY = t[i - 1] === undefined ? y : t[i - 1][1];
var xPoint = Math.min(Math.max((v - prevX) / (x - prevX), 0), 1);
var yPoint = xPoint * (y - prevY) + prevY;
return yPoint;
}
function fnOrVal(s) {
if (s[0] === "(") return eval(s);else return parseFloat(s);
}
lax.setup = function () {
var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
lax.breakpoints = o.breakpoints || {};
lax.selector = o.selector || '.lax';
lax.populateElements();
};
lax.removeElement = function (el) {
var i = this.elements.findIndex(function (o) {
return o.el = el;
});
if (i > -1) {
this.elements.splice(i, 1);
}
};
lax.addElement = function (el) {
var o = {
el: el,
transforms: []
};
var presetNames = el.attributes["data-lax-preset"] && el.attributes["data-lax-preset"].value;
originalStyle: {
transform: el.style.transform,
filter: el.style.filter
},
transforms: {} //find presets in data attributes
if (presetNames) {
presetNames.split(" ").forEach(function (p) {
};
var presets = [];
for (var i = 0; i < el.attributes.length; i++) {
var a = el.attributes[i];
if (a.name.indexOf("data-lax-preset") > -1) {
presets.push(a);
}
} //unwrap presets into transformations
var _loop = function _loop() {
a = presets[i];
b = a.name.split(breakpointsSeparator);
var breakpoint = b[1] ? "".concat(breakpointsSeparator).concat(b[1]) : '';
a.value.split(" ").forEach(function (p) {
var bits = p.split("-");
var fn = lax.presets[bits[0]];
if (!fn) {
console.error("preset #{bits[0]} is not defined");
console.log("lax error: preset ".concat(bits[0], " is not defined"));
} else {
var d = fn(bits[1]);
for (var k in d) {
el.setAttribute(k, d[k]);
el.setAttribute("".concat(k).concat(breakpoint), d[k]);
}
}
});
el.setAttribute("data-lax-anchor", "self");
el.attributes.removeNamedItem("data-lax-preset");
el.attributes.removeNamedItem(a.name);
};
for (var i = 0; i < presets.length; i++) {
var a;
var b;
_loop();
} // use gpu
var useGpu = !(el.attributes["data-lax-use-gpu"] && el.attributes["data-lax-use-gpu"].value === 'false');
if (useGpu) {
el.style["backface-visibility"] = "hidden";
el.style["-webkit-backface-visibility"] = "hidden";
}
var optimise = !(el.attributes["data-lax-optimize"] && el.attributes["data-lax-optimize"].value == 'false');
if (optimise) el.style["-webkit-backface-visibility"] = "hidden";
if (el.attributes["data-lax-optimize"]) el.attributes.removeNamedItem("data-lax-optimize");
if (el.attributes["data-lax-use-gpu"]) el.attributes.removeNamedItem("data-lax-use-gpu"); // optmise off screen
o.optimise = false;
if (el.attributes["data-lax-optimize"] && el.attributes["data-lax-optimize"].value === 'true') {
o.optimise = true;
var bounds = el.getBoundingClientRect();
el.setAttribute("data-lax-opacity", "".concat(-bounds.height - 1, " 0, ").concat(-bounds.height, " 1, ").concat(window.innerHeight, " 1, ").concat(window.innerHeight + 1, " 0"));
el.attributes.removeNamedItem("data-lax-optimize");
} // build transform list
for (var i = 0; i < el.attributes.length; i++) {
var a = el.attributes[i];
var bits = a.name.split("-");
if (a.name.indexOf("data-lax") < 0) continue;
var b = a.name.split(breakpointsSeparator);
var bits = b[0].split("-");
var breakpoint = b[1] || "default";
if (bits[1] === "lax") {
if (a.name === "data-lax-anchor") {
o["data-lax-anchor"] = a.value === "self" ? el : document.querySelector(a.value);
var rect = o["data-lax-anchor"].getBoundingClientRect();
o["data-lax-anchor-top"] = Math.floor(rect.top) + window.scrollY;
o.anchorTop = Math.floor(rect.top) + window.scrollY;
} else {
o.transforms[a.name] = a.value.replace(new RegExp('vw', 'g'), window.innerWidth).replace(new RegExp('vh', 'g'), window.innerHeight).replace(new RegExp('elh', 'g'), el.clientHeight).replace(new RegExp('elw', 'g'), el.clientWidth).replace(new RegExp('-vw', 'g'), -window.innerWidth).replace(new RegExp('-vh', 'g'), -window.innerHeight).replace(new RegExp('-elh', 'g'), -el.clientHeight).replace(new RegExp('-elw', 'g'), -el.clientWidth).replace(/\s+/g, " ").split(",").map(function (x) {
return x.trim().split(" ").map(function (y) {
if (y[0] === "(") return eval(y);else return parseFloat(y);
var name;
var valueMap;
(function () {
var tString = a.value.replace(new RegExp('-vw', 'g'), -window.innerWidth).replace(new RegExp('-vh', 'g'), -window.innerHeight).replace(new RegExp('-elh', 'g'), -el.clientHeight).replace(new RegExp('-elw', 'g'), -el.clientWidth).replace(new RegExp('vw', 'g'), window.innerWidth).replace(new RegExp('vh', 'g'), window.innerHeight).replace(new RegExp('elh', 'g'), el.clientHeight).replace(new RegExp('elw', 'g'), el.clientWidth).replace(/\s+/g, " ");
var _tString$split = tString.split("|"),
_tString$split2 = _slicedToArray(_tString$split, 2),
arrString = _tString$split2[0],
optionString = _tString$split2[1];
var options = {};
if (optionString) {
optionString.split(" ").forEach(function (o) {
var _o$split = o.split("="),
_o$split2 = _slicedToArray(_o$split, 2),
key = _o$split2[0],
val = _o$split2[1];
options[key] = key && fnOrVal(val);
});
}
name = b[0];
valueMap = arrString.split(",").map(function (x) {
return x.trim().split(" ").map(fnOrVal);
}).sort(function (a, b) {
return a[0] - b[0];
});
}).sort(function (a, b) {
return a[0] - b[0];
});
if (!o.transforms[name]) {
o.transforms[name] = {};
}
o.transforms[name][breakpoint] = {
valueMap: valueMap,
options: options
};
})();
}
}
} // sprite sheet animation
var spriteData = el.attributes["data-lax-sprite-data"] && el.attributes["data-lax-sprite-data"].value;
if (spriteData) {
o.spriteData = spriteData.split(",").map(function (x) {
return parseInt(x);
});
el.style.height = o.spriteData[1] + "px";
el.style.width = o.spriteData[0] + "px";
var spriteImage = el.attributes["data-lax-sprite-image"] && el.attributes["data-lax-sprite-image"].value;
if (spriteImage) {
el.style.backgroundImage = "url(".concat(spriteImage, ")");
}
}
parallaxObjects.push(o);
});
};
lax.elements.push(o);
lax.updateElement(o);
};
var lastScroll = 0;
lax.populateElements = function () {
lax.elements = [];
document.querySelectorAll(lax.selector).forEach(this.addElement);
currentBreakpoint = lax.getCurrentBreakPoint();
};
lax.update = function (y) {
var momentum = lastScroll - y;
lastScroll = y;
parallaxObjects.forEach(function (o) {
var transformString = "";
var r = o["data-lax-anchor-top"] ? o["data-lax-anchor-top"] - y : y;
lax.getCurrentBreakPoint = function () {
var b = 'default';
var w = window.innerWidth;
for (var i in lax.breakpoints) {
var px = parseFloat(lax.breakpoints[i]);
if (px <= w) {
b = i;
} else {
break;
}
}
return b;
};
lax.updateElement = function (o) {
var originalStyle = o.originalStyle,
anchorTop = o.anchorTop,
transforms = o.transforms,
spriteData = o.spriteData,
el = o.el;
var r = anchorTop ? anchorTop - lastY : lastY;
var style = {
transform: "",
filter: ""
transform: originalStyle.transform,
filter: originalStyle.filter
};
for (var i in o.transforms) {
var arr = o.transforms[i];
var t = transforms[i];
var v = intrp(arr, r);
for (var i in transforms) {
var transformData = transforms[i][currentBreakpoint] || transforms[i]["default"];
if (!transformData) {
// console.log(`lax error: there is no setting for key ${i} and screen size ${currentBreakpoint}. Try adding a default value!`)
continue;
}
var _r = r;
if (transformData.options.offset) _r = _r + transformData.options.offset;
if (transformData.options.speed) _r = _r * transformData.options.speed;
if (transformData.options.loop) _r = _r % transformData.options.loop;
var t = transformFns[i];
var v = intrp(transformData.valueMap, _r);
if (!t) {
console.error("lax: " + i + " is not supported");
return;
// console.info(`lax: error ${i} is not supported`)
continue;
}
t(style, v);
}
for (var k in style) {
if (style.opacity === 0) {
// if opacity 0 don't update
o.el.style.opacity = 0;
} else {
o.el.style[k] = style[k];
if (spriteData) {
var _spriteData = _slicedToArray(spriteData, 5),
frameW = _spriteData[0],
frameH = _spriteData[1],
numFrames = _spriteData[2],
cols = _spriteData[3],
scrollStep = _spriteData[4];
var frameNo = Math.floor(lastY / scrollStep) % numFrames;
var framePosX = frameNo % cols;
var framePosY = Math.floor(frameNo / cols);
style.backgroundPosition = "-".concat(framePosX * frameW, "px -").concat(framePosY * frameH, "px");
}
if (style.opacity === 0) {
// if opacity 0 don't update
el.style.opacity = 0;
} else {
for (var k in style) {
el.style[k] = style[k];
}
}
});
};
};
lax.update = function (y) {
if (lastY === y) return;
lastY = y;
lax.elements.forEach(lax.updateElement);
};
return lax;
}();
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') module.exports = lax;else window.lax = lax;
})();

2
lib/lax.min.js vendored

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,12 +1,29 @@
{
"name": "lax.js",
"version": "1.0.0",
"version": "1.2.0",
"scripts": {
"build": "babel src -d lib; uglifyjs lib/lax.js -o lib/lax.min.js -c -m; gzip < lib/lax.min.js > lib/lax.min.js.gz"
"build": "babel src -d lib; uglifyjs lib/lax.js -o lib/lax.min.js -c -m; gzip < lib/lax.min.js > lib/lax.min.js.gz;"
},
"dependencies": {
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4"
}
},
"description": "Simple & light weight (2kb minified & zipped) vanilla javascript plugin to create smooth & beautiful animations when you scrolllll! Harness the power of the most intuitive interaction and make your websites come alive!",
"license": "MIT",
"author": "alexfoxy@gmail.com",
"repository": {
"type" : "git",
"url" : "https://github.com/alexfoxy/laxxx"
},
"main": "lib/lax.min.js",
"keywords": [
"javascript",
"parallax",
"scroll",
"animation",
"effects",
"css",
"html"
]
}

View File

@@ -14,238 +14,375 @@
//
(function() {
var lax = {}
window.lax = lax
var parallaxObjects = []
const transforms = {
"data-lax-opacity": function(style, v) { style.opacity = v },
"data-lax-translate": function(style, v) { style.transform += ` translate(${v}px, ${v}px)` },
"data-lax-translate-x": function(style, v) { style.transform += ` translateX(${v}px)` },
"data-lax-translate-y": function(style, v) { style.transform += ` translateY(${v}px)` },
"data-lax-scale": function(style, v) { style.transform += ` scale(${v})` },
"data-lax-scale-x": function(style, v) { style.transform += ` scaleX(${v})` },
"data-lax-scale-y": function(style, v) { style.transform += ` scaleY(${v})` },
"data-lax-skew": function(style, v) { style.transform += ` skew(${v}deg, ${v}deg)` },
"data-lax-skew-x": function(style, v) { style.transform += ` skewX(${v}deg)` },
"data-lax-skew-y": function(style, v) { style.transform += ` skewY(${v}deg)` },
"data-lax-rotate": function(style, v) { style.transform += ` rotate(${v}deg)` },
"data-lax-brightness": function(style, v) { style.filter += ` brightness(${v}%)` },
"data-lax-contrast": function(style, v) { style.filter += ` contrast(${v}%)` },
"data-lax-hue-rotate": function(style, v) { style.filter += ` hue-rotate(${v}deg)` },
"data-lax-blur": function(style, v) { style.filter += ` blur(${v}px)` },
"data-lax-invert": function(style, v) { style.filter += ` invert(${v}%)` },
"data-lax-saturate": function(style, v) { style.filter += ` saturate(${v}%)` },
"data-lax-grayscale": function(style, v) { style.filter += ` grayscale(${v}%)` },
}
let crazy = ""
for(var i=0;i<100;i++) {
crazy += " " + (window.innerHeight*(i/100)) + " " + (Math.random() * 360) + ", "
}
lax.presets = {
linger: (v) => {
return { "data-lax-translate-y": `(vh*0.7) 0, 0 200, -500 0` }
},
lazy: (v=100) => {
return { "data-lax-translate-y": `(vh) 0, (-elh) ${v}` }
},
eager: (v=100) => {
return { "data-lax-translate-y": `(vh) 0, (-elh) -${v}` }
},
slalom: (v=50) => {
return { "data-lax-translate-x": `vh ${v}, (vh*0.8) ${-v}, (vh*0.6) ${v}, (vh*0.4) ${-v}, (vh*0.2) ${v}, (vh*0) ${-v}, (-elh) ${v}` }
},
crazy: (v) => {
return { "data-lax-hue-rotate": crazy }
},
spin: (v=360) => {
return { "data-lax-rotate": `(vh) 0, (-elh) ${v}` }
},
spinRev: (v=360) => {
return { "data-lax-rotate": `(vh) 0, (-elh) ${-v}` }
},
spinIn: (v=360) => {
return { "data-lax-rotate": `vh ${v}, (vh*0.5) 0` }
},
spinOut: (v=360) => {
return { "data-lax-rotate": `(vh*0.5) 0, -elh ${v}` }
},
blurInOut: (v=40) => {
return { "data-lax-blur": `(vh) ${v}, (vh*0.8) 0, (vh*0.2) 0, 0 ${v}` }
},
blurIn: (v=40) => {
return { "data-lax-blur": `(vh) ${v}, (vh*0.7) 0` }
},
blurOut: (v=40) => {
return { "data-lax-blur": `(vh*0.3) 0, 0 ${v}` }
},
fadeInOut: () => {
return { "data-lax-opacity": "(vh) 0, (vh*0.8) 1, (vh*0.2) 1, 0 0" }
},
fadeIn: () => {
return { "data-lax-opacity": "(vh) 0, (vh*0.7) 1" }
},
fadeOut: () => {
return { "data-lax-opacity": "(vh*0.3) 1, 0 0" }
},
driftLeft: (v=100) => {
return { "data-lax-translate-x": `vh ${v}, -elh ${-v}` }
},
driftRight: (v=100) => {
return { "data-lax-translate-x": `vh ${-v}, -elh ${v}` }
},
leftToRight: (v=1) => {
return { "data-lax-translate-x": `vh 0, -elh (vw*${v})` }
},
rightToLeft: (v=1) => {
return { "data-lax-translate-x": `vh 0, -elh (vw*${-v})` }
},
zoomInOut: (v=0.2) => {
return { "data-lax-scale": `(vh) ${v}, (vh*0.8) 1, (vh*0.2) 1, -elh ${v}` }
},
zoomIn: (v=0.2) => {
return { "data-lax-scale": `(vh) ${v}, (vh*0.7) 1` }
},
zoomOut: (v=0.2) => {
return { "data-lax-scale": `(vh*0.3) 1, -elh ${v}` }
},
}
lax.addPreset = (name, o) => {
lax.presets[name] = o
}
function intrp(table, v) {
var i = 0
while(table[i][0] <= v && table[i+1] !== undefined) {
i+=1
}
var x = table[i][0]
var prevX = table[i-1] === undefined ? x : table[i-1][0]
var y = table[i][1]
var prevY = table[i-1] === undefined ? y : table[i-1][1]
var xPoint = Math.min(Math.max((v-prevX)/(x-prevX),0),1)
var yPoint = (xPoint*(y-prevY)) + prevY
return yPoint
}
lax.setup = function(o) {
lax.populateParallaxObjects()
}
lax.populateParallaxObjects = function() {
var selector = Object.keys(transforms).map(t => `[${t}]`).join(",")
selector += ",[data-lax-preset]"
document.querySelectorAll(selector).forEach(function(el) {
var o = {
el: el,
transforms: []
var lax = (function() {
var lax = {
elements: []
}
var presetNames = el.attributes["data-lax-preset"] && el.attributes["data-lax-preset"].value
if(presetNames) {
presetNames.split(" ").forEach((p) => {
const bits = p.split("-")
const fn = lax.presets[bits[0]]
if(!fn) {
console.error(`preset #{bits[0]} is not defined`)
} else {
const d = fn(bits[1])
for(var k in d) {
el.setAttribute(k, d[k])
let lastY = 0;
let currentBreakpoint = 'default'
const breakpointsSeparator = "_"
const transformFns = {
"data-lax-opacity": function(style, v) { style.opacity = v },
"data-lax-translate": function(style, v) { style.transform += ` translate(${v}px, ${v}px)` },
"data-lax-translate-x": function(style, v) { style.transform += ` translateX(${v}px)` },
"data-lax-translate-y": function(style, v) { style.transform += ` translateY(${v}px)` },
"data-lax-scale": function(style, v) { style.transform += ` scale(${v})` },
"data-lax-scale-x": function(style, v) { style.transform += ` scaleX(${v})` },
"data-lax-scale-y": function(style, v) { style.transform += ` scaleY(${v})` },
"data-lax-skew": function(style, v) { style.transform += ` skew(${v}deg, ${v}deg)` },
"data-lax-skew-x": function(style, v) { style.transform += ` skewX(${v}deg)` },
"data-lax-skew-y": function(style, v) { style.transform += ` skewY(${v}deg)` },
"data-lax-rotate": function(style, v) { style.transform += ` rotate(${v}deg)` },
"data-lax-brightness": function(style, v) { style.filter += ` brightness(${v}%)` },
"data-lax-contrast": function(style, v) { style.filter += ` contrast(${v}%)` },
"data-lax-hue-rotate": function(style, v) { style.filter += ` hue-rotate(${v}deg)` },
"data-lax-blur": function(style, v) { style.filter += ` blur(${v}px)` },
"data-lax-invert": function(style, v) { style.filter += ` invert(${v}%)` },
"data-lax-saturate": function(style, v) { style.filter += ` saturate(${v}%)` },
"data-lax-grayscale": function(style, v) { style.filter += ` grayscale(${v}%)` },
"data-lax-bg-pos": function(style, v) { style.backgroundPosition = `${v}px ${v}px` },
"data-lax-bg-pos-x": function(style, v) { style.backgroundPositionX = `${v}px` },
"data-lax-bg-pos-y": function(style, v) { style.backgroundPositionY = `${v}px` }
}
let crazy = ""
for(var i=0;i<20;i++) {
crazy += " " + i*5 + " " + (i*47)%360 + ", "
}
lax.presets = {
linger: (v) => {
return { "data-lax-translate-y": `(vh*0.7) 0, 0 200, -500 0` }
},
lazy: (v=100) => {
return { "data-lax-translate-y": `(vh) 0, (-elh) ${v}` }
},
eager: (v=100) => {
return { "data-lax-translate-y": `(vh) 0, (-elh) -${v}` }
},
slalom: (v=50) => {
return { "data-lax-translate-x": `vh ${v}, (vh*0.8) ${-v}, (vh*0.6) ${v}, (vh*0.4) ${-v}, (vh*0.2) ${v}, (vh*0) ${-v}, (-elh) ${v}` }
},
crazy: (v) => {
return { "data-lax-hue-rotate": `${crazy} | loop=20` }
},
spin: (v=360) => {
return { "data-lax-rotate": `(vh) 0, (-elh) ${v}` }
},
spinRev: (v=360) => {
return { "data-lax-rotate": `(vh) 0, (-elh) ${-v}` }
},
spinIn: (v=360) => {
return { "data-lax-rotate": `vh ${v}, (vh*0.5) 0` }
},
spinOut: (v=360) => {
return { "data-lax-rotate": `(vh*0.5) 0, -elh ${v}` }
},
blurInOut: (v=40) => {
return { "data-lax-blur": `(vh) ${v}, (vh*0.8) 0, (vh*0.2) 0, 0 ${v}` }
},
blurIn: (v=40) => {
return { "data-lax-blur": `(vh) ${v}, (vh*0.7) 0` }
},
blurOut: (v=40) => {
return { "data-lax-blur": `(vh*0.3) 0, 0 ${v}` }
},
fadeInOut: () => {
return { "data-lax-opacity": "(vh) 0, (vh*0.8) 1, (vh*0.2) 1, 0 0" }
},
fadeIn: () => {
return { "data-lax-opacity": "(vh) 0, (vh*0.7) 1" }
},
fadeOut: () => {
return { "data-lax-opacity": "(vh*0.3) 1, 0 0" }
},
driftLeft: (v=100) => {
return { "data-lax-translate-x": `vh ${v}, -elh ${-v}` }
},
driftRight: (v=100) => {
return { "data-lax-translate-x": `vh ${-v}, -elh ${v}` }
},
leftToRight: (v=1) => {
return { "data-lax-translate-x": `vh 0, -elh (vw*${v})` }
},
rightToLeft: (v=1) => {
return { "data-lax-translate-x": `vh 0, -elh (vw*${-v})` }
},
zoomInOut: (v=0.2) => {
return { "data-lax-scale": `(vh) ${v}, (vh*0.8) 1, (vh*0.2) 1, -elh ${v}` }
},
zoomIn: (v=0.2) => {
return { "data-lax-scale": `(vh) ${v}, (vh*0.7) 1` }
},
zoomOut: (v=0.2) => {
return { "data-lax-scale": `(vh*0.3) 1, -elh ${v}` }
},
speedy: (v=30) => {
return { "data-lax-skew-x": `(vh) ${v}, -elh ${-v}` }
},
swing: (v=30) => {
return { "data-lax-skew-y": `(vh) ${v}, -elh ${-v}` }
}
}
lax.addPreset = (p, o) => {
lax.presets[p] = o
}
function intrp(t, v) {
var i = 0
while(t[i][0] <= v && t[i+1] !== undefined) {
i+=1
}
var x = t[i][0]
var prevX = t[i-1] === undefined ? x : t[i-1][0]
var y = t[i][1]
var prevY = t[i-1] === undefined ? y : t[i-1][1]
var xPoint = Math.min(Math.max((v-prevX)/(x-prevX),0),1)
var yPoint = (xPoint*(y-prevY)) + prevY
return yPoint
}
function fnOrVal(s) {
if(s[0] === "(") return eval(s)
else return parseFloat(s)
}
lax.setup = function(o={}) {
lax.breakpoints = o.breakpoints || {}
lax.selector = o.selector || '.lax'
lax.populateElements()
}
lax.removeElement = function(el) {
const i = this.elements.findIndex(o => o.el = el)
if(i > -1) {
this.elements.splice(i, 1)
}
}
lax.addElement = function(el) {
var o = {
el: el,
originalStyle: {
transform: el.style.transform,
filter: el.style.filter
},
transforms: {}
}
//find presets in data attributes
var presets = []
for(var i=0; i<el.attributes.length; i++) {
var a = el.attributes[i]
if(a.name.indexOf("data-lax-preset") > -1) {
presets.push(a);
}
}
//unwrap presets into transformations
for(var i=0; i<presets.length; i++) {
var a = presets[i]
var b = a.name.split(breakpointsSeparator)
const breakpoint = b[1] ? `${breakpointsSeparator}${b[1]}` : ''
a.value.split(" ").forEach((p) => {
const bits = p.split("-")
const fn = lax.presets[bits[0]]
if(!fn) {
console.log(`lax error: preset ${bits[0]} is not defined`)
} else {
const d = fn(bits[1])
for(var k in d) {
el.setAttribute(`${k}${breakpoint}`, d[k])
}
}
})
el.setAttribute("data-lax-anchor", "self")
el.attributes.removeNamedItem(a.name)
}
// use gpu
const useGpu = !(el.attributes["data-lax-use-gpu"] && el.attributes["data-lax-use-gpu"].value === 'false')
if(useGpu) {
el.style["backface-visibility"] = "hidden"
el.style["-webkit-backface-visibility"] = "hidden"
}
if(el.attributes["data-lax-use-gpu"]) el.attributes.removeNamedItem("data-lax-use-gpu")
// optmise off screen
o.optimise = false
if(el.attributes["data-lax-optimize"] && el.attributes["data-lax-optimize"].value === 'true') {
o.optimise = true
const bounds = el.getBoundingClientRect()
el.setAttribute("data-lax-opacity", `${-bounds.height-1} 0, ${-bounds.height} 1, ${window.innerHeight} 1, ${window.innerHeight+1} 0`)
el.attributes.removeNamedItem("data-lax-optimize")
}
// build transform list
for(var i=0; i<el.attributes.length; i++) {
var a = el.attributes[i]
if(a.name.indexOf("data-lax") < 0) continue
var b = a.name.split(breakpointsSeparator)
var bits = b[0].split("-")
var breakpoint = b[1] || "default"
if(bits[1] === "lax") {
if(a.name === "data-lax-anchor") {
o["data-lax-anchor"] = a.value === "self" ? el : document.querySelector(a.value)
const rect = o["data-lax-anchor"].getBoundingClientRect()
o.anchorTop = Math.floor(rect.top) + window.scrollY
} else {
const tString = a.value
.replace(new RegExp('-vw', 'g'), -window.innerWidth)
.replace(new RegExp('-vh', 'g'), -window.innerHeight)
.replace(new RegExp('-elh', 'g'), -el.clientHeight)
.replace(new RegExp('-elw', 'g'), -el.clientWidth)
.replace(new RegExp('vw', 'g'), window.innerWidth)
.replace(new RegExp('vh', 'g'), window.innerHeight)
.replace(new RegExp('elh', 'g'), el.clientHeight)
.replace(new RegExp('elw', 'g'), el.clientWidth)
.replace(/\s+/g," ")
const [arrString, optionString] = tString.split("|")
const options = {}
if(optionString) {
optionString.split(" ").forEach((o) => {
const [key, val] = o.split("=")
options[key] = key && fnOrVal(val)
})
}
var name = b[0]
var valueMap = arrString.split(",").map((x) => {
return x.trim().split(" ").map(fnOrVal)
}).sort((a,b) => {
return a[0] - b[0]
})
if(!o.transforms[name]) {
o.transforms[name] = {}
}
o.transforms[name][breakpoint] = { valueMap, options }
}
}
})
}
el.setAttribute("data-lax-anchor", "self")
el.attributes.removeNamedItem("data-lax-preset")
// sprite sheet animation
const spriteData = el.attributes["data-lax-sprite-data"] && el.attributes["data-lax-sprite-data"].value
if(spriteData) {
o.spriteData = spriteData.split(",").map(x => parseInt(x))
el.style.height = o.spriteData[1] + "px"
el.style.width = o.spriteData[0] + "px"
const spriteImage = el.attributes["data-lax-sprite-image"] && el.attributes["data-lax-sprite-image"].value
if(spriteImage) {
el.style.backgroundImage = `url(${spriteImage})`
}
}
lax.elements.push(o)
lax.updateElement(o)
}
const optimise = !(el.attributes["data-lax-optimize"] && el.attributes["data-lax-optimize"].value == 'false')
if(optimise) el.style["-webkit-backface-visibility"] = "hidden"
if(el.attributes["data-lax-optimize"]) el.attributes.removeNamedItem("data-lax-optimize")
lax.populateElements = function() {
lax.elements = []
for(var i=0; i<el.attributes.length; i++) {
var a = el.attributes[i]
var bits = a.name.split("-")
if(bits[1] === "lax") {
if(a.name === "data-lax-anchor") {
o["data-lax-anchor"] = a.value === "self" ? el : document.querySelector(a.value)
const rect = o["data-lax-anchor"].getBoundingClientRect()
o["data-lax-anchor-top"] = Math.floor(rect.top) + window.scrollY
document.querySelectorAll(lax.selector).forEach(this.addElement)
currentBreakpoint = lax.getCurrentBreakPoint()
}
lax.getCurrentBreakPoint = function() {
let b = 'default'
const w = window.innerWidth
for(var i in lax.breakpoints) {
let px = parseFloat(lax.breakpoints[i])
if(px <= w) {
b = i
} else {
o.transforms[a.name] = a.value
.replace(new RegExp('vw', 'g'), window.innerWidth)
.replace(new RegExp('vh', 'g'), window.innerHeight)
.replace(new RegExp('elh', 'g'), el.clientHeight)
.replace(new RegExp('elw', 'g'), el.clientWidth)
.replace(new RegExp('-vw', 'g'), -window.innerWidth)
.replace(new RegExp('-vh', 'g'), -window.innerHeight)
.replace(new RegExp('-elh', 'g'), -el.clientHeight)
.replace(new RegExp('-elw', 'g'), -el.clientWidth).replace(/\s+/g," ")
.split(",").map((x) => {
return x.trim().split(" ").map(y => {
if(y[0] === "(") return eval(y)
else return parseFloat(y)
})
}).sort((a,b) => {
return a[0] - b[0]
})
break
}
}
return b
}
lax.updateElement = function(o) {
const { originalStyle, anchorTop, transforms, spriteData, el } = o
let r = anchorTop ? anchorTop-lastY : lastY
var style = {
transform: originalStyle.transform,
filter: originalStyle.filter
}
for(var i in transforms) {
const transformData = transforms[i][currentBreakpoint] || transforms[i]["default"]
if(!transformData) {
// console.log(`lax error: there is no setting for key ${i} and screen size ${currentBreakpoint}. Try adding a default value!`)
continue
}
let _r = r
if(transformData.options.offset) _r = _r+transformData.options.offset
if(transformData.options.speed) _r = _r*transformData.options.speed
if(transformData.options.loop) _r = _r%transformData.options.loop
const t = transformFns[i]
const v = intrp(transformData.valueMap, _r)
if(!t) {
// console.info(`lax: error ${i} is not supported`)
continue
}
t(style, v)
}
if(spriteData) {
const [frameW,frameH,numFrames,cols,scrollStep] = spriteData
const frameNo = Math.floor(lastY/scrollStep) % numFrames
const framePosX = frameNo%cols
const framePosY = Math.floor(frameNo/cols)
style.backgroundPosition = `-${framePosX*frameW}px -${framePosY*frameH}px`
}
if(style.opacity === 0) { // if opacity 0 don't update
el.style.opacity = 0
} else {
for(let k in style) {
el.style[k] = style[k]
}
}
}
parallaxObjects.push(o)
})
}
var lastScroll = 0
lax.update = function(y) {
var momentum = lastScroll-y
lastScroll = y
parallaxObjects.forEach(function(o) {
var transformString = ""
var r = o["data-lax-anchor-top"] ? o["data-lax-anchor-top"]-y : y
var style = {
transform: "",
filter: ""
lax.update = function(y) {
if(lastY === y) return
lastY = y
lax.elements.forEach(lax.updateElement)
}
for(var i in o.transforms) {
var arr = o.transforms[i]
var t = transforms[i]
var v = intrp(arr, r)
return lax;
})();
if(!t) {
console.error("lax: " + i + " is not supported")
return
}
t(style, v)
}
for(let k in style) {
if(style.opacity === 0) { // if opacity 0 don't update
o.el.style.opacity = 0
} else {
o.el.style[k] = style[k]
}
}
})
}
})()
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
module.exports = lax;
else
window.lax = lax;
})();