├── .babelrc ├── .gitignore ├── README.md ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── src ├── createServiceWorker.js ├── index.js ├── react-skrollr │ ├── Parallax.js │ ├── ParallaxProvider.js │ └── index.js └── style.css └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | /lib 4 | /build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Skrollr 2 | [![npm version](https://badge.fury.io/js/react-skrollr.png)](https://badge.fury.io/js/react-skrollr) 3 | 4 | React Component parallax scrolling JavaScript library base on [*Skrollr*]() 5 | 6 | See [*live demo*]() 7 | 8 | 9 | 10 | ### Getting Started 11 | ``` 12 | $ npm install --save react-skrollr 13 | ``` 14 | 15 | ### Import package 16 | 17 | ```js 18 | import { ParallaxProvider, Parallax } from 'react-skrollr' 19 | ``` 20 | 21 | ### Init config (Optional) 22 | Use init config via props `init` (props type is object) 23 | 24 | Skrollr init [*Options*]() 25 | 26 | Add `ParallaxProvider` into root app 27 | ```js 28 | class App extends React.Component { 29 | render() { 30 | return ( 31 | 38 | ... 39 | 40 | ) 41 | } 42 | } 43 | ``` 44 | 45 | ### Setting parallax data (Required) 46 | Use data scrolling via props `data` (props type is object) 47 | 48 | Skrollr [*Data attr document*]() 49 | 50 | ```js 51 | const Component = () => { 52 | return ( 53 | Some content 59 | ) 60 | } 61 | ``` 62 | 63 | ### Example use 64 | 65 | ```js 66 | class App extends React.Component { 67 | render() { 68 | return ( 69 | 70 | 76 | Some content or Component 77 | 78 | 79 | ); 80 | } 81 | } 82 | ``` 83 | 84 | Thank you for your suggestions! -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-skrollr", 3 | "version": "1.0.4", 4 | "description": "React Component parallax scrolling JavaScript library base on Skrollr", 5 | "main": "lib/index.js", 6 | "author": "[GAMO] Thawatchai Kuansombat (thawatchai.deartk@gmail.com)", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/GA-MO/react-skrollr.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/GA-MO/react-skrollr/issues" 14 | }, 15 | "keywords": [ 16 | "react-skrollr", 17 | "skrollr", 18 | "react-parallax", 19 | "parallax", 20 | "scroll-parallax", 21 | "react" 22 | ], 23 | "files": [ 24 | "lib" 25 | ], 26 | "dependencies": { 27 | "skrollr": "0.6.26" 28 | }, 29 | "devDependencies": { 30 | "babel": "^6.23.0", 31 | "babel-cli": "^6.26.0", 32 | "babel-preset-es2015": "^6.24.1", 33 | "babel-preset-react": "^6.24.1", 34 | "babel-preset-stage-0": "^6.24.1", 35 | "react": "16.0.0", 36 | "react-dom": "16.0.0", 37 | "react-scripts": "1.0.0" 38 | }, 39 | "scripts": { 40 | "start": "react-scripts start", 41 | "build": "react-scripts build", 42 | "serve": "serve -s build", 43 | "build-lib": "babel ./src/react-skrollr --out-dir lib", 44 | "test": "react-scripts test --env=jsdom", 45 | "eject": "react-scripts eject", 46 | "prepublish": "npm run build-lib" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GA-MO/react-skrollr/487a1435d9fcda3883adf63b4efc693ca744d677/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/createServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | export default function register() { 12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 13 | window.addEventListener('load', () => { 14 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 15 | navigator.serviceWorker 16 | .register(swUrl) 17 | .then(registration => { 18 | // eslint-disable-next-line no-param-reassign 19 | registration.onupdatefound = () => { 20 | const installingWorker = registration.installing; 21 | installingWorker.onstatechange = () => { 22 | if (installingWorker.state === 'installed') { 23 | if (navigator.serviceWorker.controller) { 24 | // At this point, the old content will have been purged and 25 | // the fresh content will have been added to the cache. 26 | // It's the perfect time to display a "New content is 27 | // available; please refresh." message in your web app. 28 | console.log('New content is available; please refresh.'); // eslint-disable-line no-console 29 | } else { 30 | // At this point, everything has been precached. 31 | // It's the perfect time to display a 32 | // "Content is cached for offline use." message. 33 | console.log('Content is cached for offline use.'); // eslint-disable-line no-console 34 | } 35 | } 36 | }; 37 | }; 38 | }) 39 | .catch(error => { 40 | console.error('Error during service worker registration:', error); 41 | }); 42 | }); 43 | } 44 | } 45 | 46 | export function unregister() { 47 | if ('serviceWorker' in navigator) { 48 | navigator.serviceWorker.ready.then(registration => { 49 | registration.unregister(); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "react-dom"; 3 | import { ParallaxProvider, Parallax } from "./react-skrollr"; 4 | import "./style.css"; 5 | 6 | const data = { 7 | "data-top-top": "transform: translateX(-100%);", 8 | "data-center-center": "opacity: 1;transform: translateX(0%);", 9 | "data-bottom-top": "opacity: 0;" 10 | }; 11 | 12 | const App = () => ( 13 | console.log("scrollTop", scrollTop)} 20 | > 21 |
React Skrollr
22 | 23 | 24 | Start scrolling to see some magic happen {"\u2728"} 25 | 26 | 27 | Start scrolling to see some magic happen {"\u2728"} 28 | 29 | 30 | Start scrolling to see some magic happen {"\u2728"} 31 | 32 | 33 | Start scrolling to see some magic happen {"\u2728"} 34 | 35 | 36 | Start scrolling to see some magic happen {"\u2728"} 37 | 38 | 39 | Start scrolling to see some magic happen {"\u2728"} 40 | 41 | 42 | Start scrolling to see some magic happen {"\u2728"} 43 | 44 | 45 | Start scrolling to see some magic happen {"\u2728"} 46 | 47 | 48 | Start scrolling to see some magic happen {"\u2728"} 49 | 50 | 51 | Start scrolling to see some magic happen {"\u2728"} 52 | 53 | 54 | Start scrolling to see some magic happen {"\u2728"} 55 | 56 | 57 | Start scrolling to see some magic happen {"\u2728"} 58 | 59 | 60 | Start scrolling to see some magic happen {"\u2728"} 61 | 62 | 63 | Start scrolling to see some magic happen {"\u2728"} 64 | 65 | 66 | Start scrolling to see some magic happen {"\u2728"} 67 | 68 | 69 | Start scrolling to see some magic happen {"\u2728"} 70 | 71 | 72 | Start scrolling to see some magic happen {"\u2728"} 73 | 74 | 75 | Start scrolling to see some magic happen {"\u2728"} 76 | 77 | 78 | 79 | Start scrolling to see some magic happen {"\u2728"} 80 | 81 | 82 | Start scrolling to see some magic happen {"\u2728"} 83 | 84 | 85 | Start scrolling to see some magic happen {"\u2728"} 86 | 87 | 88 |
89 | ); 90 | 91 | render(, document.getElementById("root")); 92 | -------------------------------------------------------------------------------- /src/react-skrollr/Parallax.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | 4 | export default class Parallax extends React.Component { 5 | static contextTypes = { refresh: PropTypes.func } 6 | 7 | componentDidMount() { 8 | if (typeof this.context.refresh === 'function') this.context.refresh() 9 | } 10 | 11 | componentWillReceiveProps() { 12 | if (typeof this.context.refresh === 'function') this.context.refresh() 13 | } 14 | 15 | render() { 16 | const { data, children } = this.props 17 | return
{children}
18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/react-skrollr/ParallaxProvider.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import skrollr from 'skrollr' 4 | 5 | export default class ParallaxProvider extends React.Component { 6 | static propTypes = { 7 | init: PropTypes.object, 8 | disableOnMobile: PropTypes.bool 9 | } 10 | 11 | static defaultProps = { 12 | init: {}, 13 | disableOnMobile: true 14 | } 15 | 16 | initSkrollr() { 17 | this.skrollr = skrollr.init(this.props.init) 18 | } 19 | 20 | refresh = () => { 21 | if (this.skrollr) this.skrollr.refresh() 22 | } 23 | 24 | isMobile = () => { 25 | return /Android|iPhone|iPad|iPod|BlackBerry/i.test( 26 | navigator.userAgent || navigator.vendor || window.opera 27 | ) 28 | } 29 | 30 | shouldInitOrDestroy = () => { 31 | const { disableOnMobile } = this.props 32 | if (!disableOnMobile) { 33 | this.initSkrollr() 34 | return 35 | } 36 | 37 | if (disableOnMobile && this.isMobile() && this.skrollr !== undefined) { 38 | this.skrollr.destroy() 39 | this.skrollr = undefined 40 | } 41 | 42 | if (disableOnMobile && !this.isMobile() && this.skrollr === undefined) { 43 | this.initSkrollr() 44 | } 45 | } 46 | 47 | componentDidMount() { 48 | this.shouldInitOrDestroy() 49 | window.addEventListener('resize', this.shouldInitOrDestroy) 50 | } 51 | 52 | componentWillUnmount() { 53 | window.removeEventListener('resize', this.shouldInitOrDestroy) 54 | if (this.skrollr) this.skrollr.destroy() 55 | } 56 | 57 | static childContextTypes = { 58 | refresh: PropTypes.func 59 | } 60 | 61 | getChildContext() { 62 | return { refresh: this.refresh } 63 | } 64 | 65 | render() { 66 | const { children } = this.props 67 | return
{children}
68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/react-skrollr/index.js: -------------------------------------------------------------------------------- 1 | export { default as ParallaxProvider } from './ParallaxProvider' 2 | export { default as Parallax } from './Parallax' 3 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Arial'; 3 | text-align: center; 4 | background: #27c9ff; 5 | color: #fff; 6 | } 7 | span { 8 | height: 100px; 9 | background: #fff; 10 | color: #2fcaff; 11 | display: flex; 12 | justify-content: center; 13 | align-items: center; 14 | } 15 | .title { 16 | height: 100vh; 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | font-size: 60px; 21 | font-weight: bold; 22 | } --------------------------------------------------------------------------------