Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a98a9781c | ||
|
|
e630079794 | ||
|
|
f68690aca8 | ||
|
|
33757cf7fa | ||
|
|
e44b8c7ddb | ||
|
|
57d6726326 | ||
|
|
6437b229f9 | ||
|
|
359d19e8af | ||
|
|
e6a322bbac | ||
|
|
b670d2fd12 | ||
|
|
e1ed428663 | ||
|
|
877bb3ec1a | ||
|
|
b7d32ace26 | ||
|
|
3813e8d486 | ||
|
|
b4cfc8d6b4 | ||
|
|
f2d3dc0977 | ||
|
|
a9a5d6a216 | ||
|
|
f035230a56 | ||
|
|
fddfeaabeb | ||
|
|
51dac49553 | ||
|
|
eb0a1b4230 | ||
|
|
7965234d87 | ||
|
|
ea813af50b | ||
|
|
278168414b | ||
|
|
25ac2b5497 | ||
|
|
9c9038a3ea | ||
|
|
bb6133ea2b | ||
|
|
0d36e901d7 | ||
|
|
49c45d8e4f | ||
|
|
1247463303 | ||
|
|
a587813c1e | ||
|
|
08dd1ceb6e | ||
|
|
f9074ee5e6 | ||
|
|
8684fb8ee3 | ||
|
|
9589627ed7 | ||
|
|
692ff93731 | ||
|
|
cf77d95f0e | ||
|
|
1dd3bebbdd | ||
|
|
33bd72d825 | ||
|
|
b461e7b1cf | ||
|
|
fee90b3a82 | ||
|
|
7431ff3840 | ||
|
|
07899d3443 | ||
|
|
b99389f388 | ||
|
|
027772e364 | ||
|
|
802fa7592c | ||
|
|
f9395c6c27 | ||
|
|
e8b68c246a | ||
|
|
e2a30f53b5 | ||
|
|
c96ff53460 | ||
|
|
9790b42b2e | ||
|
|
25d890421b | ||
|
|
842b7d40d6 | ||
|
|
4657e7adff | ||
|
|
d768100817 | ||
|
|
d274614a28 | ||
|
|
298f29e188 | ||
|
|
4791239fd3 | ||
|
|
793a9bb36e | ||
|
|
afe3114f9b | ||
|
|
b50e688197 |
21
LICENSE
Normal 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.
|
||||
172
README.md
@@ -1,14 +1,18 @@
|
||||
# lax.js
|
||||
|
||||
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!
|
||||
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/laxxx/)
|
||||
|
||||

|
||||

|
||||
|
||||
## Getting started
|
||||
[>>> MARIO DEMO <<<](https://alexfox.dev/laxxx/sprite.html)
|
||||
|
||||
### NPM setup
|
||||

|
||||
|
||||
## Getting Started
|
||||
|
||||
### NPM Setup
|
||||
|
||||
```bash
|
||||
npm install lax.js
|
||||
@@ -17,7 +21,7 @@ npm install lax.js
|
||||
import lax from 'lax.js'
|
||||
```
|
||||
|
||||
### Basic browser setup
|
||||
### Basic Browser Setup
|
||||
1) Add lax.js to your html
|
||||
|
||||
```html
|
||||
@@ -28,35 +32,46 @@ import lax from 'lax.js'
|
||||
|
||||
```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)
|
||||
* [react (using hooks)](https://github.com/arthurdenner/use-lax)
|
||||
* [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>
|
||||
@@ -64,36 +79,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 |
|
||||
@@ -121,7 +176,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
|
||||
|
||||
@@ -153,6 +209,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
|
||||
@@ -165,25 +248,40 @@ 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
|
||||
* Move presets to lax-presets.js to reduce base library size
|
||||
* Implement a tween for scroll wheels to remove reliance on smoothscroll
|
||||
* A way to add weight/momentum to moving objecs
|
||||
* More cool demos
|
||||
* More concise read me for react / vue.js
|
||||
* ~~Support for sprite sheet animations~~
|
||||
|
||||
|
||||
69
dev/inertia.html
Normal 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
@@ -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});
|
||||
66
dev/performance.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!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.style.position = "absolute"
|
||||
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
@@ -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
@@ -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
|
After Width: | Height: | Size: 2.4 KiB |
@@ -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
|
After Width: | Height: | Size: 137 KiB |
BIN
docs/img/bball.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/img/bowser-sprite.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/button-bg.jpg
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
docs/img/l.png
Normal file
|
After Width: | Height: | Size: 237 B |
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 |
BIN
docs/img/mario-foreground.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/img/mario-logo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/img/mario-scrolldown.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/img/mario-sprite.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
docs/img/mario-stars.gif
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/img/nyan.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
@@ -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 |
143
docs/index.html
@@ -9,17 +9,26 @@
|
||||
<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()
|
||||
|
||||
document.addEventListener('scroll', function(x) {
|
||||
lax.update(window.scrollY)
|
||||
}, false)
|
||||
|
||||
lax.update(window.scrollY)
|
||||
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.updateElements()
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -48,8 +57,8 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
margin-top: 20vh;
|
||||
z-index: 2;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bg {
|
||||
@@ -61,12 +70,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;
|
||||
@@ -176,10 +185,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;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -187,34 +198,44 @@
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: white !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: white;
|
||||
color: #35D5E5 !important;
|
||||
color: black !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.github-corner {
|
||||
z-index: 1000;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<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"
|
||||
<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>
|
||||
|
||||
<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>
|
||||
@@ -223,131 +244,135 @@
|
||||
|
||||
<div id="section1" class="section">
|
||||
<div class="left">
|
||||
<div class="bubble a"
|
||||
<div class="lax bubble a"
|
||||
style="background: #EDD943"
|
||||
data-lax-preset="lazy-250"
|
||||
></div>
|
||||
|
||||
<div class="bubble c"
|
||||
<div class="lax bubble c"
|
||||
style="background: #ED2471; margin-left: 80pt"
|
||||
data-lax-preset="lazy-100"
|
||||
></div>
|
||||
|
||||
<div class="bubble b"
|
||||
<div class="lax 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>
|
||||
<h3 data-lax-preset="driftRight" data-lax-optimize=true class="lax chunkyText" style="color: #35D5E5;">oooh!</h3>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<div class="bubble a"
|
||||
<div class="lax bubble a"
|
||||
style="background: #35D5E5; margin-left: 120pt"
|
||||
data-lax-preset="lazy-200"
|
||||
></div>
|
||||
|
||||
<div class="bubble c"
|
||||
<div class="lax bubble c"
|
||||
style="background: #EDD943; margin-left: -20pt"
|
||||
data-lax-preset="lazy-150"
|
||||
></div>
|
||||
|
||||
<div class="bubble b"
|
||||
<div class="lax bubble b"
|
||||
style="background: #ED2471; margin-left: 20pt; margin-top: 200pt"
|
||||
data-lax-preset="lazy-350"
|
||||
></div>
|
||||
<h3 data-lax-preset="driftLeft" class="chunkyText" style="color: #ED2471; margin-top: 200pt;">aaah!</h3>
|
||||
<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="crazyText">sooo crazy</h3>
|
||||
<h3 data-lax-preset="crazy zoomInOut" class="lax crazyText" data-lax-optimize=true>sooo crazy</h3>
|
||||
</div>
|
||||
|
||||
<div id="section2" class="section">
|
||||
<div class="blockContainer" data-lax-preset="leftToRight-1.1 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.2 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.4 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.3 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.05 fadeInOut">
|
||||
<div class="block"
|
||||
<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 fadeInOut" class="chunkyText" style="
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.15 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.45 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.5 fadeInOut">
|
||||
<div class="block"
|
||||
<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="blockContainer" data-lax-preset="leftToRight-1.25 fadeInOut">
|
||||
<div class="block"
|
||||
<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="section">
|
||||
<p data-lax-preset="linger">
|
||||
<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="button" data-lax-preset="linger" href="https://github.com/alexfoxy/laxxx">
|
||||
<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>
|
||||
|
||||
<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
206
docs/sprite.html
Normal 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>
|
||||
381
lib/lax.js
@@ -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!!
|
||||
@@ -19,7 +27,10 @@
|
||||
var lax = {
|
||||
elements: []
|
||||
};
|
||||
var transforms = {
|
||||
var lastY = 0;
|
||||
var currentBreakpoint = 'default';
|
||||
var breakpointsSeparator = "_";
|
||||
var transformFns = {
|
||||
"data-lax-opacity": function dataLaxOpacity(style, v) {
|
||||
style.opacity = v;
|
||||
},
|
||||
@@ -73,12 +84,21 @@
|
||||
},
|
||||
"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 + ", ";
|
||||
for (var i = 0; i < 20; i++) {
|
||||
_crazy += " " + i * 5 + " " + i * 47 % 360 + ", ";
|
||||
}
|
||||
|
||||
lax.presets = {
|
||||
@@ -107,7 +127,7 @@
|
||||
},
|
||||
crazy: function crazy(v) {
|
||||
return {
|
||||
"data-lax-hue-rotate": _crazy
|
||||
"data-lax-hue-rotate": "".concat(_crazy, " | loop=20")
|
||||
};
|
||||
},
|
||||
spin: function spin() {
|
||||
@@ -208,128 +228,307 @@
|
||||
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.addPreset = function (name, o) {
|
||||
lax.presets[name] = o;
|
||||
lax.addPreset = function (p, o) {
|
||||
lax.presets[p] = o;
|
||||
};
|
||||
|
||||
function intrp(table, v) {
|
||||
function intrp(t, v) {
|
||||
var i = 0;
|
||||
|
||||
while (table[i][0] <= v && table[i + 1] !== undefined) {
|
||||
while (t[i][0] <= v && t[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 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;
|
||||
}
|
||||
|
||||
lax.setup = function (o) {
|
||||
lax.populateObjects();
|
||||
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.populateObjects = function () {
|
||||
var selector = Object.keys(transforms).map(function (t) {
|
||||
return "[".concat(t, "]");
|
||||
}).join(",");
|
||||
selector += ",[data-lax-preset]";
|
||||
document.querySelectorAll(selector).forEach(function (el) {
|
||||
var o = {
|
||||
el: el,
|
||||
transforms: []
|
||||
};
|
||||
var presetNames = el.attributes["data-lax-preset"] && el.attributes["data-lax-preset"].value;
|
||||
lax.removeElement = function (el) {
|
||||
var i = lax.elements.findIndex(function (o) {
|
||||
return o.el = el;
|
||||
});
|
||||
|
||||
if (presetNames) {
|
||||
presetNames.split(" ").forEach(function (p) {
|
||||
var bits = p.split("-");
|
||||
var fn = lax.presets[bits[0]];
|
||||
if (i > -1) {
|
||||
lax.elements.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
if (!fn) {
|
||||
console.error("preset #{bits[0]} is not defined");
|
||||
} else {
|
||||
var d = fn(bits[1]);
|
||||
lax.createLaxObject = function (el) {
|
||||
var o = {
|
||||
el: el,
|
||||
originalStyle: {
|
||||
transform: el.style.transform,
|
||||
filter: el.style.filter
|
||||
},
|
||||
transforms: {}
|
||||
};
|
||||
return o;
|
||||
};
|
||||
|
||||
for (var k in d) {
|
||||
el.setAttribute(k, d[k]);
|
||||
}
|
||||
}
|
||||
});
|
||||
el.setAttribute("data-lax-anchor", "self");
|
||||
el.attributes.removeNamedItem("data-lax-preset");
|
||||
lax.calcTransforms = function (o) {
|
||||
var el = o.el; //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
|
||||
|
||||
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");
|
||||
|
||||
for (var i = 0; i < el.attributes.length; i++) {
|
||||
var a = el.attributes[i];
|
||||
var bits = a.name.split("-");
|
||||
var _loop = function _loop(_i2) {
|
||||
var a = presets[_i2];
|
||||
var 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 (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;
|
||||
} 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);
|
||||
if (!fn) {
|
||||
console.log("lax error: preset ".concat(bits[0], " is not defined"));
|
||||
} else {
|
||||
var d = fn(bits[1]);
|
||||
|
||||
for (var k in d) {
|
||||
el.setAttribute("".concat(k).concat(breakpoint), d[k]);
|
||||
}
|
||||
}
|
||||
});
|
||||
el.setAttribute("data-lax-anchor", "self");
|
||||
el.attributes.removeNamedItem(a.name);
|
||||
};
|
||||
|
||||
for (var _i2 = 0; _i2 < presets.length; _i2++) {
|
||||
_loop(_i2);
|
||||
} // 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";
|
||||
}
|
||||
|
||||
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 _i3 = 0; _i3 < el.attributes.length; _i3++) {
|
||||
var _a = el.attributes[_i3];
|
||||
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.anchorTop = Math.floor(rect.top) + window.scrollY;
|
||||
} else {
|
||||
(function () {
|
||||
var tString = _a.value.replace(/vw/g, window.innerWidth).replace(/vh/g, window.innerHeight).replace(/elh/g, el.clientHeight).replace(/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);
|
||||
});
|
||||
}
|
||||
|
||||
var name = b[0];
|
||||
var valueMap = arrString.split(",").map(function (x) {
|
||||
return x.trim().split(" ").map(fnOrVal);
|
||||
}).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
|
||||
|
||||
lax.elements.push(o);
|
||||
});
|
||||
|
||||
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, ")");
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
};
|
||||
|
||||
var lastScroll = 0;
|
||||
lax.populateElements = function () {
|
||||
lax.elements = [];
|
||||
document.querySelectorAll(lax.selector).forEach(function (el) {
|
||||
var o = lax.calcTransforms(lax.createLaxObject(el));
|
||||
lax.elements.push(o);
|
||||
lax.updateElement(o);
|
||||
});
|
||||
currentBreakpoint = lax.getCurrentBreakPoint();
|
||||
};
|
||||
|
||||
lax.updateElements = function () {
|
||||
lax.elements.forEach(function (o) {
|
||||
lax.calcTransforms(o);
|
||||
lax.updateElement(o);
|
||||
});
|
||||
currentBreakpoint = lax.getCurrentBreakPoint();
|
||||
};
|
||||
|
||||
lax.getCurrentBreakPoint = function () {
|
||||
var b = 'default';
|
||||
var w = window.innerWidth;
|
||||
|
||||
for (var _i4 in lax.breakpoints) {
|
||||
var px = parseFloat(lax.breakpoints[_i4]);
|
||||
|
||||
if (px <= w) {
|
||||
b = _i4;
|
||||
} 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: originalStyle.transform,
|
||||
filter: originalStyle.filter
|
||||
};
|
||||
|
||||
for (var _i5 in transforms) {
|
||||
var transformData = transforms[_i5][currentBreakpoint] || transforms[_i5]["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[_i5];
|
||||
var v = intrp(transformData.valueMap, _r);
|
||||
|
||||
if (!t) {
|
||||
// console.info(`lax: error ${i} is not supported`)
|
||||
continue;
|
||||
}
|
||||
|
||||
t(style, v);
|
||||
}
|
||||
|
||||
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) {
|
||||
var momentum = lastScroll - y;
|
||||
lastScroll = y;
|
||||
lax.elements.forEach(function (o) {
|
||||
var transformString = "";
|
||||
var r = o["data-lax-anchor-top"] ? o["data-lax-anchor-top"] - y : y;
|
||||
var style = {
|
||||
transform: "",
|
||||
filter: ""
|
||||
};
|
||||
|
||||
for (var i in o.transforms) {
|
||||
var arr = o.transforms[i];
|
||||
var t = transforms[i];
|
||||
var v = intrp(arr, r);
|
||||
|
||||
if (!t) {
|
||||
console.error("lax: " + i + " is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
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 (lastY === y) return;
|
||||
lastY = y;
|
||||
lax.elements.forEach(lax.updateElement);
|
||||
};
|
||||
|
||||
return lax;
|
||||
|
||||
2
lib/lax.min.js
vendored
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "lax.js",
|
||||
"version": "1.0.2",
|
||||
"version": "1.2.1",
|
||||
"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;"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.2.3",
|
||||
|
||||
397
src/lax.js
@@ -13,38 +13,44 @@
|
||||
// without getting a written permission first.
|
||||
//
|
||||
|
||||
(function() {
|
||||
var lax = (function() {
|
||||
var lax = {
|
||||
(() => {
|
||||
const lax = (() => {
|
||||
const lax = {
|
||||
elements: []
|
||||
}
|
||||
|
||||
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)` },
|
||||
let lastY = 0;
|
||||
let currentBreakpoint = 'default'
|
||||
const breakpointsSeparator = "_"
|
||||
|
||||
"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}%)` },
|
||||
const transformFns = {
|
||||
"data-lax-opacity": (style, v) => { style.opacity = v },
|
||||
"data-lax-translate": (style, v) => { style.transform += ` translate(${v}px, ${v}px)` },
|
||||
"data-lax-translate-x": (style, v) => { style.transform += ` translateX(${v}px)` },
|
||||
"data-lax-translate-y": (style, v) => { style.transform += ` translateY(${v}px)` },
|
||||
"data-lax-scale": (style, v) => { style.transform += ` scale(${v})` },
|
||||
"data-lax-scale-x": (style, v) => { style.transform += ` scaleX(${v})` },
|
||||
"data-lax-scale-y": (style, v) => { style.transform += ` scaleY(${v})` },
|
||||
"data-lax-skew": (style, v) => { style.transform += ` skew(${v}deg, ${v}deg)` },
|
||||
"data-lax-skew-x": (style, v) => { style.transform += ` skewX(${v}deg)` },
|
||||
"data-lax-skew-y": (style, v) => { style.transform += ` skewY(${v}deg)` },
|
||||
"data-lax-rotate": (style, v) => { style.transform += ` rotate(${v}deg)` },
|
||||
"data-lax-brightness": (style, v) => { style.filter += ` brightness(${v}%)` },
|
||||
"data-lax-contrast": (style, v) => { style.filter += ` contrast(${v}%)` },
|
||||
"data-lax-hue-rotate": (style, v) => { style.filter += ` hue-rotate(${v}deg)` },
|
||||
"data-lax-blur": (style, v) => { style.filter += ` blur(${v}px)` },
|
||||
"data-lax-invert": (style, v) => { style.filter += ` invert(${v}%)` },
|
||||
"data-lax-saturate": (style, v) => { style.filter += ` saturate(${v}%)` },
|
||||
"data-lax-grayscale": (style, v) => { style.filter += ` grayscale(${v}%)` },
|
||||
"data-lax-bg-pos": (style, v) => { style.backgroundPosition = `${v}px ${v}px` },
|
||||
"data-lax-bg-pos-x": (style, v) => { style.backgroundPositionX = `${v}px` },
|
||||
"data-lax-bg-pos-y": (style, v) => { style.backgroundPositionY = `${v}px` }
|
||||
}
|
||||
|
||||
let crazy = ""
|
||||
|
||||
for(var i=0;i<100;i++) {
|
||||
crazy += " " + (window.innerHeight*(i/100)) + " " + (Math.random() * 360) + ", "
|
||||
for(let i=0;i<20;i++) {
|
||||
crazy += " " + i*5 + " " + (i*47)%360 + ", "
|
||||
}
|
||||
|
||||
lax.presets = {
|
||||
@@ -61,7 +67,7 @@
|
||||
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 }
|
||||
return { "data-lax-hue-rotate": `${crazy} | loop=20` }
|
||||
},
|
||||
spin: (v=360) => {
|
||||
return { "data-lax-rotate": `(vh) 0, (-elh) ${v}` }
|
||||
@@ -114,138 +120,279 @@
|
||||
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 = (name, o) => {
|
||||
lax.presets[name] = o
|
||||
lax.addPreset = (p, o) => {
|
||||
lax.presets[p] = o
|
||||
}
|
||||
|
||||
function intrp(table, v) {
|
||||
var i = 0
|
||||
function intrp(t, v) {
|
||||
let i = 0
|
||||
|
||||
while(table[i][0] <= v && table[i+1] !== undefined) {
|
||||
while(t[i][0] <= v && t[i+1] !== undefined) {
|
||||
i+=1
|
||||
}
|
||||
|
||||
var x = table[i][0]
|
||||
var prevX = table[i-1] === undefined ? x : table[i-1][0]
|
||||
const x = t[i][0]
|
||||
const prevX = t[i-1] === undefined ? x : t[i-1][0]
|
||||
|
||||
var y = table[i][1]
|
||||
var prevY = table[i-1] === undefined ? y : table[i-1][1]
|
||||
const y = t[i][1]
|
||||
const 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
|
||||
const xPoint = Math.min(Math.max((v-prevX)/(x-prevX),0),1)
|
||||
const yPoint = (xPoint*(y-prevY)) + prevY
|
||||
|
||||
return yPoint
|
||||
}
|
||||
|
||||
lax.setup = function(o) {
|
||||
lax.populateObjects()
|
||||
function fnOrVal(s) {
|
||||
if(s[0] === "(") return eval(s)
|
||||
else return parseFloat(s)
|
||||
}
|
||||
|
||||
lax.populateObjects = function() {
|
||||
var selector = Object.keys(transforms).map(t => `[${t}]`).join(",")
|
||||
selector += ",[data-lax-preset]"
|
||||
lax.setup = (o={}) => {
|
||||
lax.breakpoints = o.breakpoints || {}
|
||||
|
||||
lax.selector = o.selector || '.lax'
|
||||
lax.populateElements()
|
||||
}
|
||||
|
||||
document.querySelectorAll(selector).forEach(function(el) {
|
||||
var o = {
|
||||
el: el,
|
||||
transforms: []
|
||||
}
|
||||
lax.removeElement = (el) => {
|
||||
const i = lax.elements.findIndex(o => o.el = el)
|
||||
if(i > -1) {
|
||||
lax.elements.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
lax.createLaxObject = (el) => {
|
||||
const o = {
|
||||
el: el,
|
||||
originalStyle: {
|
||||
transform: el.style.transform,
|
||||
filter: el.style.filter
|
||||
},
|
||||
transforms: {}
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
lax.calcTransforms = (o) => {
|
||||
const { el } = o
|
||||
|
||||
//find presets in data attributes
|
||||
const presets = []
|
||||
for(let i=0; i<el.attributes.length; i++) {
|
||||
const a = el.attributes[i]
|
||||
if(a.name.indexOf("data-lax-preset") > -1) {
|
||||
presets.push(a);
|
||||
}
|
||||
}
|
||||
|
||||
//unwrap presets into transformations
|
||||
for(let i=0; i<presets.length; i++) {
|
||||
const a = presets[i]
|
||||
const 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(let k in d) {
|
||||
el.setAttribute(`${k}${breakpoint}`, d[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
el.setAttribute("data-lax-anchor", "self")
|
||||
el.attributes.removeNamedItem("data-lax-preset")
|
||||
}
|
||||
el.attributes.removeNamedItem(a.name)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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
|
||||
} 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]
|
||||
})
|
||||
// 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(let i=0; i<el.attributes.length; i++) {
|
||||
const a = el.attributes[i]
|
||||
if(a.name.indexOf("data-lax") < 0) continue
|
||||
|
||||
const b = a.name.split(breakpointsSeparator)
|
||||
const bits = b[0].split("-")
|
||||
const 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(/vw/g, window.innerWidth)
|
||||
.replace(/vh/g, window.innerHeight)
|
||||
.replace(/elh/g, el.clientHeight)
|
||||
.replace(/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)
|
||||
})
|
||||
}
|
||||
|
||||
const name = b[0]
|
||||
const 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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lax.elements.push(o)
|
||||
})
|
||||
// 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})`
|
||||
}
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
var lastScroll = 0
|
||||
lax.populateElements = () => {
|
||||
lax.elements = []
|
||||
|
||||
lax.update = function(y) {
|
||||
var momentum = lastScroll-y
|
||||
lastScroll = y
|
||||
|
||||
lax.elements.forEach(function(o) {
|
||||
var transformString = ""
|
||||
var r = o["data-lax-anchor-top"] ? o["data-lax-anchor-top"]-y : y
|
||||
|
||||
var style = {
|
||||
transform: "",
|
||||
filter: ""
|
||||
}
|
||||
|
||||
for(var i in o.transforms) {
|
||||
var arr = o.transforms[i]
|
||||
var t = transforms[i]
|
||||
var v = intrp(arr, r)
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
document.querySelectorAll(lax.selector).forEach((el) => {
|
||||
const o = lax.calcTransforms(lax.createLaxObject(el))
|
||||
lax.elements.push(o)
|
||||
lax.updateElement(o)
|
||||
})
|
||||
|
||||
|
||||
|
||||
currentBreakpoint = lax.getCurrentBreakPoint()
|
||||
}
|
||||
|
||||
lax.updateElements = () => {
|
||||
lax.elements.forEach((o) => {
|
||||
lax.calcTransforms(o)
|
||||
lax.updateElement(o)
|
||||
})
|
||||
|
||||
currentBreakpoint = lax.getCurrentBreakPoint()
|
||||
}
|
||||
|
||||
|
||||
lax.getCurrentBreakPoint = () => {
|
||||
let b = 'default'
|
||||
const w = window.innerWidth
|
||||
|
||||
for(let i in lax.breakpoints) {
|
||||
const px = parseFloat(lax.breakpoints[i])
|
||||
if(px <= w) {
|
||||
b = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
lax.updateElement = (o) => {
|
||||
const { originalStyle, anchorTop, transforms, spriteData, el } = o
|
||||
|
||||
let r = anchorTop ? anchorTop-lastY : lastY
|
||||
|
||||
const style = {
|
||||
transform: originalStyle.transform,
|
||||
filter: originalStyle.filter
|
||||
}
|
||||
|
||||
for(let 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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lax.update = (y) => {
|
||||
if(lastY === y) return
|
||||
lastY = y
|
||||
lax.elements.forEach(lax.updateElement)
|
||||
}
|
||||
|
||||
return lax;
|
||||
|
||||