├── docs ├── CNAME ├── imgs │ ├── logo.png │ ├── back │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ └── 7.jpg │ └── logo-white.png ├── README.md ├── docs │ ├── #1 - Getting Started.md │ ├── slickScroll.md │ ├── #3 - Easing & Timing.md │ └── #2 - Offsets.md ├── style.min.css ├── index.html ├── style.sass ├── style.css └── slickscroll.min.js ├── .npmignore ├── .gitignore ├── assets └── Logo.png ├── webpack.config.js ├── src ├── struct.ts ├── defaults.ts ├── utils.ts └── index.ts ├── LICENSE.md ├── package.json ├── README.md ├── gulpfile.ts ├── tsconfig.json └── dist ├── slickscroll.es.min.js ├── slickscroll.node.min.js └── slickscroll.min.js /docs/CNAME: -------------------------------------------------------------------------------- 1 | slickscroll.musabhassan.com -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | assets 2 | docs 3 | README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | 4 | builds/ -------------------------------------------------------------------------------- /assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/assets/Logo.png -------------------------------------------------------------------------------- /docs/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/logo.png -------------------------------------------------------------------------------- /docs/imgs/back/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/1.jpg -------------------------------------------------------------------------------- /docs/imgs/back/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/2.jpg -------------------------------------------------------------------------------- /docs/imgs/back/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/3.jpg -------------------------------------------------------------------------------- /docs/imgs/back/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/4.jpg -------------------------------------------------------------------------------- /docs/imgs/back/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/5.jpg -------------------------------------------------------------------------------- /docs/imgs/back/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/6.jpg -------------------------------------------------------------------------------- /docs/imgs/back/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/back/7.jpg -------------------------------------------------------------------------------- /docs/imgs/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Musab-Hassan/slickscrolljs/HEAD/docs/imgs/logo-white.png -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | module: { 5 | rules: [ 6 | { 7 | test: /\.tsx?$/, 8 | use: 'ts-loader', 9 | exclude: /node_modules/, 10 | }, 11 | ], 12 | }, 13 | resolve: { 14 | extensions: ['.tsx', '.ts', '.js'], 15 | } 16 | }; -------------------------------------------------------------------------------- /src/struct.ts: -------------------------------------------------------------------------------- 1 | 2 | // MomentumScroll interface 3 | export interface momentumScrollStruct { 4 | root: string | HTMLElement | HTMLBodyElement | null, 5 | easing?: string, 6 | duration?: number, 7 | fixedOffsets?: string[] | HTMLElement[] | NodeList[] | null[], 8 | offsets?: [{ 9 | element: string | HTMLElement | NodeList | null, 10 | speedY?: number, 11 | speedX?: number 12 | }], 13 | onScroll?(func: () => any): any 14 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | This directory contains the [showcase webpage](http://slickscroll.musabhassan.com) and documentation. 4 | 5 | Detailed documentation can be found in the `docs` directory. 6 | 7 |
8 | 9 | ## Markdown Documentation 10 | 11 | The guides are sorted numerically starting with *docs/#1 - Getting Started*. Documentation of individual functions for quicker overview can be found in files with the function name without numerical prefixes. *docs/momentumScroll.md* contains all the documentation for the `momentumScroll` function. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Musab Hassan 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slickscrolljs", 3 | "version": "2.0.2", 4 | "description": "Lightweight JavaScript library for smooth momentum scrolling and adding scroll based parallax effects", 5 | "module": "dist/slickscroll.es.min.js", 6 | "main": "dist/slickscroll.node.min.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/Musab-Hassan/slickscroll.git" 10 | }, 11 | "homepage": "https://github.com/Musab-Hassan/slickscroll", 12 | "keywords": [ 13 | "slickscroll", 14 | "scroll", 15 | "easing", 16 | "javascript" 17 | ], 18 | "author": "Musab Hassan (https://musab-hassan.github.io)", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "@types/node": "^15.14.9", 22 | "gulp": "^4.0.2", 23 | "gulp-typescript": "^6.0.0-alpha.1", 24 | "ts-loader": "^9.2.6", 25 | "ts-node": "^9.1.1", 26 | "typescript": "^4.5.4", 27 | "webpack": "^5.65.0", 28 | "webpack-cli": "^4.9.1", 29 | "webpack-stream": "^7.0.0" 30 | }, 31 | "scripts": { 32 | "build": "gulp build", 33 | "watch": "gulp watch", 34 | "dev": "gulp dev", 35 | "watch-dev": "gulp watch-dev" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/docs/#1 - Getting Started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | Momentum scrolling is achieved by creating a new instance of `slickScroll`. 4 | 5 | ```javascript 6 | // ES6 7 | new slickScroll(options); 8 | // ES5 & Node 9 | new slickScroll.default(options); 10 | ``` 11 | 12 | For this documentation, the ES6 version will be used for examples however the same applies to ES5 and Node by just replacing `slickScroll` with `slickScroll.default`; 13 | 14 | Here is an example to apply slickscroll to the body. 15 | 16 | ```javascript 17 | let slick = new slickScroll({ 18 | root: "body" 19 | }); 20 | ``` 21 | The root option specifies the element in which the scrolling will be animated. 22 | 23 | *Note: the function will override the overflow property. Overflow must be changed again after initialization by modifying inline styles of the root. The following overflowX modification can only be done after initialization of slickscroll* 24 | ```javascript 25 | document.querySelector("body").style.overflowX = "hidden"; 26 | ``` 27 | 28 |
29 | 30 | ### Destroy 31 | Instances of slickscroll can be destroyed, removing the momentum scrolling effect and reverting the scroll behaviour to the browser default. 32 | 33 | ```javascript 34 | let slick = new slickScroll({ 35 | root: "body", 36 | ... 37 | }); 38 | 39 | slick.destroy(); 40 | ``` 41 | 42 | Next Document. 43 | #### **#2 - Offsets** 44 | -------------------------------------------------------------------------------- /docs/docs/slickScroll.md: -------------------------------------------------------------------------------- 1 | # slickScroll 2 | Allows momentumScrolling and scroll based parallax effects. 3 | 4 | ### Class Overview 5 | ```javascript 6 | new slickScroll(options) 7 | ``` 8 | 9 | ### Parameters 10 | 11 | - options `Object` - *options for momentum scrolling* 12 | 13 | Name | Type | Required | Default | Description 14 | | - | - | - | - | - | 15 | root | *String \| HTMLElement* | Yes | `body` | Element to apply momentum scroll on 16 | easing | *String* | No | `cubicBezier(0.15, 1, 0.4, 1)` | Easing function 17 | duration | *Number* | No | `1000` | Duration of easing in milliseconds 18 | fixedOffsets | *String[] \| HTMLElement[]* | No | - | Array of position:fixed elements 19 | offsets | *Object[]* | No | - | Array of elements with custom speeds (See ***#2-Offsets.md***) 20 | onScroll | *Function* | No | - | Scroll listener for root element 21 | 22 | ### Returns 23 | 24 | - addOffset `Method` - *Add offset (element with custom speed)* 25 | 26 | **Parameters** 27 | - offset `Object` - *Refer to **#2-Offsets.md** * 28 | 29 | - element `String` | `HTMLElement` - *Element to be added as an offset* 30 | - speedX `Number` - *overflow-x speed (Optional)* 31 | - speedY `Number` - *overflow-y speed (Optional)* 32 | 33 |
34 | 35 | - addFixedOffset `Method` - *Add fixed offset (element with fixed position)* 36 | 37 | **Parameters** 38 | - element `String` | `HTMLElement` - *Element to be added as a fixed offset* 39 | 40 |
41 | 42 | - removeOffset `Method` - *Removes an offset or fixedOffset* 43 | 44 | **Parameters** 45 | - element `String` | `HTMLElement` - *Offset name or node to be removed* 46 | 47 |
48 | 49 | - destroy `Method` - *Disables scroll effects for instance and reverts scrolling to original behaviour* 50 | -------------------------------------------------------------------------------- /src/defaults.ts: -------------------------------------------------------------------------------- 1 | 2 | /* Default values and properties */ 3 | 4 | 5 | // Default properties for momentumScrollStruct 6 | export const defaults: { root: any, duration: number, easing: string, offsets: any[], fixedOffsets: any[] } = { 7 | root: "body", 8 | duration: 1000, 9 | easing: "cubic-bezier(0.15, 1, 0.4, 1)", 10 | offsets: [], 11 | fixedOffsets: [] 12 | } 13 | 14 | // Default offset speeds 15 | export const defaultSpeeds: { speedY: number, speedX: number } = { 16 | speedY: 1, 17 | speedX: 1 18 | } 19 | 20 | // Default pennerEasings 21 | export const pennerEasings: { name: string, value: number[] } [] = [ 22 | // Sine 23 | { name: "easeInSine", value: [0.12, 0, 0.39, 0] }, 24 | { name: "easeOutSine", value: [0.61, 1, 0.88, 1] }, 25 | { name: "easeInOutSine", value: [0.37, 0, 0.63, 1] }, 26 | // Quad 27 | { name: "easeInQuad", value: [0.11, 0, 0.5, 0] }, 28 | { name: "easeOutQuad", value: [0.5, 1, 0.89, 1] }, 29 | { name: "easeInOutQuad", value: [0.45, 0, 0.55, 1] }, 30 | // Cubic 31 | { name: "easeInCubic", value: [0.32, 0, 0.67, 0] }, 32 | { name: "easeOutCubic", value: [0.33, 1, 0.68, 1] }, 33 | { name: "easeInOutCubic", value: [0.65, 0, 0.35, 1] }, 34 | // Quart 35 | { name: "easeInQuart", value: [0.5, 0, 0.75, 0] }, 36 | { name: "easeOutQuart", value: [0.25, 1, 0.5, 1] }, 37 | { name: "easeInOutQuart", value: [0.76, 0, 0.24, 1] }, 38 | // Quint 39 | { name: "easeInQuint", value: [0.64, 0, 0.78, 0] }, 40 | { name: "easeOutQuint", value: [0.22, 1, 0.36, 1] }, 41 | { name: "easeInOutQuint", value: [0.83, 0, 0.17, 1] }, 42 | // Expo 43 | { name: "easeInExpo", value: [0.7, 0, 0.84, 0] }, 44 | { name: "easeOutExpo", value: [0.16, 1, 0.3, 1] }, 45 | { name: "easeInOutExpo", value: [0.87, 0, 0.13, 1] }, 46 | // Circ 47 | { name: "easeInCirc", value: [0.55, 0, 1, 0.45] }, 48 | { name: "easeOutCirc", value: [0, 0.55, 0.45, 1] }, 49 | { name: "easeInOutCirc", value: [0.85, 0, 0.15, 1] } 50 | ]; -------------------------------------------------------------------------------- /docs/docs/#3 - Easing & Timing.md: -------------------------------------------------------------------------------- 1 | # Easing 2 | The momentumScroll function's timing and easing can also be changed. SlickScroll uses the same timing and easing functions as the CSS transform property. 3 | 4 | ### Easing 5 | 6 | Slickscroll supports Cubic Beziers and the Penner Easing functions for easing. 7 | 8 | The default easing function is `cubicBezier(0.15, 1, 0.4, 1)` which can be changed by modifying the `easing` option. 9 | 10 | Penner Functions can be used. 11 | ```javascript 12 | new slickscroll({ 13 | root: "body", 14 | easing: "easeInOutSine" 15 | }) 16 | ``` 17 | 18 | Cubic Beziers can also be used. 19 | ```javascript 20 | new slickScroll({ 21 | root: "body", 22 | easing: "cubicBezier(.56, .09, .89, .29)", 23 | }) 24 | ``` 25 | 26 | ### Penner Functions 27 | 28 | List of Penner functions slickScroll supports: 29 | 30 | Ease In | Ease Out | Ease In Out 31 | | - | - | - | 32 | easeInSine | easeOutSine | easeInOutSine 33 | easeInQuad | easeOutQuad | easeInOutQuad 34 | easeInCubic | easeOutCubic | easeInOutCubic 35 | easeInQuart | easeOutQuart | easeInOutQuart 36 | easeInQuint | easeOutQuint | easeInOutQuint 37 | easeInExpo | easeOutExpo | easeInOutExpo 38 | easeInCirc | easeOutCirc | easeInOutCirc 39 | 40 | 41 | # Timing 42 | 43 | Along with easing, the duration can also be changed to modify the scroll speed. 44 | 45 | The default duration is 1000ms (1s). To set a different duration, the `duration` option can be changed with a value in milliseconds. 46 | 47 | In this example, the duration is set to 2.5 seconds. 48 | ```javascript 49 | new slickScroll({ 50 | root: "body", 51 | duration: 2500 52 | }); 53 | ``` 54 | 55 | 56 | # Quick Overview 57 | 58 | Easings can be modified through the `easing` option. 59 | 60 | ```javascript 61 | new slickScroll({ 62 | easing: String // Penner function name or bezier curve 63 | }); 64 | ``` 65 | Default value: `cubicBezier(0.15, 1, 0.4, 1)` 66 | 67 | The scroll animation duration can be modified with the `duration` option. 68 | 69 | ```javascript 70 | new slickScroll({ 71 | duration: Number // Time in miliseconds 72 | )}; 73 | ``` 74 | Default value: `1000` 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | Slickscroll is a JavaScript library that makes momentum & parallax scrolling quick and painless 6 | 7 | [![NPM version](http://img.shields.io/npm/v/slickscrolljs.svg?style=for-the-badge&logo=npm)](https://www.npmjs.org/package/slickscrolljs) [![NPM license](http://img.shields.io/npm/l/slickscrolljs.svg?style=for-the-badge)](https://www.npmjs.org/package/slickscrolljs) 8 | 9 | **View Demo: [slickscroll.musabhassan.com](https://slickscroll.musabhassan.com)** 10 | 11 |
12 | Momentum Scrolling
13 | Momentum Scrolling is the smooth and eased scrolling fancy websites have to allow the page to flow smoothly when scrolling. 14 |

15 | 16 | 17 | ## Download & Setup 18 | 19 | ### Download 20 | Manually download from *Releases*, from the `dist` directory, or npm. 21 | 22 | npm 23 | ``` 24 | npm install --save slickscrolljs 25 | ``` 26 | 27 | ### Setup 28 | 29 | This setup will just apply momentum scrolling to the body 30 | 31 | ES6 import 32 | ```javascript 33 | import slickScroll from './slickscroll.es.min.js'; 34 | 35 | const slick = new slickScroll({ 36 | root: "body" 37 | }); 38 | ``` 39 | 40 | HTML script tag 41 | ```html 42 | 43 | 44 | 51 | ``` 52 | 53 | Node require 54 | ```javascript 55 | const slickScroll = require('slickscrolljs'); 56 | 57 | const slick = new slickScroll.default({ 58 | root: "body" 59 | }); 60 | ``` 61 | 62 | ## Hello World 63 | The hello world will apply the momentum scrolling to the element you specify. 64 | ```javascript 65 | new slickScroll({ 66 | root: "body" 67 | }) 68 | ``` 69 | The overflow property of the `root` element will be overridden with `auto` upon initialization of slickscroll. If you wish to change overflow to anything else, you must modify it after the initialization. 70 | 71 | Momentum scrolling applies to both x and y axis of an element. If you wish for an axis to not scroll, change it's overflow value to `hidden` after slickscroll initialization. 72 | 73 | Example to hide overflow-x after initializing up slickscroll; 74 | 75 | ```javascript 76 | const slick = new slickScroll.default({ 77 | root: "body" 78 | }); 79 | 80 | document.body.style.overflowX = "hidden"; 81 | ``` 82 | 83 | All the valid options aswell as documentation and Getting Started can be found in the `docs` directory. 84 | 85 | ## Browser Support 86 | 87 | Browser | Version 88 | | - | - | 89 | Chrome | 61+ 90 | Edge | 80+ 91 | IE | 11 92 | Firefox | 48+ 93 | Opera | 48+ 94 | Safari | 12+ 95 | 96 | ### Contributors 97 | Musab-Hassan 98 | 99 | ### License 100 | MIT license. 101 | -------------------------------------------------------------------------------- /docs/style.min.css: -------------------------------------------------------------------------------- 1 | @import url("https://use.typekit.net/gey1gtp.css");*{margin:0;padding:0}html{overflow:hidden !important}body{background-color:#1C1C1C;overflow-x:hidden !important;height:100vh}.page-cover{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#1C1C1C;color:#fff;text-align:center;display:flex;flex-direction:column;justify-content:center;padding:20px;box-sizing:border-box;z-index:100}.page-cover.mobile{display:none}@media only screen and (max-width: 700px){.page-cover.mobile{display:flex !important}}.page-cover .cover-title{font-family:"Proxima-nova",sans-serif;text-transform:uppercase;font-size:2em}.nav-container{display:flex;justify-content:stretch;position:fixed;top:0;left:0;width:100%;padding:0 4vw;margin-top:6vh;box-sizing:border-box;background-color:transparent;z-index:20}.nav-container .align{flex-grow:1}.nav-container .align.left .logo{height:3em}.nav-container .align.right{text-align:right;color:white;display:flex;flex-direction:column;justify-content:center}.nav-container .align.right ul{list-style-type:none}.nav-container .align.right ul li{display:inline-block;margin-left:2em}#landing.section{width:100vw;height:100vh;display:flex;flex-direction:column;justify-content:center;position:relative}#landing.section .back-image{position:absolute;left:0;right:0;margin-left:auto;margin-right:auto;text-align:center;z-index:-1}#landing.section .back-image img{height:70vh;border-radius:40px;box-shadow:5px 5px 10px rgba(0,0,0,0.4);transform:rotate(15deg);-webkit-transform:rotate(15deg)}#landing.section .align-wrapper{width:100%;text-align:center}#landing.section .align-wrapper .content{width:60%;margin:0 auto;text-align:center}#landing.section .align-wrapper .content *{margin-bottom:5vh}#content.section{position:relative;width:100vw;padding:0 10vw;margin-top:15vh;box-sizing:border-box}#content.section .back-image-slide{position:absolute;text-align:center;left:-20vw;right:-20vw;top:-10vh;z-index:-1}#content.section .back-image-slide .stack{display:inline-block}#content.section .back-image-slide .stack.offset{position:relative;top:10vh;opacity:0.4}#content.section .back-image-slide .stack:not(:last-child){margin-right:5vh}#content.section .back-image-slide img{display:block;height:40vh;width:35vw;object-fit:cover;opacity:0.3;border-radius:30px;margin-bottom:8vh}#content.section .aligner{width:100%;display:flex;flex-direction:column;justify-content:center}#content.section .aligner .right,#content.section .aligner .left{display:block;margin-bottom:15vh}#content.section .aligner .right .button,#content.section .aligner .left .button{margin-top:5vh}#content.section .aligner .right .heart,#content.section .aligner .left .heart{position:relative;top:50%;left:0.2em;fill:#FF5722;transform:translateY(30%);width:1.7em}#content.section .aligner .right{align-self:flex-end;text-align:right}.button{display:inline-block;font-size:1em;letter-spacing:0.07em;font-family:"Proxima-nova",sans-serif;text-transform:uppercase;font-weight:800;padding:0.8em 2em;box-sizing:border-box;text-decoration:none;color:#1C1C1C;cursor:pointer;border-radius:60px;background-color:#77FF65;transition:transform 0.3s cubic-bezier(0.68, -0.6, 0.32, 1.6)}.button:hover{transform:scale(1.08)}.sublink,.subtext{position:relative;font-size:1em;letter-spacing:0.07em;font-family:"Proxima-nova",sans-serif;text-transform:uppercase;text-decoration:none;font-weight:800;color:#fff}.sublink{cursor:pointer}.sublink::before{content:"";position:absolute;width:100%;height:2px;bottom:0;left:0;background-color:#fff;transform:scaleX(0);transition:all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6);-webkit-transform:scaleX(0);-webkit-transition:all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6)}.sublink:hover::before{transform:scaleX(1)}.sublink span{color:#84f397}.title{font-size:4em;letter-spacing:0.03em;color:#fff;font-family:"Proxima-nova",sans-serif;text-transform:uppercase;font-weight:800}.title span{color:#84f397}h2,h3{font-size:3.8em;letter-spacing:0.03em;color:#fff;font-family:"Proxima-nova",sans-serif;text-transform:uppercase;font-weight:800}h2 span,h3 span{color:#77FF65}h3{font-weight:200;font-size:3.5em}h3 span{font-weight:800} 2 | -------------------------------------------------------------------------------- /gulpfile.ts: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * 3 | * Build production builds with 'npm run build' 4 | * Watch to build for production with 'npm run watch' 5 | * Build dev builds with 'npm run dev' 6 | * Watch to build dev builds with 'npm run watch-dev' 7 | * 8 | ***************************************/ 9 | 10 | 11 | const { src, dest, task, parallel, watch } = require('gulp'); 12 | const webpack = require("webpack-stream"); 13 | 14 | const webpackConfig = require('./webpack.config.js'); 15 | 16 | /* Production Builds */ 17 | const buildES6 = function() { 18 | 19 | let config = {...webpackConfig, ...{ 20 | mode: "production", 21 | experiments: { 22 | outputModule: true, 23 | }, 24 | output: { 25 | filename: 'slickscroll.es.min.js', 26 | library: { 27 | type: 'module' 28 | } 29 | } 30 | }}; 31 | 32 | return src("src/index.ts") 33 | .pipe(webpack(config)) 34 | .pipe(dest("dist/")) 35 | } 36 | 37 | const buildES5 = function() { 38 | let config = { 39 | ...webpackConfig, ...{ 40 | mode: "production", 41 | output: { 42 | filename: 'slickscroll.min.js', 43 | library: { 44 | name: "slickScroll", 45 | type: 'var' 46 | } 47 | } 48 | } 49 | }; 50 | 51 | return src("src/index.ts") 52 | .pipe(webpack(config)) 53 | .pipe(dest("dist/")) 54 | } 55 | 56 | const buildNode = function() { 57 | let config = { 58 | ...webpackConfig, ...{ 59 | mode: "production", 60 | output: { 61 | filename: 'slickscroll.node.min.js', 62 | library: { 63 | name: "slickScroll", 64 | type: 'commonjs' 65 | } 66 | } 67 | } 68 | }; 69 | 70 | return src("src/index.ts") 71 | .pipe(webpack(config)) 72 | .pipe(dest("dist/")) 73 | } 74 | 75 | task("build", parallel(buildES5, buildES6, buildNode)); 76 | task('watch', function () { 77 | watch('src/**', parallel(buildES5, buildES6, buildNode)); 78 | }); 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | /* Dev Builds */ 90 | const buildES6Dev = function () { 91 | 92 | let config = { 93 | ...webpackConfig, ...{ 94 | mode: "development", 95 | devtool: "source-map", 96 | experiments: { 97 | outputModule: true, 98 | }, 99 | output: { 100 | filename: 'build.es.js', 101 | library: { 102 | type: 'module' 103 | } 104 | } 105 | } 106 | }; 107 | 108 | return src("src/index.ts") 109 | .pipe(webpack(config)) 110 | .pipe(dest("builds/")) 111 | } 112 | 113 | const buildES5Dev = function () { 114 | let config = { 115 | ...webpackConfig, ...{ 116 | mode: "development", 117 | devtool: "source-map", 118 | output: { 119 | filename: 'build.js', 120 | library: { 121 | name: "slickScroll", 122 | type: 'var' 123 | } 124 | } 125 | } 126 | }; 127 | 128 | return src("src/index.ts") 129 | .pipe(webpack(config)) 130 | .pipe(dest("builds/")) 131 | } 132 | 133 | const buildNodeDev = function () { 134 | let config = { 135 | ...webpackConfig, ...{ 136 | mode: "development", 137 | devtool: "source-map", 138 | output: { 139 | filename: 'build.node.js', 140 | library: { 141 | name: "slickScroll", 142 | type: 'commonjs' 143 | } 144 | } 145 | } 146 | }; 147 | 148 | return src("src/index.ts") 149 | .pipe(webpack(config)) 150 | .pipe(dest("builds/")) 151 | } 152 | 153 | task("dev", parallel(buildES5Dev, buildES6Dev, buildNodeDev)); 154 | task('watch-dev', function () { 155 | watch('src/**', parallel(buildES5Dev, buildES6Dev, buildNodeDev)); 156 | }); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SlickScroll - Momentum Scrolling JS library 9 | 10 | 11 | 12 | 13 | 14 | 15 | 32 | 33 | 34 | 35 | 40 | 41 | 42 |
43 |

This webpage is best seen on a desktop or a laptop.

Slickscroll still works on mobile, however this webpage doesn't.

44 |
45 | 46 | 47 | 58 | 59 | 60 |
61 |
62 | 63 |
64 |
65 |
66 |

67 | A JavaScript Library that makes momentum scrolling quick and painless. 68 |

69 | Read the docs 70 |
71 |
72 |
73 | 74 | 75 |
76 |
77 |
78 | 79 | 80 |
81 |
82 | 83 | 84 |
85 |
86 | 87 | 88 |
89 |
90 |
91 |
92 |

Supports Vertical &
Horizontal Scrolling

93 |
94 |
95 |

Offset Speeds for
making it Parallax

96 |
97 |
98 |

Lightweight
with no gimmicks

99 |
100 |
101 |

Open Source,
check it out on Github

102 | View on Github 103 |
104 |
105 |

Made by Musab Hassan with 106 | 107 | 109 | 110 |

111 |
112 |
113 |
114 | 115 | -------------------------------------------------------------------------------- /docs/docs/#2 - Offsets.md: -------------------------------------------------------------------------------- 1 | # Offsets 2 | 3 | SlickScroll supports both momentum scrolling and parallax scrolling. Offsets allow the scrolling speed of elements to be changed creating a parallax scrolling effect. 4 | 5 |
6 | Parallax scrolling is when some elements move slower than others giving the illusion of depth allowing a webpage to look 3 dimensional without actually containing anything 3D. 7 |

8 | 9 | The [slickscroll webpage](https://slickscroll.musabhassan.com) demonstrates parallax scrolling with the slower moving images in the back. 10 | 11 | The following is an example that demonstrates how to setup offsets. 12 | 13 | ```html 14 | 15 |
...
16 |
17 | SlickScroll offsets guide 18 |
19 | 20 | ``` 21 | 22 | To give the `#back-image` element 80% of the vertical scrolling speed, the following options can be used. 23 | 24 | ```javascript 25 | new slickScroll({ 26 | root: "body", 27 | offsets: [ 28 | { 29 | element: "#back-image", 30 | speedY: 0.8 // Vertical speed 31 | } 32 | ] 33 | }) 34 | ``` 35 | The back image now moves slower than the content in front of it creating a parallax effect. 36 | 37 | **Note: The offset element must be inside the root element for it to work correctly. In the example above, `#back-image` is inside the root element `body`.** 38 | 39 | 40 | # Fixed Offsets 41 | Since slickScroll's momentum scrolling transforms the root element, fixed elements inside the root element no longer work. For fixed elements use fixedOffsets. 42 | 43 | Example: 44 | 45 | ```html 46 | 47 | 48 |
49 | SlickScroll fixed offsets guide 50 |
51 | 52 | ``` 53 | ```css 54 | #nav-bar { 55 | position: fixed; 56 | ... 57 | } 58 | ``` 59 | ```javascript 60 | new slickscroll({ 61 | root: "body", 62 | }); 63 | ``` 64 | In this example, the fixed `#nav-bar` will not stay fixed as it is inside the moving root element. To make it fixed, it must be made a fixedOffset. The following is the correct way of making `#nav-bar` fixed. 65 | 66 | ```javascript 67 | new slickScroll({ 68 | root: "body", 69 | fixedOffets: [` 70 | "#nav-bar" 71 | ] 72 | }); 73 | ``` 74 | Now `#nav-bar` will behave like a `position: fixed` element. 75 | 76 | # Dynamically Adding Offsets 77 | Offsets and fixedOffsets can also be added after class initialization dynamically. They can also be removed if no longer needed. 78 | 79 | In this example there is an instance of momentumScroll with default options on the body. 80 | ```javascript 81 | let slick = new slickScroll({ 82 | root: document.body, 83 | }); 84 | ``` 85 | with the following markup. 86 | ```html 87 | 88 |
...
89 | 90 |
91 | SlickScroll offsets guide 92 |
93 | 94 | ``` 95 | If we want to make the `#back-image` an offset and the `#nav-bar` a fixedOffset later somewhere, we can just add them dynamically later. 96 | 97 | To add `#back-image` as an offset dynamically, `addOffset` can be used: 98 | ```javascript 99 | slick.addOffset({ 100 | element: "#back-image", 101 | speedY: 0.8 102 | }) 103 | ``` 104 | To add `#nav-bar` as a fixedOffset dynamically, `addFixedOffset` can be used we use: 105 | ```javascript 106 | slick.addFixedOffset("#nav-bar"); 107 | ``` 108 | 109 | Elements that are added as offsets dynamically behave just like offsets added during initialization. Both fixedOffsets and offsets can also be removed with the `removeOffset` method. 110 | 111 | To remove `#nav-bar` from fixedOffsets and `#back-image` from offsets, the `removeOffset` method can be used. 112 | 113 | ```javascript 114 | slick.removeOffset("#nav-bar"); 115 | slick.removeOffset("#back-image"); 116 | ``` 117 | 118 | 119 | 120 | # Quick Overview 121 | 122 | ### Offsets 123 | 124 | The structure of the offsets option 125 | ```javascript 126 | let slick = new slickScroll({ 127 | offsets: [ 128 | { 129 | element: String | DOMElement, // Element name 130 | speedX: Number, // % of root horizontal scroll speed 131 | speedY: Number // % of root vertical scroll speed 132 | } 133 | ] 134 | }) 135 | ``` 136 | Offsets can be added dynamically after intialization through `addOffset()`. 137 | ```javascript 138 | slick.addOffset({ 139 | element: String | DOMElement, 140 | speedX: Number, 141 | speedY: Number 142 | }) 143 | ``` 144 | 145 | ### Fixed Offsets 146 | 147 | The structure of the fixedOffsets option 148 | ```javascript 149 | let slick = new slickScroll({ 150 | fixedOffsets: String[] | DOMElement[] 151 | }) 152 | ``` 153 | Fixed offsets can be added dynamically after initialization through `addFixedOffset()`. 154 | ```javascript 155 | slick.addFixedOffset(String | DOMElement); 156 | ``` 157 | 158 | Both offsets and fixedOffsets can be removed dynamically through 159 | ```javascript 160 | slick.removeOffest(String | DOMElement); 161 | ``` 162 | 163 | 164 | Next Document. 165 | #### **#3 - Easing & Timing** -------------------------------------------------------------------------------- /docs/style.sass: -------------------------------------------------------------------------------- 1 | @import url("https://use.typekit.net/gey1gtp.css") 2 | 3 | $primaryColor: #77FF65 4 | $secondaryColor: #84f397 5 | $inkColor: #1C1C1C 6 | $invColor: white 7 | $font: "Proxima-nova", sans-serif 8 | 9 | * 10 | margin: 0 11 | padding: 0 12 | 13 | html 14 | overflow: hidden !important 15 | 16 | body 17 | background-color: $inkColor 18 | overflow-x: hidden !important 19 | height: 100vh 20 | 21 | 22 | .page-cover 23 | position: fixed 24 | top: 0 25 | left: 0 26 | width: 100% 27 | height: 100% 28 | background-color: $inkColor 29 | color: $invColor 30 | text-align: center 31 | display: flex 32 | flex-direction: column 33 | justify-content: center 34 | padding: 20px 35 | box-sizing: border-box 36 | z-index: 100 37 | 38 | &.mobile 39 | display: none 40 | 41 | @media only screen and (max-width: 700px) 42 | &.mobile 43 | display: flex !important 44 | 45 | .cover-title 46 | font-family: $font 47 | text-transform: uppercase 48 | font-size: 2em 49 | 50 | 51 | .nav-container 52 | display: flex 53 | justify-content: stretch 54 | position: fixed 55 | top: 0 56 | left: 0 57 | width: 100% 58 | padding: 0 4vw 59 | margin-top: 6vh 60 | box-sizing: border-box 61 | background-color: transparent 62 | z-index: 20 63 | 64 | .align 65 | flex-grow: 1 66 | 67 | &.left 68 | .logo 69 | height: 3em 70 | 71 | &.right 72 | text-align: right 73 | color: white 74 | display: flex 75 | flex-direction: column 76 | justify-content: center 77 | 78 | ul 79 | list-style-type: none 80 | 81 | li 82 | display: inline-block 83 | margin-left: 2em 84 | 85 | #landing.section 86 | width: 100vw 87 | height: 100vh 88 | display: flex 89 | flex-direction: column 90 | justify-content: center 91 | position: relative 92 | 93 | .back-image 94 | position: absolute 95 | left: 0 96 | right: 0 97 | margin-left: auto 98 | margin-right: auto 99 | text-align: center 100 | z-index: -1 101 | 102 | img 103 | height: 70vh 104 | border-radius: 40px 105 | box-shadow: 5px 5px 10px rgba(0,0,0,0.4) 106 | transform: rotate(15deg) 107 | -webkit-transform: rotate(15deg) 108 | 109 | .align-wrapper 110 | width: 100% 111 | text-align: center 112 | 113 | .content 114 | width: 60% 115 | margin: 0 auto 116 | text-align: center 117 | 118 | * 119 | margin-bottom: 5vh 120 | 121 | #content.section 122 | position: relative 123 | width: 100vw 124 | padding: 0 10vw 125 | margin-top: 15vh 126 | box-sizing: border-box 127 | 128 | .back-image-slide 129 | position: absolute 130 | text-align: center 131 | left: -20vw 132 | right: -20vw 133 | top: -10vh 134 | z-index: -1 135 | 136 | .stack 137 | display: inline-block 138 | 139 | &.offset 140 | position: relative 141 | top: 10vh 142 | opacity: 0.4 143 | 144 | &:not(:last-child) 145 | margin-right: 5vh 146 | 147 | img 148 | display: block 149 | height: 40vh 150 | width: 35vw 151 | object-fit: cover 152 | opacity: 0.3 153 | border-radius: 30px 154 | margin-bottom: 8vh 155 | 156 | .aligner 157 | width: 100% 158 | display: flex 159 | flex-direction: column 160 | justify-content: center 161 | 162 | .right,.left 163 | display: block 164 | margin-bottom: 15vh 165 | 166 | .button 167 | margin-top: 5vh 168 | 169 | .heart 170 | position: relative 171 | top: 50% 172 | left: 0.2em 173 | fill: #FF5722 174 | transform: translateY(30%) 175 | width: 1.7em 176 | 177 | .right 178 | align-self: flex-end 179 | text-align: right 180 | 181 | 182 | .button 183 | display: inline-block 184 | font-size: 1em 185 | letter-spacing: 0.07em 186 | font-family: $font 187 | text-transform: uppercase 188 | font-weight: 800 189 | padding: 0.8em 2em 190 | box-sizing: border-box 191 | text-decoration: none 192 | color: $inkColor 193 | cursor: pointer 194 | border-radius: 60px 195 | background-color: $primaryColor 196 | transition: transform 0.3s cubic-bezier(0.68, -0.6, 0.32, 1.6) 197 | 198 | &:hover 199 | transform: scale(1.08) 200 | 201 | .sublink, .subtext 202 | position: relative 203 | font-size: 1em 204 | letter-spacing: 0.07em 205 | font-family: $font 206 | text-transform: uppercase 207 | text-decoration: none 208 | font-weight: 800 209 | color: $invColor 210 | 211 | .sublink 212 | cursor: pointer 213 | 214 | &::before 215 | content: "" 216 | position: absolute 217 | width: 100% 218 | height: 2px 219 | bottom: 0 220 | left: 0 221 | background-color: $invColor 222 | transform: scaleX(0) 223 | transition: all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6) 224 | -webkit-transform: scaleX(0) 225 | -webkit-transition: all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6) 226 | 227 | &:hover::before 228 | transform: scaleX(1) 229 | 230 | 231 | span 232 | color: $secondaryColor 233 | 234 | .title 235 | font-size: 4em 236 | letter-spacing: 0.03em 237 | color: $invColor 238 | font-family: $font 239 | text-transform: uppercase 240 | font-weight: 800 241 | 242 | span 243 | color: $secondaryColor 244 | 245 | h2,h3 246 | font-size: 3.8em 247 | letter-spacing: 0.03em 248 | color: $invColor 249 | font-family: $font 250 | text-transform: uppercase 251 | font-weight: 800 252 | 253 | span 254 | color: $primaryColor 255 | 256 | h3 257 | font-weight: 200 258 | font-size: 3.5em 259 | 260 | span 261 | font-weight: 800 262 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://use.typekit.net/gey1gtp.css"); 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | html { 8 | overflow: hidden !important; 9 | } 10 | 11 | body { 12 | background-color: #1C1C1C; 13 | overflow-x: hidden !important; 14 | height: 100vh; 15 | } 16 | 17 | .page-cover { 18 | position: fixed; 19 | top: 0; 20 | left: 0; 21 | width: 100%; 22 | height: 100%; 23 | background-color: #1C1C1C; 24 | color: white; 25 | text-align: center; 26 | display: flex; 27 | flex-direction: column; 28 | justify-content: center; 29 | padding: 20px; 30 | box-sizing: border-box; 31 | z-index: 100; 32 | } 33 | 34 | .page-cover.mobile { 35 | display: none; 36 | } 37 | 38 | @media only screen and (max-width: 700px) { 39 | .page-cover.mobile { 40 | display: flex !important; 41 | } 42 | } 43 | 44 | .page-cover .cover-title { 45 | font-family: "Proxima-nova", sans-serif; 46 | text-transform: uppercase; 47 | font-size: 2em; 48 | } 49 | 50 | .nav-container { 51 | display: flex; 52 | justify-content: stretch; 53 | position: fixed; 54 | top: 0; 55 | left: 0; 56 | width: 100%; 57 | padding: 0 4vw; 58 | margin-top: 6vh; 59 | box-sizing: border-box; 60 | background-color: transparent; 61 | z-index: 20; 62 | } 63 | 64 | .nav-container .align { 65 | flex-grow: 1; 66 | } 67 | 68 | .nav-container .align.left .logo { 69 | height: 3em; 70 | } 71 | 72 | .nav-container .align.right { 73 | text-align: right; 74 | color: white; 75 | display: flex; 76 | flex-direction: column; 77 | justify-content: center; 78 | } 79 | 80 | .nav-container .align.right ul { 81 | list-style-type: none; 82 | } 83 | 84 | .nav-container .align.right ul li { 85 | display: inline-block; 86 | margin-left: 2em; 87 | } 88 | 89 | #landing.section { 90 | width: 100vw; 91 | height: 100vh; 92 | display: flex; 93 | flex-direction: column; 94 | justify-content: center; 95 | position: relative; 96 | } 97 | 98 | #landing.section .back-image { 99 | position: absolute; 100 | left: 0; 101 | right: 0; 102 | margin-left: auto; 103 | margin-right: auto; 104 | text-align: center; 105 | z-index: -1; 106 | } 107 | 108 | #landing.section .back-image img { 109 | height: 70vh; 110 | border-radius: 40px; 111 | box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.4); 112 | transform: rotate(15deg); 113 | -webkit-transform: rotate(15deg); 114 | } 115 | 116 | #landing.section .align-wrapper { 117 | width: 100%; 118 | text-align: center; 119 | } 120 | 121 | #landing.section .align-wrapper .content { 122 | width: 60%; 123 | margin: 0 auto; 124 | text-align: center; 125 | } 126 | 127 | #landing.section .align-wrapper .content * { 128 | margin-bottom: 5vh; 129 | } 130 | 131 | #content.section { 132 | position: relative; 133 | width: 100vw; 134 | padding: 0 10vw; 135 | margin-top: 15vh; 136 | box-sizing: border-box; 137 | } 138 | 139 | #content.section .back-image-slide { 140 | position: absolute; 141 | text-align: center; 142 | left: -20vw; 143 | right: -20vw; 144 | top: -10vh; 145 | z-index: -1; 146 | } 147 | 148 | #content.section .back-image-slide .stack { 149 | display: inline-block; 150 | } 151 | 152 | #content.section .back-image-slide .stack.offset { 153 | position: relative; 154 | top: 10vh; 155 | opacity: 0.4; 156 | } 157 | 158 | #content.section .back-image-slide .stack:not(:last-child) { 159 | margin-right: 5vh; 160 | } 161 | 162 | #content.section .back-image-slide img { 163 | display: block; 164 | height: 40vh; 165 | width: 35vw; 166 | object-fit: cover; 167 | opacity: 0.3; 168 | border-radius: 30px; 169 | margin-bottom: 8vh; 170 | } 171 | 172 | #content.section .aligner { 173 | width: 100%; 174 | display: flex; 175 | flex-direction: column; 176 | justify-content: center; 177 | } 178 | 179 | #content.section .aligner .right, #content.section .aligner .left { 180 | display: block; 181 | margin-bottom: 15vh; 182 | } 183 | 184 | #content.section .aligner .right .button, #content.section .aligner .left .button { 185 | margin-top: 5vh; 186 | } 187 | 188 | #content.section .aligner .right .heart, #content.section .aligner .left .heart { 189 | position: relative; 190 | top: 50%; 191 | left: 0.2em; 192 | fill: #FF5722; 193 | transform: translateY(30%); 194 | width: 1.7em; 195 | } 196 | 197 | #content.section .aligner .right { 198 | align-self: flex-end; 199 | text-align: right; 200 | } 201 | 202 | .button { 203 | display: inline-block; 204 | font-size: 1em; 205 | letter-spacing: 0.07em; 206 | font-family: "Proxima-nova", sans-serif; 207 | text-transform: uppercase; 208 | font-weight: 800; 209 | padding: 0.8em 2em; 210 | box-sizing: border-box; 211 | text-decoration: none; 212 | color: #1C1C1C; 213 | cursor: pointer; 214 | border-radius: 60px; 215 | background-color: #77FF65; 216 | transition: transform 0.3s cubic-bezier(0.68, -0.6, 0.32, 1.6); 217 | } 218 | 219 | .button:hover { 220 | transform: scale(1.08); 221 | } 222 | 223 | .sublink, .subtext { 224 | position: relative; 225 | font-size: 1em; 226 | letter-spacing: 0.07em; 227 | font-family: "Proxima-nova", sans-serif; 228 | text-transform: uppercase; 229 | text-decoration: none; 230 | font-weight: 800; 231 | color: white; 232 | } 233 | 234 | .sublink { 235 | cursor: pointer; 236 | } 237 | 238 | .sublink::before { 239 | content: ""; 240 | position: absolute; 241 | width: 100%; 242 | height: 2px; 243 | bottom: 0; 244 | left: 0; 245 | background-color: white; 246 | transform: scaleX(0); 247 | transition: all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6); 248 | -webkit-transform: scaleX(0); 249 | -webkit-transition: all 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6); 250 | } 251 | 252 | .sublink:hover::before { 253 | transform: scaleX(1); 254 | } 255 | 256 | .sublink span { 257 | color: #84f397; 258 | } 259 | 260 | .title { 261 | font-size: 4em; 262 | letter-spacing: 0.03em; 263 | color: white; 264 | font-family: "Proxima-nova", sans-serif; 265 | text-transform: uppercase; 266 | font-weight: 800; 267 | } 268 | 269 | .title span { 270 | color: #84f397; 271 | } 272 | 273 | h2, h3 { 274 | font-size: 3.8em; 275 | letter-spacing: 0.03em; 276 | color: white; 277 | font-family: "Proxima-nova", sans-serif; 278 | text-transform: uppercase; 279 | font-weight: 800; 280 | } 281 | 282 | h2 span, h3 span { 283 | color: #77FF65; 284 | } 285 | 286 | h3 { 287 | font-weight: 200; 288 | font-size: 3.5em; 289 | } 290 | 291 | h3 span { 292 | font-weight: 800; 293 | } 294 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "es6", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | "lib": ["DOM", "es6", "es2015"], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "", /* Concatenate and emit output to single file. */ 17 | "outDir": "./dist/", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | // "strict": true, /* Enable all strict type-checking options. */ 29 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 43 | // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ 44 | 45 | /* Module Resolution Options */ 46 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 47 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 48 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 49 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 50 | "typeRoots": [ "./node_modules/@types" ], /* List of folders to include type definitions from. */ 51 | // "types": [ "node" ], /* Type declaration files to be included in compilation. */ 52 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 53 | //"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 54 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 55 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 56 | 57 | /* Source Map Options */ 58 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 61 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 62 | 63 | /* Experimental Options */ 64 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 65 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 66 | 67 | /* Advanced Options */ 68 | // "skipLibCheck": true, /* Skip type checking of declaration files. */ 69 | // "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | /* utils.ts */ 2 | /* Helper functions */ 3 | 4 | import { pennerEasings } from "./defaults"; 5 | 6 | 7 | // Select the node if a query string is provided 8 | export function selectNode(elem: any, multiple?: boolean) { 9 | // return node if element is string 10 | if (typeof elem == "string") { 11 | if (multiple) { 12 | return document.querySelectorAll(elem); 13 | } else { 14 | return document.querySelector(elem); 15 | } 16 | } else { 17 | // return elem itself if already a node 18 | return elem; 19 | } 20 | } 21 | 22 | 23 | // Converts CSS bezier string to bezier floats 24 | export function parseBezierString(bezierString: any) { 25 | let valObj = pennerEasings.filter(e => e.name == bezierString); 26 | let vals: [mX1: number, mY1: number, mX2: number, mY2: number]; 27 | if (valObj[0]) { 28 | vals = <[mX1: number, mY1: number, mX2: number, mY2: number]>valObj[0].value; 29 | } else { 30 | bezierString = bezierString.split(/([^\(-\)]*)/); 31 | bezierString = bezierString[3].split(/,(?![^()]*\()/); 32 | vals = bezierString.map((x: any) => { return parseFloat(x) }); 33 | } 34 | 35 | if (Array.isArray(vals) && vals.length == 4) 36 | return vals; 37 | else 38 | throw "easing string is invalid."; 39 | } 40 | 41 | 42 | // Checks for mobile & unsupported browsers 43 | export function isCompatible() { 44 | let check = false; 45 | (function (a) { 46 | if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substring(0, 4))) 47 | check = true; 48 | }) (navigator.userAgent || navigator.vendor); 49 | 50 | if (!check && CSS.supports) check = !CSS.supports("position", "sticky"); 51 | return !check; 52 | } 53 | 54 | 55 | 56 | // Adds fixed transformable child element to the root element 57 | export function DOMRestructure(root: any) { 58 | // Make sure root doesnt already have a position 59 | if (getComputedStyle(root).position != "absolute" || getComputedStyle(root).position != "fixed") { 60 | root.style.position = "relative"; 61 | } 62 | 63 | let child = document.createElement('div'); 64 | let dummy = document.createElement('div'); 65 | 66 | child.classList.add("_SS_wrapper"); 67 | dummy.classList.add("_SS_dummy"); 68 | 69 | for (let i = root.children.length; i > 0; i--) { 70 | child.insertBefore(root.children[(i - 1)], child.children[0]); 71 | } 72 | 73 | root.innerHTML = ""; 74 | root.style.overflow = "auto"; 75 | root.appendChild(child); 76 | root.appendChild(dummy); 77 | 78 | // Dummy Scroll element to allow overflow to appear 79 | dummy.style.height = child.scrollHeight + "px"; 80 | dummy.style.width = child.scrollWidth + "px"; 81 | dummy.style.top = "0px"; 82 | dummy.style.left = "0px"; 83 | dummy.style.position = "absolute"; 84 | dummy.style.zIndex = "-9999"; 85 | 86 | // Content inside the root element 87 | child.style.zIndex = "1"; 88 | child.style.height = "100%"; 89 | child.style.width = "100%"; 90 | child.style.overflow = "visible"; 91 | child.style.top = "0px"; 92 | child.style.left = "0px"; 93 | child.style.position = "sticky"; 94 | 95 | return { 96 | fixed: root.querySelector("div._SS_wrapper"), 97 | dummy: root.querySelector("div._SS_dummy") 98 | }; 99 | } 100 | 101 | 102 | 103 | // ES6 version of gre/bezier-easing 104 | // https://github.com/gre/bezier-easing/blob/master/src/index.js 105 | export function bezierEasing(mX1: number, mY1: number, mX2: number, mY2: number) { 106 | 107 | let newton_iterations = 4; 108 | let newton_min_slope = 0.001; 109 | let subdivision_precision = 0.0000001; 110 | let subdivision_max_iterations = 10; 111 | 112 | let kSplineTableSize = 11; 113 | let kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); 114 | 115 | let float32ArraySupported = typeof Float32Array === 'function'; 116 | 117 | function A(aA1: number, aA2: number) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; } 118 | 119 | function B(aA1: number, aA2: number) { return 3.0 * aA2 - 6.0 * aA1; } 120 | 121 | function C(aA1: number) { return 3.0 * aA1; } 122 | 123 | function calcBezier(aT: number, aA1: number, aA2: number) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; } 124 | 125 | function getSlope(aT: number, aA1: number, aA2: number) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); } 126 | 127 | function binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number,) { 128 | let currentX, currentT, i = 0; 129 | do { 130 | currentT = aA + (aB - aA) / 2.0; 131 | currentX = calcBezier(currentT, mX1, mX2) - aX; 132 | if (currentX > 0.0) { 133 | aB = currentT; 134 | } else { 135 | aA = currentT; 136 | } 137 | } while (Math.abs(currentX) > subdivision_precision && ++i < subdivision_max_iterations); 138 | return currentT; 139 | } 140 | 141 | function newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) { 142 | for (let i = 0; i < newton_iterations; ++i) { 143 | let currentSlope = getSlope(aGuessT, mX1, mX2); 144 | if (currentSlope === 0.0) { 145 | return aGuessT; 146 | } 147 | let currentX = calcBezier(aGuessT, mX1, mX2) - aX; 148 | aGuessT -= currentX / currentSlope; 149 | } 150 | return aGuessT; 151 | } 152 | 153 | function LinearEasing(x: number) { return x; } 154 | 155 | if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { 156 | throw new Error('bezier x values must be in [0, 1] range'); 157 | } 158 | 159 | if (mX1 === mY1 && mX2 === mY2) return LinearEasing; 160 | 161 | let sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); 162 | for (let i = 0; i < kSplineTableSize; ++i) { 163 | sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); 164 | } 165 | 166 | function getTForX(aX: number) { 167 | let intervalStart = 0.0; 168 | let currentSample = 1; 169 | let lastSample = kSplineTableSize - 1; 170 | 171 | for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) { 172 | intervalStart += kSampleStepSize; 173 | } 174 | --currentSample; 175 | 176 | // Interpolate to provide an initial guess for t 177 | let dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); 178 | let guessForT = intervalStart + dist * kSampleStepSize; 179 | 180 | let initialSlope = getSlope(guessForT, mX1, mX2); 181 | if (initialSlope >= newton_min_slope) { 182 | return newtonRaphsonIterate(aX, guessForT, mX1, mX2); 183 | } else if (initialSlope === 0.0) { 184 | return guessForT; 185 | } else { 186 | return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); 187 | } 188 | } 189 | 190 | return (x: number) => { 191 | if (x === 0 || x === 1) return x; 192 | return calcBezier(getTForX(x), mY1, mY2); 193 | }; 194 | }; -------------------------------------------------------------------------------- /dist/slickscroll.es.min.js: -------------------------------------------------------------------------------- 1 | var e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{Z:()=>O});const i={root:"body",duration:1e3,easing:"cubic-bezier(0.15, 1, 0.4, 1)",offsets:[],fixedOffsets:[]},s={speedY:1,speedX:1},r=[{name:"easeInSine",value:[.12,0,.39,0]},{name:"easeOutSine",value:[.61,1,.88,1]},{name:"easeInOutSine",value:[.37,0,.63,1]},{name:"easeInQuad",value:[.11,0,.5,0]},{name:"easeOutQuad",value:[.5,1,.89,1]},{name:"easeInOutQuad",value:[.45,0,.55,1]},{name:"easeInCubic",value:[.32,0,.67,0]},{name:"easeOutCubic",value:[.33,1,.68,1]},{name:"easeInOutCubic",value:[.65,0,.35,1]},{name:"easeInQuart",value:[.5,0,.75,0]},{name:"easeOutQuart",value:[.25,1,.5,1]},{name:"easeInOutQuart",value:[.76,0,.24,1]},{name:"easeInQuint",value:[.64,0,.78,0]},{name:"easeOutQuint",value:[.22,1,.36,1]},{name:"easeInOutQuint",value:[.83,0,.17,1]},{name:"easeInExpo",value:[.7,0,.84,0]},{name:"easeOutExpo",value:[.16,1,.3,1]},{name:"easeInOutExpo",value:[.87,0,.13,1]},{name:"easeInCirc",value:[.55,0,1,.45]},{name:"easeOutCirc",value:[0,.55,.45,1]},{name:"easeInOutCirc",value:[.85,0,.15,1]}];function o(e,t){return"string"==typeof e?t?document.querySelectorAll(e):document.querySelector(e):e}function a(e,t,i,s){let r=.1,o="function"==typeof Float32Array;function a(e,t){return 1-3*t+3*e}function n(e,t){return 3*t-6*e}function l(e){return 3*e}function f(e,t,i){return((a(t,i)*e+n(t,i))*e+l(t))*e}function h(e,t,i){return 3*a(t,i)*e*e+2*n(t,i)*e+l(t)}if(!(0<=e&&e<=1&&0<=i&&i<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&i===s)return function(e){return e};let p=o?new Float32Array(11):new Array(11);for(let t=0;t<11;++t)p[t]=f(t*r,e,i);return o=>0===o||1===o?o:f(function(t){let s=0,o=1;for(;10!==o&&p[o]<=t;++o)s+=r;--o;let a=s+(t-p[o])/(p[o+1]-p[o])*r,n=h(a,e,i);return n>=.001?function(e,t,i,s){for(let r=0;r<4;++r){let r=h(t,i,s);if(0===r)return t;t-=(f(t,i,s)-e)/r}return t}(t,a,e,i):0===n?a:function(e,t,i,s,r){let o,a,n=0;do{a=t+(i-t)/2,o=f(a,s,r)-e,o>0?i=a:t=a}while(Math.abs(o)>1e-7&&++n<10);return a}(t,s,s+r,e,i)}(o),t,s)}var n,l,f,h,p,m,c,d,u,y,v,w,b,g,x,k=function(e,t,i,s,r){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?r.call(e,i):r?r.value=i:t.set(e,i),i},S=function(e,t,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!s:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(e):s?s.value:t.get(e)};class O{constructor(e){n.add(this),l.set(this,void 0),f.set(this,{x:0,y:0}),h.set(this,{x:0,y:0}),p.set(this,void 0),m.set(this,void 0),c.set(this,void 0),d.set(this,[]),u.set(this,[]),y.set(this,void 0),w.set(this,(e=>{k(this,f,{x:S(this,m,"f").scrollLeft,y:S(this,m,"f").scrollTop},"f"),void 0!==S(this,f,"f").x&&void 0!==S(this,f,"f").y||k(this,f,{x:S(this,m,"f").scrollX,y:S(this,m,"f").scrollY},"f"),S(this,l,"f").onScroll&&new Promise((t=>{S(this,l,"f").onScroll(e),t(!0)}))})),b.set(this,(()=>{if(S(this,y,"f"))return;let e=function(e){let t,i=r.filter((t=>t.name==e));if(t=i[0]?i[0].value:(e=(e=e.split(/([^\(-\)]*)/))[3].split(/,(?![^()]*\()/)).map((e=>parseFloat(e))),Array.isArray(t)&&4==t.length)return t;throw"easing string is invalid."}(S(this,l,"f").easing),t=1/(S(this,l,"f").duration/10+1);S(this,h,"f").x+=a.apply(null,e)(t)*(S(this,f,"f").x-S(this,h,"f").x),S(this,h,"f").y+=a.apply(null,e)(t)*(S(this,f,"f").y-S(this,h,"f").y),S(this,h,"f").x=Math.ceil(100*S(this,h,"f").x)/100,S(this,h,"f").y=Math.ceil(100*S(this,h,"f").y)/100;let i=-1*S(this,h,"f").x,n=-1*S(this,h,"f").y,m=`translate3d(${i}px, ${n}px, 0px)`;if(S(this,p,"f").fixed.style.webkitTransform=m,S(this,p,"f").fixed.style.transform=m,Array.isArray(S(this,u,"f")))for(let e=0;eS(this,b,"f").call(this)))})),x.set(this,(()=>{void 0!==S(this,p,"f")&&(S(this,p,"f").dummy.style.height=S(this,p,"f").fixed.scrollHeight+"px")})),k(this,l,Object.assign({},i,e),"f"),k(this,m,o(e.root),"f"),void 0!==e.fixedOffsets&&k(this,d,e.fixedOffsets,"f"),void 0!==e.offsets&&k(this,u,e.offsets,"f"),function(){let e=!1;var t;return t=navigator.userAgent||navigator.vendor,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substring(0,4)))&&(e=!0),!e&&CSS.supports&&(e=!CSS.supports("position","sticky")),!e}()?S(this,n,"m",v).call(this):S(this,n,"m",g).call(this)}destroy(){let e=S(this,m,"f").querySelector("._SS_wrapper");S(this,m,"f").removeEventListener("scroll",S(this,w,"f")),S(this,m,"f").removeEventListener("resize",S(this,x,"f")),S(this,c,"f").disconnect();for(let t=e.children.length;t>0;t--)e.children[t-1].removeProperty&&e.children[t-1].removeProperty("transform"),S(this,m,"f").insertBefore(e.children[t-1],S(this,m,"f").children[0]);function t(e){e&&e.forEach((e=>{let t=o(e.element,!0);if(e.element||(t=o(e,!0)),NodeList.prototype.isPrototypeOf(t))for(e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform")}))}e.remove(),o(S(this,l,"f").root).querySelector("._SS_dummy").remove(),S(this,m,"f").style.removeProperty("overflow"),S(this,m,"f").style.removeProperty("position"),k(this,y,!0,"f"),t(S(this,u,"f")),t(S(this,d,"f"))}removeOffset(e){k(this,u,S(this,u,"f").filter((t=>t.element!==e)),"f"),k(this,u,S(this,u,"f").filter((t=>t.element!==o(e,!0))),"f"),k(this,d,S(this,d,"f").filter((t=>t!==e)),"f"),k(this,d,S(this,d,"f").filter((t=>t!==o(e,!0))),"f");let t=o(e,!0);if(NodeList.prototype.isPrototypeOf(t))for(let e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform"),"fixed"==e.style.position&&e.style.removeProperty("position");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform"),"fixed"==t.style.position&&t.style.removeProperty("position")}addOffset(e){"object"==typeof e&&!S(this,u,"f").find((t=>t.element==e.element))&&e.element&&(e=Object.assign({},s,e),S(this,u,"f").push(e))}addFixedOffset(e){o(e,!0)&&!S(this,d,"f").includes(e)&&S(this,d,"f").push(e)}}l=new WeakMap,f=new WeakMap,h=new WeakMap,p=new WeakMap,m=new WeakMap,c=new WeakMap,d=new WeakMap,u=new WeakMap,y=new WeakMap,w=new WeakMap,b=new WeakMap,x=new WeakMap,n=new WeakSet,v=function(){k(this,p,function(e){"absolute"==getComputedStyle(e).position&&"fixed"==getComputedStyle(e).position||(e.style.position="relative");let t=document.createElement("div"),i=document.createElement("div");t.classList.add("_SS_wrapper"),i.classList.add("_SS_dummy");for(let i=e.children.length;i>0;i--)t.insertBefore(e.children[i-1],t.children[0]);return e.innerHTML="",e.style.overflow="auto",e.appendChild(t),e.appendChild(i),i.style.height=t.scrollHeight+"px",i.style.width=t.scrollWidth+"px",i.style.top="0px",i.style.left="0px",i.style.position="absolute",i.style.zIndex="-9999",t.style.zIndex="1",t.style.height="100%",t.style.width="100%",t.style.overflow="visible",t.style.top="0px",t.style.left="0px",t.style.position="sticky",{fixed:e.querySelector("div._SS_wrapper"),dummy:e.querySelector("div._SS_dummy")}}(S(this,m,"f")),"f");let e=new WebKitCSSMatrix(window.getComputedStyle(S(this,p,"f").fixed).transform);k(this,f,{x:e.m41,y:e.m42},"f"),k(this,c,new MutationObserver(S(this,x,"f")),"f"),S(this,c,"f").observe(S(this,m,"f"),{childList:!0,attributes:!0,subtree:!0}),window.addEventListener("resize",S(this,x,"f")),S(this,m,"f").addEventListener("scroll",S(this,w,"f")),S(this,b,"f").call(this)},g=function(){S(this,m,"f").addEventListener("scroll",(e=>{S(this,u,"f")&&S(this,u,"f").forEach((t=>{t=Object.assign({},s,t);let i=`translate3d(${e.target.scrollLeft*(1-t.speedX)}px, ${e.target.scrollTop*(1-t.speedY)}px, 0px)`,r=o(t.element,!0);if(Symbol.iterator in Object(r))for(let e of r)e.style.webkitTransform=i,e.style.transform=i;else r.style.webkitTransform=i,r.style.transform=i}))})),S(this,d,"f")&&S(this,d,"f").forEach((e=>{let t=o(e,!0);if(Symbol.iterator in Object(t))for(let e of t)e.style.position="fixed";else t.style.position="fixed"}))};var P=t.Z;export{P as default}; -------------------------------------------------------------------------------- /docs/slickscroll.min.js: -------------------------------------------------------------------------------- 1 | var slickScroll;(()=>{"use strict";var e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};(()=>{e.r(t),e.d(t,{default:()=>O});const i={root:"body",duration:1e3,easing:"cubic-bezier(0.15, 1, 0.4, 1)",offsets:[],fixedOffsets:[]},s={speedY:1,speedX:1},r=[{name:"easeInSine",value:[.12,0,.39,0]},{name:"easeOutSine",value:[.61,1,.88,1]},{name:"easeInOutSine",value:[.37,0,.63,1]},{name:"easeInQuad",value:[.11,0,.5,0]},{name:"easeOutQuad",value:[.5,1,.89,1]},{name:"easeInOutQuad",value:[.45,0,.55,1]},{name:"easeInCubic",value:[.32,0,.67,0]},{name:"easeOutCubic",value:[.33,1,.68,1]},{name:"easeInOutCubic",value:[.65,0,.35,1]},{name:"easeInQuart",value:[.5,0,.75,0]},{name:"easeOutQuart",value:[.25,1,.5,1]},{name:"easeInOutQuart",value:[.76,0,.24,1]},{name:"easeInQuint",value:[.64,0,.78,0]},{name:"easeOutQuint",value:[.22,1,.36,1]},{name:"easeInOutQuint",value:[.83,0,.17,1]},{name:"easeInExpo",value:[.7,0,.84,0]},{name:"easeOutExpo",value:[.16,1,.3,1]},{name:"easeInOutExpo",value:[.87,0,.13,1]},{name:"easeInCirc",value:[.55,0,1,.45]},{name:"easeOutCirc",value:[0,.55,.45,1]},{name:"easeInOutCirc",value:[.85,0,.15,1]}];function o(e,t){return"string"==typeof e?t?document.querySelectorAll(e):document.querySelector(e):e}function a(e,t,i,s){let r=.1,o="function"==typeof Float32Array;function a(e,t){return 1-3*t+3*e}function n(e,t){return 3*t-6*e}function l(e){return 3*e}function f(e,t,i){return((a(t,i)*e+n(t,i))*e+l(t))*e}function h(e,t,i){return 3*a(t,i)*e*e+2*n(t,i)*e+l(t)}if(!(0<=e&&e<=1&&0<=i&&i<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&i===s)return function(e){return e};let m=o?new Float32Array(11):new Array(11);for(let t=0;t<11;++t)m[t]=f(t*r,e,i);return o=>0===o||1===o?o:f(function(t){let s=0,o=1;for(;10!==o&&m[o]<=t;++o)s+=r;--o;let a=s+(t-m[o])/(m[o+1]-m[o])*r,n=h(a,e,i);return n>=.001?function(e,t,i,s){for(let r=0;r<4;++r){let r=h(t,i,s);if(0===r)return t;t-=(f(t,i,s)-e)/r}return t}(t,a,e,i):0===n?a:function(e,t,i,s,r){let o,a,n=0;do{a=t+(i-t)/2,o=f(a,s,r)-e,o>0?i=a:t=a}while(Math.abs(o)>1e-7&&++n<10);return a}(t,s,s+r,e,i)}(o),t,s)}var n,l,f,h,m,p,c,d,u,y,v,w,b,g,x,k=function(e,t,i,s,r){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?r.call(e,i):r?r.value=i:t.set(e,i),i},S=function(e,t,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!s:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(e):s?s.value:t.get(e)};class O{constructor(e){n.add(this),l.set(this,void 0),f.set(this,{x:0,y:0}),h.set(this,{x:0,y:0}),m.set(this,void 0),p.set(this,void 0),c.set(this,void 0),d.set(this,[]),u.set(this,[]),y.set(this,void 0),w.set(this,(e=>{k(this,f,{x:S(this,p,"f").scrollLeft,y:S(this,p,"f").scrollTop},"f"),void 0!==S(this,f,"f").x&&void 0!==S(this,f,"f").y||k(this,f,{x:S(this,p,"f").scrollX,y:S(this,p,"f").scrollY},"f"),S(this,l,"f").onScroll&&new Promise((t=>{S(this,l,"f").onScroll(e),t(!0)}))})),b.set(this,(()=>{if(S(this,y,"f"))return;let e=function(e){let t,i=r.filter((t=>t.name==e));if(t=i[0]?i[0].value:(e=(e=e.split(/([^\(-\)]*)/))[3].split(/,(?![^()]*\()/)).map((e=>parseFloat(e))),Array.isArray(t)&&4==t.length)return t;throw"easing string is invalid."}(S(this,l,"f").easing),t=1/(S(this,l,"f").duration/10+1);S(this,h,"f").x+=a.apply(null,e)(t)*(S(this,f,"f").x-S(this,h,"f").x),S(this,h,"f").y+=a.apply(null,e)(t)*(S(this,f,"f").y-S(this,h,"f").y),S(this,h,"f").x=Math.ceil(100*S(this,h,"f").x)/100,S(this,h,"f").y=Math.ceil(100*S(this,h,"f").y)/100;let i=-1*S(this,h,"f").x,n=-1*S(this,h,"f").y,p=`translate3d(${i}px, ${n}px, 0px)`;if(S(this,m,"f").fixed.style.webkitTransform=p,S(this,m,"f").fixed.style.transform=p,Array.isArray(S(this,u,"f")))for(let e=0;eS(this,b,"f").call(this)))})),x.set(this,(()=>{void 0!==S(this,m,"f")&&(S(this,m,"f").dummy.style.height=S(this,m,"f").fixed.scrollHeight+"px")})),k(this,l,Object.assign({},i,e),"f"),k(this,p,o(e.root),"f"),k(this,d,e.fixedOffsets,"f"),k(this,u,e.offsets,"f"),function(){let e=!1;var t;return t=navigator.userAgent||navigator.vendor,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substring(0,4)))&&(e=!0),!e&&CSS.supports&&(e=!CSS.supports("position","sticky")),!e}()?S(this,n,"m",v).call(this):S(this,n,"m",g).call(this)}destroy(){let e=S(this,p,"f").querySelector("._SS_wrapper");S(this,p,"f").removeEventListener("scroll",S(this,w,"f")),S(this,p,"f").removeEventListener("resize",S(this,x,"f")),S(this,c,"f").disconnect();for(let t=e.children.length;t>0;t--)e.children[t-1].removeProperty&&e.children[t-1].removeProperty("transform"),S(this,p,"f").insertBefore(e.children[t-1],S(this,p,"f").children[0]);function t(e){e&&e.forEach((e=>{let t=o(e.element,!0);if(e.element||(t=o(e,!0)),NodeList.prototype.isPrototypeOf(t))for(e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform")}))}e.remove(),o(S(this,l,"f").root).querySelector("._SS_dummy").remove(),S(this,p,"f").style.removeProperty("overflow"),S(this,p,"f").style.removeProperty("position"),k(this,y,!0,"f"),t(S(this,u,"f")),t(S(this,d,"f"))}removeOffset(e){k(this,u,S(this,u,"f").filter((t=>t.element!==e)),"f"),k(this,u,S(this,u,"f").filter((t=>t.element!==o(e,!0))),"f"),k(this,d,S(this,d,"f").filter((t=>t!==e)),"f"),k(this,d,S(this,d,"f").filter((t=>t!==o(e,!0))),"f");let t=o(e,!0);if(NodeList.prototype.isPrototypeOf(t))for(let e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform"),"fixed"==e.style.position&&e.style.removeProperty("position");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform"),"fixed"==t.style.position&&t.style.removeProperty("position")}addOffset(e){"object"==typeof e&&!S(this,u,"f").find((t=>t.element==e.element))&&e.element&&(e=Object.assign({},s,e),S(this,u,"f").push(e))}addFixedOffset(e){o(e,!0)&&!S(this,d,"f").includes(e)&&S(this,d,"f").push(e)}}l=new WeakMap,f=new WeakMap,h=new WeakMap,m=new WeakMap,p=new WeakMap,c=new WeakMap,d=new WeakMap,u=new WeakMap,y=new WeakMap,w=new WeakMap,b=new WeakMap,x=new WeakMap,n=new WeakSet,v=function(){k(this,m,function(e){"absolute"==getComputedStyle(e).position&&"fixed"==getComputedStyle(e).position||(e.style.position="relative");let t=document.createElement("div"),i=document.createElement("div");t.classList.add("_SS_wrapper"),i.classList.add("_SS_dummy");for(let i=e.children.length;i>0;i--)t.insertBefore(e.children[i-1],t.children[0]);return e.innerHTML="",e.style.overflow="auto",e.appendChild(t),e.appendChild(i),i.style.height=t.scrollHeight+"px",i.style.width=t.scrollWidth+"px",i.style.top="0px",i.style.left="0px",i.style.position="absolute",i.style.zIndex="-9999",t.style.zIndex="1",t.style.height="100%",t.style.width="100%",t.style.overflow="visible",t.style.top="0px",t.style.left="0px",t.style.position="sticky",{fixed:e.querySelector("div._SS_wrapper"),dummy:e.querySelector("div._SS_dummy")}}(S(this,p,"f")),"f");let e=new WebKitCSSMatrix(window.getComputedStyle(S(this,m,"f").fixed).transform);k(this,f,{x:e.m41,y:e.m42},"f"),k(this,c,new MutationObserver(S(this,x,"f")),"f"),S(this,c,"f").observe(S(this,p,"f"),{childList:!0,attributes:!0,subtree:!0}),window.addEventListener("resize",S(this,x,"f")),S(this,p,"f").addEventListener("scroll",S(this,w,"f")),S(this,b,"f").call(this)},g=function(){S(this,p,"f").addEventListener("scroll",(e=>{S(this,u,"f")&&S(this,u,"f").forEach((t=>{t=Object.assign({},s,t);let i=`translate3d(${e.target.scrollLeft*(1-t.speedX)}px, ${e.target.scrollTop*(1-t.speedY)}px, 0px)`,r=o(t.element,!0);if(Symbol.iterator in Object(r))for(let e of r)e.style.webkitTransform=i,e.style.transform=i;else r.style.webkitTransform=i,r.style.transform=i}))})),S(this,d,"f")&&S(this,d,"f").forEach((e=>{let t=o(e,!0);if(Symbol.iterator in Object(t))for(let e of t)e.style.position="fixed";else t.style.position="fixed"}))}})(),slickScroll=t})(); -------------------------------------------------------------------------------- /dist/slickscroll.node.min.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{default:()=>O});const i={root:"body",duration:1e3,easing:"cubic-bezier(0.15, 1, 0.4, 1)",offsets:[],fixedOffsets:[]},s={speedY:1,speedX:1},r=[{name:"easeInSine",value:[.12,0,.39,0]},{name:"easeOutSine",value:[.61,1,.88,1]},{name:"easeInOutSine",value:[.37,0,.63,1]},{name:"easeInQuad",value:[.11,0,.5,0]},{name:"easeOutQuad",value:[.5,1,.89,1]},{name:"easeInOutQuad",value:[.45,0,.55,1]},{name:"easeInCubic",value:[.32,0,.67,0]},{name:"easeOutCubic",value:[.33,1,.68,1]},{name:"easeInOutCubic",value:[.65,0,.35,1]},{name:"easeInQuart",value:[.5,0,.75,0]},{name:"easeOutQuart",value:[.25,1,.5,1]},{name:"easeInOutQuart",value:[.76,0,.24,1]},{name:"easeInQuint",value:[.64,0,.78,0]},{name:"easeOutQuint",value:[.22,1,.36,1]},{name:"easeInOutQuint",value:[.83,0,.17,1]},{name:"easeInExpo",value:[.7,0,.84,0]},{name:"easeOutExpo",value:[.16,1,.3,1]},{name:"easeInOutExpo",value:[.87,0,.13,1]},{name:"easeInCirc",value:[.55,0,1,.45]},{name:"easeOutCirc",value:[0,.55,.45,1]},{name:"easeInOutCirc",value:[.85,0,.15,1]}];function o(e,t){return"string"==typeof e?t?document.querySelectorAll(e):document.querySelector(e):e}function n(e,t,i,s){let r=.1,o="function"==typeof Float32Array;function n(e,t){return 1-3*t+3*e}function a(e,t){return 3*t-6*e}function l(e){return 3*e}function f(e,t,i){return((n(t,i)*e+a(t,i))*e+l(t))*e}function p(e,t,i){return 3*n(t,i)*e*e+2*a(t,i)*e+l(t)}if(!(0<=e&&e<=1&&0<=i&&i<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&i===s)return function(e){return e};let h=o?new Float32Array(11):new Array(11);for(let t=0;t<11;++t)h[t]=f(t*r,e,i);return o=>0===o||1===o?o:f(function(t){let s=0,o=1;for(;10!==o&&h[o]<=t;++o)s+=r;--o;let n=s+(t-h[o])/(h[o+1]-h[o])*r,a=p(n,e,i);return a>=.001?function(e,t,i,s){for(let r=0;r<4;++r){let r=p(t,i,s);if(0===r)return t;t-=(f(t,i,s)-e)/r}return t}(t,n,e,i):0===a?n:function(e,t,i,s,r){let o,n,a=0;do{n=t+(i-t)/2,o=f(n,s,r)-e,o>0?i=n:t=n}while(Math.abs(o)>1e-7&&++a<10);return n}(t,s,s+r,e,i)}(o),t,s)}var a,l,f,p,h,m,c,d,u,y,v,w,b,g,x,k=function(e,t,i,s,r){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?r.call(e,i):r?r.value=i:t.set(e,i),i},S=function(e,t,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!s:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(e):s?s.value:t.get(e)};class O{constructor(e){a.add(this),l.set(this,void 0),f.set(this,{x:0,y:0}),p.set(this,{x:0,y:0}),h.set(this,void 0),m.set(this,void 0),c.set(this,void 0),d.set(this,[]),u.set(this,[]),y.set(this,void 0),w.set(this,(e=>{k(this,f,{x:S(this,m,"f").scrollLeft,y:S(this,m,"f").scrollTop},"f"),void 0!==S(this,f,"f").x&&void 0!==S(this,f,"f").y||k(this,f,{x:S(this,m,"f").scrollX,y:S(this,m,"f").scrollY},"f"),S(this,l,"f").onScroll&&new Promise((t=>{S(this,l,"f").onScroll(e),t(!0)}))})),b.set(this,(()=>{if(S(this,y,"f"))return;let e=function(e){let t,i=r.filter((t=>t.name==e));if(t=i[0]?i[0].value:(e=(e=e.split(/([^\(-\)]*)/))[3].split(/,(?![^()]*\()/)).map((e=>parseFloat(e))),Array.isArray(t)&&4==t.length)return t;throw"easing string is invalid."}(S(this,l,"f").easing),t=1/(S(this,l,"f").duration/10+1);S(this,p,"f").x+=n.apply(null,e)(t)*(S(this,f,"f").x-S(this,p,"f").x),S(this,p,"f").y+=n.apply(null,e)(t)*(S(this,f,"f").y-S(this,p,"f").y),S(this,p,"f").x=Math.ceil(100*S(this,p,"f").x)/100,S(this,p,"f").y=Math.ceil(100*S(this,p,"f").y)/100;let i=-1*S(this,p,"f").x,a=-1*S(this,p,"f").y,m=`translate3d(${i}px, ${a}px, 0px)`;if(S(this,h,"f").fixed.style.webkitTransform=m,S(this,h,"f").fixed.style.transform=m,Array.isArray(S(this,u,"f")))for(let e=0;eS(this,b,"f").call(this)))})),x.set(this,(()=>{void 0!==S(this,h,"f")&&(S(this,h,"f").dummy.style.height=S(this,h,"f").fixed.scrollHeight+"px")})),k(this,l,Object.assign({},i,e),"f"),k(this,m,o(e.root),"f"),void 0!==e.fixedOffsets&&k(this,d,e.fixedOffsets,"f"),void 0!==e.offsets&&k(this,u,e.offsets,"f"),function(){let e=!1;var t;return t=navigator.userAgent||navigator.vendor,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substring(0,4)))&&(e=!0),!e&&CSS.supports&&(e=!CSS.supports("position","sticky")),!e}()?S(this,a,"m",v).call(this):S(this,a,"m",g).call(this)}destroy(){let e=S(this,m,"f").querySelector("._SS_wrapper");S(this,m,"f").removeEventListener("scroll",S(this,w,"f")),S(this,m,"f").removeEventListener("resize",S(this,x,"f")),S(this,c,"f").disconnect();for(let t=e.children.length;t>0;t--)e.children[t-1].removeProperty&&e.children[t-1].removeProperty("transform"),S(this,m,"f").insertBefore(e.children[t-1],S(this,m,"f").children[0]);function t(e){e&&e.forEach((e=>{let t=o(e.element,!0);if(e.element||(t=o(e,!0)),NodeList.prototype.isPrototypeOf(t))for(e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform")}))}e.remove(),o(S(this,l,"f").root).querySelector("._SS_dummy").remove(),S(this,m,"f").style.removeProperty("overflow"),S(this,m,"f").style.removeProperty("position"),k(this,y,!0,"f"),t(S(this,u,"f")),t(S(this,d,"f"))}removeOffset(e){k(this,u,S(this,u,"f").filter((t=>t.element!==e)),"f"),k(this,u,S(this,u,"f").filter((t=>t.element!==o(e,!0))),"f"),k(this,d,S(this,d,"f").filter((t=>t!==e)),"f"),k(this,d,S(this,d,"f").filter((t=>t!==o(e,!0))),"f");let t=o(e,!0);if(NodeList.prototype.isPrototypeOf(t))for(let e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform"),"fixed"==e.style.position&&e.style.removeProperty("position");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform"),"fixed"==t.style.position&&t.style.removeProperty("position")}addOffset(e){"object"==typeof e&&!S(this,u,"f").find((t=>t.element==e.element))&&e.element&&(e=Object.assign({},s,e),S(this,u,"f").push(e))}addFixedOffset(e){o(e,!0)&&!S(this,d,"f").includes(e)&&S(this,d,"f").push(e)}}l=new WeakMap,f=new WeakMap,p=new WeakMap,h=new WeakMap,m=new WeakMap,c=new WeakMap,d=new WeakMap,u=new WeakMap,y=new WeakMap,w=new WeakMap,b=new WeakMap,x=new WeakMap,a=new WeakSet,v=function(){k(this,h,function(e){"absolute"==getComputedStyle(e).position&&"fixed"==getComputedStyle(e).position||(e.style.position="relative");let t=document.createElement("div"),i=document.createElement("div");t.classList.add("_SS_wrapper"),i.classList.add("_SS_dummy");for(let i=e.children.length;i>0;i--)t.insertBefore(e.children[i-1],t.children[0]);return e.innerHTML="",e.style.overflow="auto",e.appendChild(t),e.appendChild(i),i.style.height=t.scrollHeight+"px",i.style.width=t.scrollWidth+"px",i.style.top="0px",i.style.left="0px",i.style.position="absolute",i.style.zIndex="-9999",t.style.zIndex="1",t.style.height="100%",t.style.width="100%",t.style.overflow="visible",t.style.top="0px",t.style.left="0px",t.style.position="sticky",{fixed:e.querySelector("div._SS_wrapper"),dummy:e.querySelector("div._SS_dummy")}}(S(this,m,"f")),"f");let e=new WebKitCSSMatrix(window.getComputedStyle(S(this,h,"f").fixed).transform);k(this,f,{x:e.m41,y:e.m42},"f"),k(this,c,new MutationObserver(S(this,x,"f")),"f"),S(this,c,"f").observe(S(this,m,"f"),{childList:!0,attributes:!0,subtree:!0}),window.addEventListener("resize",S(this,x,"f")),S(this,m,"f").addEventListener("scroll",S(this,w,"f")),S(this,b,"f").call(this)},g=function(){S(this,m,"f").addEventListener("scroll",(e=>{S(this,u,"f")&&S(this,u,"f").forEach((t=>{t=Object.assign({},s,t);let i=`translate3d(${e.target.scrollLeft*(1-t.speedX)}px, ${e.target.scrollTop*(1-t.speedY)}px, 0px)`,r=o(t.element,!0);if(Symbol.iterator in Object(r))for(let e of r)e.style.webkitTransform=i,e.style.transform=i;else r.style.webkitTransform=i,r.style.transform=i}))})),S(this,d,"f")&&S(this,d,"f").forEach((e=>{let t=o(e,!0);if(Symbol.iterator in Object(t))for(let e of t)e.style.position="fixed";else t.style.position="fixed"}))},exports.slickScroll=t})(); -------------------------------------------------------------------------------- /dist/slickscroll.min.js: -------------------------------------------------------------------------------- 1 | var slickScroll;(()=>{"use strict";var e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};(()=>{e.r(t),e.d(t,{default:()=>O});const i={root:"body",duration:1e3,easing:"cubic-bezier(0.15, 1, 0.4, 1)",offsets:[],fixedOffsets:[]},s={speedY:1,speedX:1},r=[{name:"easeInSine",value:[.12,0,.39,0]},{name:"easeOutSine",value:[.61,1,.88,1]},{name:"easeInOutSine",value:[.37,0,.63,1]},{name:"easeInQuad",value:[.11,0,.5,0]},{name:"easeOutQuad",value:[.5,1,.89,1]},{name:"easeInOutQuad",value:[.45,0,.55,1]},{name:"easeInCubic",value:[.32,0,.67,0]},{name:"easeOutCubic",value:[.33,1,.68,1]},{name:"easeInOutCubic",value:[.65,0,.35,1]},{name:"easeInQuart",value:[.5,0,.75,0]},{name:"easeOutQuart",value:[.25,1,.5,1]},{name:"easeInOutQuart",value:[.76,0,.24,1]},{name:"easeInQuint",value:[.64,0,.78,0]},{name:"easeOutQuint",value:[.22,1,.36,1]},{name:"easeInOutQuint",value:[.83,0,.17,1]},{name:"easeInExpo",value:[.7,0,.84,0]},{name:"easeOutExpo",value:[.16,1,.3,1]},{name:"easeInOutExpo",value:[.87,0,.13,1]},{name:"easeInCirc",value:[.55,0,1,.45]},{name:"easeOutCirc",value:[0,.55,.45,1]},{name:"easeInOutCirc",value:[.85,0,.15,1]}];function o(e,t){return"string"==typeof e?t?document.querySelectorAll(e):document.querySelector(e):e}function a(e,t,i,s){let r=.1,o="function"==typeof Float32Array;function a(e,t){return 1-3*t+3*e}function n(e,t){return 3*t-6*e}function l(e){return 3*e}function f(e,t,i){return((a(t,i)*e+n(t,i))*e+l(t))*e}function h(e,t,i){return 3*a(t,i)*e*e+2*n(t,i)*e+l(t)}if(!(0<=e&&e<=1&&0<=i&&i<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&i===s)return function(e){return e};let m=o?new Float32Array(11):new Array(11);for(let t=0;t<11;++t)m[t]=f(t*r,e,i);return o=>0===o||1===o?o:f(function(t){let s=0,o=1;for(;10!==o&&m[o]<=t;++o)s+=r;--o;let a=s+(t-m[o])/(m[o+1]-m[o])*r,n=h(a,e,i);return n>=.001?function(e,t,i,s){for(let r=0;r<4;++r){let r=h(t,i,s);if(0===r)return t;t-=(f(t,i,s)-e)/r}return t}(t,a,e,i):0===n?a:function(e,t,i,s,r){let o,a,n=0;do{a=t+(i-t)/2,o=f(a,s,r)-e,o>0?i=a:t=a}while(Math.abs(o)>1e-7&&++n<10);return a}(t,s,s+r,e,i)}(o),t,s)}var n,l,f,h,m,p,c,d,u,y,v,w,b,g,x,k=function(e,t,i,s,r){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?r.call(e,i):r?r.value=i:t.set(e,i),i},S=function(e,t,i,s){if("a"===i&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!s:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?s:"a"===i?s.call(e):s?s.value:t.get(e)};class O{constructor(e){n.add(this),l.set(this,void 0),f.set(this,{x:0,y:0}),h.set(this,{x:0,y:0}),m.set(this,void 0),p.set(this,void 0),c.set(this,void 0),d.set(this,[]),u.set(this,[]),y.set(this,void 0),w.set(this,(e=>{k(this,f,{x:S(this,p,"f").scrollLeft,y:S(this,p,"f").scrollTop},"f"),void 0!==S(this,f,"f").x&&void 0!==S(this,f,"f").y||k(this,f,{x:S(this,p,"f").scrollX,y:S(this,p,"f").scrollY},"f"),S(this,l,"f").onScroll&&new Promise((t=>{S(this,l,"f").onScroll(e),t(!0)}))})),b.set(this,(()=>{if(S(this,y,"f"))return;let e=function(e){let t,i=r.filter((t=>t.name==e));if(t=i[0]?i[0].value:(e=(e=e.split(/([^\(-\)]*)/))[3].split(/,(?![^()]*\()/)).map((e=>parseFloat(e))),Array.isArray(t)&&4==t.length)return t;throw"easing string is invalid."}(S(this,l,"f").easing),t=1/(S(this,l,"f").duration/10+1);S(this,h,"f").x+=a.apply(null,e)(t)*(S(this,f,"f").x-S(this,h,"f").x),S(this,h,"f").y+=a.apply(null,e)(t)*(S(this,f,"f").y-S(this,h,"f").y),S(this,h,"f").x=Math.ceil(100*S(this,h,"f").x)/100,S(this,h,"f").y=Math.ceil(100*S(this,h,"f").y)/100;let i=-1*S(this,h,"f").x,n=-1*S(this,h,"f").y,p=`translate3d(${i}px, ${n}px, 0px)`;if(S(this,m,"f").fixed.style.webkitTransform=p,S(this,m,"f").fixed.style.transform=p,Array.isArray(S(this,u,"f")))for(let e=0;eS(this,b,"f").call(this)))})),x.set(this,(()=>{void 0!==S(this,m,"f")&&(S(this,m,"f").dummy.style.height=S(this,m,"f").fixed.scrollHeight+"px")})),k(this,l,Object.assign({},i,e),"f"),k(this,p,o(e.root),"f"),void 0!==e.fixedOffsets&&k(this,d,e.fixedOffsets,"f"),void 0!==e.offsets&&k(this,u,e.offsets,"f"),function(){let e=!1;var t;return t=navigator.userAgent||navigator.vendor,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substring(0,4)))&&(e=!0),!e&&CSS.supports&&(e=!CSS.supports("position","sticky")),!e}()?S(this,n,"m",v).call(this):S(this,n,"m",g).call(this)}destroy(){let e=S(this,p,"f").querySelector("._SS_wrapper");S(this,p,"f").removeEventListener("scroll",S(this,w,"f")),S(this,p,"f").removeEventListener("resize",S(this,x,"f")),S(this,c,"f").disconnect();for(let t=e.children.length;t>0;t--)e.children[t-1].removeProperty&&e.children[t-1].removeProperty("transform"),S(this,p,"f").insertBefore(e.children[t-1],S(this,p,"f").children[0]);function t(e){e&&e.forEach((e=>{let t=o(e.element,!0);if(e.element||(t=o(e,!0)),NodeList.prototype.isPrototypeOf(t))for(e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform")}))}e.remove(),o(S(this,l,"f").root).querySelector("._SS_dummy").remove(),S(this,p,"f").style.removeProperty("overflow"),S(this,p,"f").style.removeProperty("position"),k(this,y,!0,"f"),t(S(this,u,"f")),t(S(this,d,"f"))}removeOffset(e){k(this,u,S(this,u,"f").filter((t=>t.element!==e)),"f"),k(this,u,S(this,u,"f").filter((t=>t.element!==o(e,!0))),"f"),k(this,d,S(this,d,"f").filter((t=>t!==e)),"f"),k(this,d,S(this,d,"f").filter((t=>t!==o(e,!0))),"f");let t=o(e,!0);if(NodeList.prototype.isPrototypeOf(t))for(let e of t)e.style.removeProperty("transform"),e.style.removeProperty("-webkit-transform"),"fixed"==e.style.position&&e.style.removeProperty("position");else t.style.removeProperty("transform"),t.style.removeProperty("-webkit-transform"),"fixed"==t.style.position&&t.style.removeProperty("position")}addOffset(e){"object"==typeof e&&!S(this,u,"f").find((t=>t.element==e.element))&&e.element&&(e=Object.assign({},s,e),S(this,u,"f").push(e))}addFixedOffset(e){o(e,!0)&&!S(this,d,"f").includes(e)&&S(this,d,"f").push(e)}}l=new WeakMap,f=new WeakMap,h=new WeakMap,m=new WeakMap,p=new WeakMap,c=new WeakMap,d=new WeakMap,u=new WeakMap,y=new WeakMap,w=new WeakMap,b=new WeakMap,x=new WeakMap,n=new WeakSet,v=function(){k(this,m,function(e){"absolute"==getComputedStyle(e).position&&"fixed"==getComputedStyle(e).position||(e.style.position="relative");let t=document.createElement("div"),i=document.createElement("div");t.classList.add("_SS_wrapper"),i.classList.add("_SS_dummy");for(let i=e.children.length;i>0;i--)t.insertBefore(e.children[i-1],t.children[0]);return e.innerHTML="",e.style.overflow="auto",e.appendChild(t),e.appendChild(i),i.style.height=t.scrollHeight+"px",i.style.width=t.scrollWidth+"px",i.style.top="0px",i.style.left="0px",i.style.position="absolute",i.style.zIndex="-9999",t.style.zIndex="1",t.style.height="100%",t.style.width="100%",t.style.overflow="visible",t.style.top="0px",t.style.left="0px",t.style.position="sticky",{fixed:e.querySelector("div._SS_wrapper"),dummy:e.querySelector("div._SS_dummy")}}(S(this,p,"f")),"f");let e=new WebKitCSSMatrix(window.getComputedStyle(S(this,m,"f").fixed).transform);k(this,f,{x:e.m41,y:e.m42},"f"),k(this,c,new MutationObserver(S(this,x,"f")),"f"),S(this,c,"f").observe(S(this,p,"f"),{childList:!0,attributes:!0,subtree:!0}),window.addEventListener("resize",S(this,x,"f")),S(this,p,"f").addEventListener("scroll",S(this,w,"f")),S(this,b,"f").call(this)},g=function(){S(this,p,"f").addEventListener("scroll",(e=>{S(this,u,"f")&&S(this,u,"f").forEach((t=>{t=Object.assign({},s,t);let i=`translate3d(${e.target.scrollLeft*(1-t.speedX)}px, ${e.target.scrollTop*(1-t.speedY)}px, 0px)`,r=o(t.element,!0);if(Symbol.iterator in Object(r))for(let e of r)e.style.webkitTransform=i,e.style.transform=i;else r.style.webkitTransform=i,r.style.transform=i}))})),S(this,d,"f")&&S(this,d,"f").forEach((e=>{let t=o(e,!0);if(Symbol.iterator in Object(t))for(let e of t)e.style.position="fixed";else t.style.position="fixed"}))}})(),slickScroll=t})(); -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * SlickScrollJS 3 | * © Musab Hassan 4 | * 5 | * Build with 'npm run build' 6 | * 7 | ***************************************/ 8 | 9 | 10 | import { DOMRestructure, selectNode, bezierEasing, parseBezierString, isCompatible } from "./utils"; 11 | import { defaults, defaultSpeeds } from "./defaults"; 12 | import { momentumScrollStruct } from "./struct"; 13 | 14 | 15 | export default class slickScroll { 16 | 17 | #params: momentumScrollStruct; 18 | 19 | #targetPosition: { x: number, y: number } = { 20 | x: 0, 21 | y: 0 22 | }; 23 | #currentPosition: { x: number, y: number } = { 24 | x: 0, 25 | y: 0 26 | }; 27 | 28 | #restructedElements: any; 29 | #rootElement: any; 30 | #mutationObserver: MutationObserver; 31 | 32 | #fixedOffsets: any[] = []; 33 | #offsets: any[] = []; 34 | 35 | #isDestroyed: boolean; 36 | 37 | 38 | constructor(params: momentumScrollStruct) { 39 | // Assign defaults to params object 40 | this.#params = (Object).assign({}, defaults, params); 41 | 42 | this.#rootElement = selectNode(params.root); 43 | 44 | // Set any offsets or fixedOffsets assigned on initialization 45 | if (params.fixedOffsets !== undefined) this.#fixedOffsets = params.fixedOffsets; 46 | if (params.offsets !== undefined) this.#offsets = params.offsets; 47 | 48 | // Switch to mobile version of client is unsupported 49 | if (isCompatible()) { 50 | this.#init(); 51 | } else { 52 | this.#mobileFallback(); 53 | } 54 | } 55 | 56 | 57 | // Initialize momentum scrolling 58 | #init() { 59 | 60 | this.#restructedElements = DOMRestructure(this.#rootElement); 61 | let matrix = new WebKitCSSMatrix(window.getComputedStyle(this.#restructedElements.fixed).transform); 62 | this.#targetPosition = { x: matrix.m41, y: matrix.m42 } 63 | 64 | // Detect any changes to root element's appearance by listening to window resize and DOM tree changes 65 | this.#mutationObserver = new MutationObserver(this.#onWindowResize); 66 | this.#mutationObserver.observe(this.#rootElement, { 67 | childList: true, 68 | attributes: true, 69 | subtree: true 70 | }); 71 | window.addEventListener("resize", this.#onWindowResize); 72 | 73 | // Bind scroll handler 74 | this.#rootElement.addEventListener("scroll", this.#scrollHandler); 75 | // Begin animation loop 76 | this.#animate(); 77 | } 78 | 79 | 80 | // Change values based on scroll position 81 | #scrollHandler = (e: any) => { 82 | 83 | // Get scroll position of rootElement 84 | this.#targetPosition = { x: this.#rootElement.scrollLeft, y: this.#rootElement.scrollTop }; 85 | 86 | if (typeof this.#targetPosition.x === "undefined" || typeof this.#targetPosition.y === "undefined") { 87 | this.#targetPosition = { x: this.#rootElement.scrollX, y: this.#rootElement.scrollY, }; 88 | } 89 | 90 | // Run params.onScroll function asynchrounously 91 | if (this.#params.onScroll) { 92 | new Promise(r => { 93 | this.#params.onScroll(e); 94 | r(true); 95 | }) 96 | } 97 | } 98 | 99 | 100 | // Tween between scroll position (momentum scrolling) 101 | #animate = () => { 102 | 103 | if (this.#isDestroyed) return; 104 | 105 | let easing = parseBezierString(this.#params.easing); 106 | let t = (1 / ((this.#params.duration / 10) + 1)); 107 | 108 | this.#currentPosition.x += bezierEasing.apply(null, easing)(t) * (this.#targetPosition.x - this.#currentPosition.x); 109 | this.#currentPosition.y += bezierEasing.apply(null, easing)(t) * (this.#targetPosition.y - this.#currentPosition.y); 110 | 111 | this.#currentPosition.x = (Math.ceil(this.#currentPosition.x * 100) / 100); 112 | this.#currentPosition.y = (Math.ceil(this.#currentPosition.y * 100) / 100); 113 | 114 | 115 | // Apply transformations to root and offsets 116 | let position = { 117 | x: this.#currentPosition.x * -1, 118 | y: this.#currentPosition.y * -1 119 | } 120 | 121 | let translateString = `translate3d(${position.x}px, ${position.y}px, 0px)`; 122 | this.#restructedElements.fixed.style.webkitTransform = translateString; 123 | this.#restructedElements.fixed.style.transform = translateString; 124 | 125 | // Parallax offset elements scrolling 126 | if (Array.isArray(this.#offsets)) { 127 | 128 | for (let i = 0; i < this.#offsets.length; i++) { 129 | 130 | let e = Object.assign({}, defaultSpeeds, this.#offsets[i]); 131 | let offset = `translate3d(${position.x * (e.speedX - 1)}px, ${position.y * (e.speedY - 1)}px, 0)`; 132 | let elements: any = selectNode(e.element, true); 133 | 134 | if (NodeList.prototype.isPrototypeOf(elements)) { 135 | for (let e of elements as any) { 136 | e.style.webkitTransform = offset; 137 | e.style.transform = offset; 138 | } 139 | } else { 140 | elements.style.webkitTransform = offset; 141 | elements.style.transform = offset; 142 | } 143 | } 144 | } 145 | 146 | // Set fixedOffsets position as fixed 147 | if (Array.isArray(this.#fixedOffsets)) { 148 | 149 | for (let i = 0; i < this.#fixedOffsets.length; i++) { 150 | let offset = `translate3d(${-position.x}px, ${-position.y}px, 0px)`; 151 | let node = selectNode(this.#fixedOffsets[i], true); 152 | 153 | if (NodeList.prototype.isPrototypeOf(node)) { 154 | for (let e of node as any) { 155 | e.style.webkitTransform = offset; 156 | e.style.transform = offset; 157 | } 158 | } else { 159 | node.style.webkitTransform = offset; 160 | node.style.transform = offset; 161 | } 162 | } 163 | } 164 | 165 | requestAnimationFrame(() => this.#animate()); 166 | } 167 | 168 | // Mobile version without momentum scrolling, just parallax offset support 169 | #mobileFallback() { 170 | 171 | // Parallax Offsets scrolling 172 | this.#rootElement.addEventListener("scroll", (event: any) => { 173 | 174 | // Offset elements scrolling 175 | if (this.#offsets) { 176 | this.#offsets.forEach((e: any) => { 177 | e = Object.assign({}, defaultSpeeds, e); 178 | 179 | let offset = `translate3d(${event.target.scrollLeft * (1 - e.speedX)}px, ${event.target.scrollTop * (1 - e.speedY)}px, 0px)`; 180 | let nodes = selectNode(e.element, true); 181 | 182 | if (Symbol.iterator in Object(nodes)) { 183 | // If multiple nodes are selected 184 | for (let e of nodes as any) { 185 | e.style.webkitTransform = offset; 186 | e.style.transform = offset; 187 | } 188 | } else { 189 | // If single node is selected 190 | nodes.style.webkitTransform = offset; 191 | nodes.style.transform = offset; 192 | } 193 | }); 194 | } 195 | }); 196 | 197 | // Set fixed offsets as just fixed 198 | if (this.#fixedOffsets) { 199 | this.#fixedOffsets.forEach((element: any) => { 200 | let nodes = selectNode(element, true); 201 | 202 | if (Symbol.iterator in Object(nodes)) { 203 | // If multiple nodes are selected 204 | for (let e of nodes as any) { 205 | e.style.position = "fixed"; 206 | } 207 | } else { 208 | // If single node is selected 209 | nodes.style.position = "fixed"; 210 | } 211 | }); 212 | } 213 | } 214 | 215 | 216 | // Resize dummy element when window resizes to prevent overscrolling 217 | #onWindowResize = () => { 218 | if (this.#restructedElements === undefined) return; 219 | this.#restructedElements.dummy.style.height = this.#restructedElements.fixed.scrollHeight + "px"; 220 | } 221 | 222 | 223 | 224 | // ? Public Methods 225 | 226 | // Remove all slickScroll handers and return rootelement's DOM tree to its original state 227 | public destroy() { 228 | 229 | let wrapper: any = this.#rootElement.querySelector("._SS_wrapper"); 230 | 231 | // Remove all Observers and EventListeners 232 | this.#rootElement.removeEventListener("scroll", this.#scrollHandler); 233 | this.#rootElement.removeEventListener("resize", this.#onWindowResize); 234 | this.#mutationObserver.disconnect(); 235 | 236 | // Revert root element to original state and remove all slickscroll classes 237 | for (let i = wrapper.children.length; i > 0; i--) { 238 | if (wrapper.children[i - 1].removeProperty) wrapper.children[i - 1].removeProperty("transform"); 239 | this.#rootElement.insertBefore(wrapper.children[i - 1], this.#rootElement.children[0]); 240 | } 241 | wrapper.remove(); 242 | 243 | selectNode(this.#params.root).querySelector("._SS_dummy")!.remove(); 244 | this.#rootElement.style.removeProperty("overflow"); 245 | this.#rootElement.style.removeProperty("position"); 246 | 247 | this.#isDestroyed = true; 248 | 249 | // Clear all transformations on offsets 250 | clearTransform(this.#offsets); 251 | clearTransform(this.#fixedOffsets); 252 | 253 | // Remove "transform" from an offset array 254 | function clearTransform(array: any[]) { 255 | if (array) { 256 | array.forEach((e) => { 257 | let elements = selectNode(e.element, true); 258 | if (!e.element) elements = selectNode(e, true); 259 | 260 | if (NodeList.prototype.isPrototypeOf(elements)) { 261 | for (e of elements as any) { 262 | e.style.removeProperty("transform"); 263 | e.style.removeProperty("-webkit-transform"); 264 | } 265 | return; 266 | } 267 | 268 | elements.style.removeProperty("transform"); 269 | elements.style.removeProperty("-webkit-transform"); 270 | }); 271 | } 272 | } 273 | } 274 | 275 | // Disable and remove a fixed or parallax Offset 276 | public removeOffset(offset: string | HTMLElement | HTMLBodyElement | null) { 277 | this.#offsets = this.#offsets.filter(item => item.element !== offset); 278 | this.#offsets = this.#offsets.filter(item => item.element !== selectNode(offset, true)); 279 | this.#fixedOffsets = this.#fixedOffsets.filter(item => item !== offset); 280 | this.#fixedOffsets = this.#fixedOffsets.filter(item => item !== selectNode(offset, true)); 281 | 282 | let offsetNode = selectNode(offset, true); 283 | 284 | if (NodeList.prototype.isPrototypeOf(offsetNode)) { 285 | for (let e of offsetNode as any) { 286 | e.style.removeProperty("transform"); 287 | e.style.removeProperty("-webkit-transform"); 288 | if (e.style.position == "fixed") e.style.removeProperty("position"); 289 | } 290 | } else { 291 | offsetNode.style.removeProperty("transform"); 292 | offsetNode.style.removeProperty("-webkit-transform"); 293 | if (offsetNode.style.position == "fixed") offsetNode.style.removeProperty("position"); 294 | } 295 | } 296 | 297 | 298 | public addOffset(offset: { 299 | element: string | HTMLElement | HTMLBodyElement | null, 300 | speedY?: number, 301 | speedX?: number 302 | }) { 303 | 304 | if (typeof offset !== "object") return; 305 | 306 | // Check if offset already exists 307 | const find = this.#offsets.find((i: any) => i.element == offset.element); 308 | if (find || !offset.element) { 309 | return; 310 | } 311 | 312 | // Assign default values to offset and push it to offsets array 313 | offset = Object.assign({}, defaultSpeeds, offset); 314 | this.#offsets.push(offset); 315 | } 316 | 317 | 318 | public addFixedOffset(element: string | HTMLElement | HTMLBodyElement | null) { 319 | 320 | // Check if offset already exists 321 | if (!selectNode(element, true) || this.#fixedOffsets.includes(element)) { 322 | return; 323 | } 324 | 325 | this.#fixedOffsets.push(element); 326 | } 327 | } --------------------------------------------------------------------------------