├── .gitignore ├── .npmignore ├── doc ├── image │ ├── sierra.jpg │ └── screen.svg ├── font │ ├── Lato-Light.eot │ ├── Lato-Light.ttf │ ├── Lato-Light.woff │ ├── Lato-Light.woff2 │ ├── Lato-Regular.eot │ ├── Lato-Regular.ttf │ ├── Lato-Regular.woff │ └── Lato-Regular.woff2 ├── index.html └── css │ └── style.css ├── bower.json ├── LICENSE ├── package.json ├── README.md ├── src ├── jsx │ ├── test.jsx │ └── react-screen.jsx └── sass │ └── react-screen.scss ├── gulpfile.js └── dist ├── react-screen.css └── react-screen.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | doc/ 2 | src/jsx/test.jsx -------------------------------------------------------------------------------- /doc/image/sierra.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/image/sierra.jpg -------------------------------------------------------------------------------- /doc/font/Lato-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Light.eot -------------------------------------------------------------------------------- /doc/font/Lato-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Light.ttf -------------------------------------------------------------------------------- /doc/font/Lato-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Light.woff -------------------------------------------------------------------------------- /doc/font/Lato-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Light.woff2 -------------------------------------------------------------------------------- /doc/font/Lato-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Regular.eot -------------------------------------------------------------------------------- /doc/font/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Regular.ttf -------------------------------------------------------------------------------- /doc/font/Lato-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Regular.woff -------------------------------------------------------------------------------- /doc/font/Lato-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gao-sun/react-screen/HEAD/doc/font/Lato-Regular.woff2 -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-screen", 3 | "description": "A different React carousel component.", 4 | "main": "dist/react-screen.js", 5 | "authors": [ 6 | "Gao Sun" 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "carousel", 11 | "react" 12 | ], 13 | "homepage": "https://github.com/gao-sun/react-screen" 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-screen", 3 | "version": "0.1.7", 4 | "description": "A different React carousel component.", 5 | "main": "dist/react-screen.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/gao-sun/react-screen.git" 12 | }, 13 | "keywords": [ 14 | "carousel", 15 | "react" 16 | ], 17 | "author": "Gao Sun", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/gao-sun/react-screen/issues" 21 | }, 22 | "homepage": "https://github.com/gao-sun/react-screen#readme", 23 | "devDependencies": { 24 | "babel-plugin-transform-class-properties": "^6.16.0", 25 | "babel-preset-es2015": "^6.16.0", 26 | "babel-preset-react": "^6.16.0", 27 | "babelify": "^7.3.0", 28 | "browserify": "^13.1.0", 29 | "gulp": "^3.9.1", 30 | "gulp-autoprefixer": "^3.1.1", 31 | "gulp-babel": "^6.1.2", 32 | "gulp-clean": "^0.3.2", 33 | "gulp-clean-css": "^2.0.13", 34 | "gulp-sass": "^2.3.2", 35 | "gulp-uglify": "^2.0.0", 36 | "react": "^15.3.2", 37 | "react-dom": "^15.3.2", 38 | "vinyl-buffer": "^1.0.0", 39 | "vinyl-source-stream": "^1.1.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-screen 2 | 3 | A lot of boring carousels? Let's try something else! 4 | 5 | ![Demo](https://gao-sun.github.io/react-screen/image/demo.gif) 6 | 7 | Full documentation @[react-screen](http://gao-sun.github.io/react-screen). 8 | 9 | ### Get Started 10 | 11 | 1.Install react-screen. 12 | ```baseh 13 | # Via npm 14 | npm install react-screen 15 | 16 | # Via Bower 17 | bower install react-screen 18 | ``` 19 | 20 | 2.Import react & react-screen. 21 | ```javascript 22 | import React, { Component } from 'react'; 23 | import ReactDOM from 'react-dom'; 24 | import { Screen, ScreenSlice } from 'react-screen'; 25 | ``` 26 | 27 | 3.Import stylesheet. 28 | ```javascript 29 | // In jsx 30 | import styles from 'node_modules/react-screen/dist/css/react-screen.css'; 31 | ``` 32 | 33 | Or 34 | ```html 35 | 36 | 37 | ``` 38 | 39 | 4.Render it! 40 | ```javascript 41 | ReactDOM.render(( 42 | 43 | 44 |

First Screen

45 |
46 | 47 |

Second Screen

48 |
49 | 50 |

Third Screen

51 |
52 |
53 | ), document.getElementById('react-screen')); 54 | ``` -------------------------------------------------------------------------------- /src/jsx/test.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Screen, ScreenSlice } from './react-screen.jsx'; 4 | 5 | ReactDOM.render(( 6 | 7 | 8 |
9 |
Immersive
10 |
Full screen. Full experience.
11 |
12 |
13 |
14 |
15 |
16 |
React Screen
17 |
18 |
19 |
20 |
21 | 22 |
23 |
Customizable
24 |
Put whatever you want.
25 |
26 |
27 |
React Screen
28 |
Button
29 |
30 |
31 |
32 | 33 |
34 |
35 | Modularized 36 |
37 |
38 | Clear. Clean. Clever. 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | ), document.getElementById('react-screen')); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const minifyCss = require('gulp-clean-css'); 3 | const browserify = require('browserify'); 4 | const babelify = require('babelify'); 5 | const source = require("vinyl-source-stream"); 6 | const buffer = require('vinyl-buffer'); 7 | const sass = require('gulp-sass'); 8 | const autoprefixer = require('gulp-autoprefixer'); 9 | const clean = require('gulp-clean'); 10 | const uglify = require('gulp-uglify'); 11 | const babel = require('gulp-babel'); 12 | 13 | const paths = { 14 | jsx: 'src/jsx/*.jsx', 15 | component: 'src/jsx/react-screen.jsx', 16 | test: 'src/jsx/test.jsx', 17 | sass: 'src/sass/*.scss', 18 | }; 19 | 20 | const debug = false; 21 | 22 | gulp.task('clean', function() { 23 | return gulp.src('dist/', { read: false }) 24 | .pipe(clean()); 25 | }); 26 | 27 | gulp.task('sass', ['clean'], function() { 28 | return gulp.src(paths.sass) 29 | .pipe(sass()) 30 | .pipe(autoprefixer({ 31 | browsers: ['last 10 versions'], 32 | cascade: false 33 | })) 34 | .pipe(minifyCss()) 35 | .pipe(gulp.dest('dist/')) 36 | }); 37 | 38 | gulp.task('generation', ['sass'], function() { 39 | let babelConfig = { presets: ['es2015', 'react'], plugins: ['transform-class-properties'] }; 40 | 41 | if(!debug) { 42 | return gulp.src(paths.component) 43 | .pipe(babel(babelConfig)) 44 | .pipe(uglify()) 45 | .pipe(gulp.dest('dist/')); 46 | } 47 | 48 | gulp.src(paths.component) 49 | .pipe(gulp.dest('dist/')); 50 | 51 | let b = browserify({ 52 | entries: paths.test, 53 | debug: debug, 54 | }); 55 | 56 | return b 57 | .transform('babelify', babelConfig) 58 | .bundle() 59 | .pipe(source('react-screen.js')) 60 | .pipe(buffer()) 61 | .pipe(gulp.dest('dist/')); 62 | }); 63 | 64 | // Whole build 65 | gulp.task('build', ['clean', 'sass', 'generation']); 66 | 67 | gulp.task('watch', function() { 68 | gulp.watch([paths.sass, paths.jsx], ['build']); 69 | }); 70 | 71 | gulp.task('default', ['build', 'watch']); -------------------------------------------------------------------------------- /doc/image/screen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/sass/react-screen.scss: -------------------------------------------------------------------------------- 1 | .react-screen-test { 2 | position: relative; 3 | width: 100%; 4 | height: 100vh; 5 | background: #888; 6 | } 7 | 8 | .react-screen-wrapper { 9 | &.out { 10 | & .react-screen-background, 11 | & .react-screen { 12 | z-index: -1; 13 | } 14 | } 15 | 16 | .hide { 17 | display: none; 18 | } 19 | } 20 | 21 | .react-screen-skip { 22 | position: fixed; 23 | z-index: 99999; 24 | bottom: 20px; 25 | right: 10px; 26 | transform: translateX(-50%); 27 | text-align: center; 28 | font-size: 1rem; 29 | color: #999; 30 | padding: .5rem 2rem; 31 | background-color: #f5f5f5; 32 | letter-spacing: 1px; 33 | border-radius: 5px; 34 | user-select: none; 35 | transition: all .2s ease; 36 | text-decoration: none; 37 | 38 | &:hover { 39 | cursor: pointer; 40 | background-color: #eee; 41 | color: #666; 42 | text-decoration: none; 43 | } 44 | } 45 | 46 | .react-screen { 47 | // display: none; 48 | position: fixed; 49 | left: 0; 50 | top: 0; 51 | width: 100%; 52 | height: 100%; 53 | background-color: #fafafa; 54 | z-index: 99998; 55 | 56 | /* In & Out */ 57 | &.in { 58 | animation-name: react-screen-in; 59 | animation-duration: .5s; 60 | animation-timing-function: ease-out; 61 | animation-fill-mode: forwards; 62 | z-index: 99999; 63 | 64 | .image-main, 65 | .description { 66 | opacity: 0; 67 | 68 | animation-name: react-screen-item-in; 69 | animation-duration: .5s; 70 | animation-timing-function: ease-out; 71 | animation-fill-mode: forwards; 72 | animation-delay: .2s; 73 | } 74 | } 75 | 76 | &.out { 77 | animation-name: react-screen-out; 78 | animation-duration: .5s; 79 | animation-timing-function: ease-out; 80 | animation-fill-mode: forwards; 81 | 82 | .image-main, 83 | .description { 84 | opacity: 1; 85 | 86 | animation-name: react-screen-item-out; 87 | animation-duration: .5s; 88 | animation-timing-function: ease-out; 89 | animation-fill-mode: forwards; 90 | animation-delay: 0s; 91 | } 92 | } 93 | } 94 | 95 | .react-screen-progress { 96 | position: fixed; 97 | right: 30px; 98 | top: 50%; 99 | width: 2px; 100 | transform: translateY(-50%); 101 | z-index: 99999; 102 | 103 | .item { 104 | position: relative; 105 | width: 2px; 106 | height: 40px; 107 | background: #ddd; 108 | 109 | .number { 110 | position: absolute; 111 | right: 15px; 112 | line-height: 40px; 113 | color: #ddd; 114 | 115 | &.active { 116 | color: #777; 117 | } 118 | 119 | &:hover { 120 | cursor: pointer; 121 | } 122 | } 123 | } 124 | 125 | .bar { 126 | position: absolute; 127 | top: 0; 128 | left: 0; 129 | width: 2px; 130 | height: 50%; 131 | background: #777; 132 | } 133 | } 134 | 135 | .react-screen-gap { 136 | position: relative; 137 | width: 100%; 138 | } 139 | 140 | .react-screen-background { 141 | position: fixed; 142 | z-index: 99998; 143 | background: #f5f5f5; 144 | top: 0; 145 | left: 0; 146 | width: 100%; 147 | height: 100%; 148 | 149 | &.in { 150 | animation-name: react-screen-in; 151 | animation-duration: .5s; 152 | animation-timing-function: ease-out; 153 | animation-fill-mode: forwards; 154 | } 155 | 156 | &.out { 157 | animation-name: react-screen-out; 158 | animation-duration: .5s; 159 | animation-timing-function: ease-out; 160 | animation-fill-mode: forwards; 161 | } 162 | } 163 | 164 | @keyframes react-screen-in { 165 | from { 166 | opacity: 0; 167 | } 168 | 169 | to { 170 | opacity: 1; 171 | } 172 | } 173 | 174 | @keyframes react-screen-out { 175 | from { 176 | opacity: 1; 177 | } 178 | 179 | to { 180 | opacity: 0; 181 | } 182 | } 183 | 184 | @keyframes react-screen-item-in { 185 | from { 186 | opacity: .2; 187 | transform: translateY(80%); 188 | } 189 | 190 | to { 191 | opacity: 1; 192 | transform: translateY(0); 193 | } 194 | } 195 | 196 | @keyframes react-screen-item-out { 197 | from { 198 | opacity: 1; 199 | transform: translateY(0); 200 | } 201 | 202 | to { 203 | opacity: .2; 204 | transform: translateY(80%); 205 | } 206 | } -------------------------------------------------------------------------------- /dist/react-screen.css: -------------------------------------------------------------------------------- 1 | .react-screen-test{position:relative;width:100%;height:100vh;background:#888}.react-screen-wrapper.out .react-screen,.react-screen-wrapper.out .react-screen-background{z-index:-1}.react-screen-wrapper .hide{display:none}.react-screen-skip{position:fixed;z-index:99999;bottom:20px;right:10px;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);text-align:center;font-size:1rem;color:#999;padding:.5rem 2rem;background-color:#f5f5f5;letter-spacing:1px;border-radius:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .2s ease;transition:all .2s ease;text-decoration:none}.react-screen-skip:hover{cursor:pointer;background-color:#eee;color:#666;text-decoration:none}.react-screen{position:fixed;left:0;top:0;width:100%;height:100%;background-color:#fafafa;z-index:99998}.react-screen.in{-webkit-animation-name:react-screen-in;animation-name:react-screen-in;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;z-index:99999}.react-screen.in .description,.react-screen.in .image-main,.react-screen.out{-webkit-animation-duration:.5s;-webkit-animation-timing-function:ease-out;-webkit-animation-fill-mode:forwards}.react-screen.in .description,.react-screen.in .image-main{opacity:0;-webkit-animation-name:react-screen-item-in;animation-name:react-screen-item-in;animation-duration:.5s;animation-timing-function:ease-out;animation-fill-mode:forwards;-webkit-animation-delay:.2s;animation-delay:.2s}.react-screen.out{-webkit-animation-name:react-screen-out;animation-name:react-screen-out;animation-duration:.5s;animation-timing-function:ease-out;animation-fill-mode:forwards}.react-screen-background.in,.react-screen.out .description,.react-screen.out .image-main{-webkit-animation-duration:.5s;-webkit-animation-timing-function:ease-out;-webkit-animation-fill-mode:forwards}.react-screen.out .description,.react-screen.out .image-main{opacity:1;-webkit-animation-name:react-screen-item-out;animation-name:react-screen-item-out;animation-duration:.5s;animation-timing-function:ease-out;animation-fill-mode:forwards;-webkit-animation-delay:0s;animation-delay:0s}.react-screen-progress{position:fixed;right:30px;top:50%;width:2px;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);z-index:99999}.react-screen-progress .item{position:relative;width:2px;height:40px;background:#ddd}.react-screen-progress .item .number{position:absolute;right:15px;line-height:40px;color:#ddd}.react-screen-progress .item .number.active{color:#777}.react-screen-progress .item .number:hover{cursor:pointer}.react-screen-progress .bar{position:absolute;top:0;left:0;width:2px;height:50%;background:#777}.react-screen-gap{position:relative;width:100%}.react-screen-background{position:fixed;z-index:99998;background:#f5f5f5;top:0;left:0;width:100%;height:100%}.react-screen-background.in{-webkit-animation-name:react-screen-in;animation-name:react-screen-in;animation-duration:.5s;animation-timing-function:ease-out;animation-fill-mode:forwards}.react-screen-background.out{-webkit-animation-name:react-screen-out;animation-name:react-screen-out;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes react-screen-in{from{opacity:0}to{opacity:1}}@keyframes react-screen-in{from{opacity:0}to{opacity:1}}@-webkit-keyframes react-screen-out{from{opacity:1}to{opacity:0}}@keyframes react-screen-out{from{opacity:1}to{opacity:0}}@-webkit-keyframes react-screen-item-in{from{opacity:.2;-webkit-transform:translateY(80%);transform:translateY(80%)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes react-screen-item-in{from{opacity:.2;-webkit-transform:translateY(80%);transform:translateY(80%)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes react-screen-item-out{from{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}to{opacity:.2;-webkit-transform:translateY(80%);transform:translateY(80%)}}@keyframes react-screen-item-out{from{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}to{opacity:.2;-webkit-transform:translateY(80%);transform:translateY(80%)}} -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Screen 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | React Screen 15 |
A different React carousel component.
16 |
17 | Document 18 | Github 19 |
20 |
21 |
22 |
23 |
Too many boring carousel?
24 |
Need a fancy way to show banners?
25 |
JUST SCROLL DOWN
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Document
33 |
Get Started
34 |
1. Install react-screen.
35 |
# Via npm
36 | npm install react-screen
37 | 
38 | # Via Bower
39 | bower install react-screen
40 |
2. Import react & react-screen.
41 |
import React, { Component } from 'react';
42 | import ReactDOM from 'react-dom';
43 | import { Screen, ScreenSlice } from 'react-screen';
44 |
3. Import stylesheet.
45 |
// In jsx
46 | import styles from 'path/to/css/react-screen.css';
47 |
Or
48 |
<!-- In HTML -->
49 | <link rel="stylesheet" href="path/to/css/react-screen.css">
50 |
4. Render it!
51 |
ReactDOM.render((
52 |     <Screen>
53 |         <ScreenSlice>
54 |             <h1>First Screen</h1>
55 |         </ScreenSlice>
56 |         <ScreenSlice>
57 |             <h1>Second Screen</h1>
58 |         </ScreenSlice>
59 |         <ScreenSlice>
60 |             <h1>Third Screen</h1>
61 |         </ScreenSlice>
62 |     </Screen>
63 | ), document.getElementById('react-screen'));
64 |
Properties
65 |
// Values show below are default.
66 | <Screen style={} sliceHeight={ 60 } delay={ 500 } showSkip={ true }>
67 | 
68 | // Descriptions
69 | {
70 |     style: "A React style object. It will apply to every screen."
71 |     sliceHeight: "Unit: vh. Implies each screen's scroll height.",
72 |     delay: 
73 |     	"Unit: ms. When scroll to a new screen, it will disables scroll for a while. 
74 |     	Useful for playing animation.",
75 |     showSkip: "Boolean. Determines whether show a skip button on screen."
76 | }
77 | 
78 |
Styling
79 |
You can easily overwrite styles, just use inspect tool to check class names.
80 |
Animation
81 |
react-screen will add class "in" to the screen just entered in, and class "out" to other screens. So you can write your own animation like this:
82 |
.react-screen.in .your-element-class {
83 |     /* In animation */
84 | }
85 | 
86 | .react-screen.out .your-element-class {
87 |     /* Out animation */
88 | }
89 | 
90 |
Issues and Contributing
91 |
If you find any bugs or have any advices, please leave an issue. Feel free to make a pull request and wait for accpetance!
92 |
93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /dist/react-screen.js: -------------------------------------------------------------------------------- 1 | "use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function preventDefault(e){e=e||window.event,e.preventDefault&&e.preventDefault(),e.returnValue=!1}function preventDefaultForScrollKeys(e){if(scrollKeys[e.keyCode])return preventDefault(e),!1}function disableScroll(){window.addEventListener&&window.addEventListener("DOMMouseScroll",preventDefault,!1),window.onwheel=preventDefault,window.onmousewheel=document.onmousewheel=preventDefault,window.ontouchmove=preventDefault,document.onkeydown=preventDefaultForScrollKeys}function enableScroll(){window.removeEventListener&&window.removeEventListener("DOMMouseScroll",preventDefault,!1),window.onmousewheel=document.onmousewheel=null,window.onwheel=null,window.ontouchmove=null,document.onkeydown=null}Object.defineProperty(exports,"__esModule",{value:!0}),exports.ScreenSlice=exports.Screen=void 0;var _createClass=function(){function e(e,t){for(var r=0;r=0&&l=0&&l=0&&l0&&this.prevIndex!=l&&this.blockScrollForAnimation(),this.blockAt(a).animateIn(),this.refs["number-"+a].classList.add("active")):(this.blockAt(a).animateOut(),this.refs["number-"+a].classList.remove("active"));this.prevIndex=l}},{key:"jumpTo",value:function(e){var t=this.length,r=window.innerHeight,n=this.getPosition(this.refs.gap).y,s=n-.5*r,o=this.refs.gap.offsetHeight;window.scrollTo(0,e*(o/t)+s+1)}}]),_createClass(t,[{key:"componentDidMount",value:function(){window.addEventListener("scroll",this.scrollListener),this.handleScroll()}},{key:"componentWillUnmount",value:function(){window.removeEventListener("scroll",this.scrollListener)}},{key:"render",value:function(){for(var e=this,t=[],r=0;r { 69 | method.bind(this)(); 70 | }, delay); 71 | } 72 | 73 | blockScrollForAnimation() { 74 | disableScroll(); 75 | setTimeout(function() { 76 | enableScroll(); 77 | }, this.delay); 78 | } 79 | 80 | skip() { 81 | window.scrollTo(0, this.getPosition(this.refs.gap).y + this.refs.gap.offsetHeight); 82 | } 83 | 84 | handleScroll() { 85 | let length = this.length; 86 | let innerHeight = window.innerHeight; 87 | let bodyScrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; 88 | let screenTop = this.getPosition(this.refs.gap).y; 89 | let screenStartTop = screenTop - 0.5 * innerHeight; 90 | let screenHeight = this.refs.gap.offsetHeight; 91 | let screenIndex = Math.floor((bodyScrollTop - screenStartTop) / (screenHeight / length)); 92 | 93 | // Background 94 | if(screenIndex >= 0 && screenIndex < length) { 95 | this.refs.background.classList.remove('out'); 96 | 97 | // Move slider to top, need a fancier way 98 | clearTimeout(this.removeWrapperTimeoutId); 99 | this.refs.wrapper.classList.remove('out'); 100 | this.removeWrapperTimeoutId = null; 101 | } else { 102 | this.refs.background.classList.add('out'); 103 | 104 | // Move slider to bottom, need a fancier way 105 | if(this.removeWrapperTimeoutId == null) { 106 | this.removeWrapperTimeoutId = window.setTimeout(() => { 107 | this.refs.wrapper.classList.add('out'); 108 | }, 500); 109 | } 110 | } 111 | // Progress 112 | if(screenIndex >= 0 && screenIndex < length) { 113 | this.refs.progress.classList.remove('hide'); 114 | this.refs['progress-bar'].style.height = (((bodyScrollTop - screenStartTop) / screenHeight) * 100) + '%'; 115 | } else { 116 | this.refs.progress.classList.add('hide'); 117 | } 118 | 119 | // Skip 120 | if(this.showSkip && screenIndex >= 0 && screenIndex < length) { 121 | this.refs.skip.classList.remove('hide'); 122 | } else { 123 | this.refs.skip.classList.add('hide'); 124 | } 125 | 126 | // Screen 127 | for(let i = 0; i < length; ++ i) { 128 | if(i == screenIndex) { 129 | if(this.delay > 0 && this.prevIndex != screenIndex) { 130 | this.blockScrollForAnimation(); 131 | } 132 | 133 | this.blockAt(i).animateIn(); 134 | this.refs['number-' + i].classList.add('active'); 135 | } else { 136 | this.blockAt(i).animateOut(); 137 | this.refs['number-' + i].classList.remove('active'); 138 | } 139 | } 140 | 141 | this.prevIndex = screenIndex; 142 | } 143 | 144 | jumpTo(index) { 145 | let length = this.length; 146 | let innerHeight = window.innerHeight; 147 | let screenTop = this.getPosition(this.refs.gap).y; 148 | let screenStartTop = screenTop - 0.5 * innerHeight; 149 | let screenHeight = this.refs.gap.offsetHeight; 150 | 151 | window.scrollTo(0, index * (screenHeight / length) + screenStartTop + 1); 152 | } 153 | 154 | // Original Event Handlers 155 | constructor(props) { 156 | super(props); 157 | this.length = Array.isArray(props.children) ? props.children.length : 1; 158 | (props.delay != undefined) && (this.delay = props.delay); 159 | (props.sliceHeight != undefined) && (this.sliceHeight = props.sliceHeight); 160 | (props.showSkip != undefined) && (this.showSkip = props.showSkip); 161 | } 162 | componentDidMount() { 163 | window.addEventListener('scroll', this.scrollListener); 164 | this.handleScroll(); 165 | } 166 | 167 | componentWillUnmount() { 168 | window.removeEventListener('scroll', this.scrollListener); 169 | } 170 | 171 | render() { 172 | let numbers = []; 173 | 174 | for(let i = 0; i < this.length; ++ i) { 175 | numbers.push( 176 |
177 |
{ (i + 1) }
178 |
179 | ); 180 | } 181 | 182 | let index = 0; 183 | let slices = React.Children.map(this.props.children, 184 | (child) => React.cloneElement(child, { 185 | ref: 'slice-' + (index++), 186 | style: this.props.style 187 | }) 188 | ); 189 | 190 | return ( 191 |
192 |
193 |
194 |
195 | { slices } 196 |
197 | { numbers } 198 |
199 |
200 |
SKIP
201 |
202 |
203 | ); 204 | } 205 | } 206 | 207 | export class ScreenSlice extends Component { 208 | cleanUp() { 209 | this.refs.screen.classList.remove('in'); 210 | this.refs.screen.classList.remove('out'); 211 | } 212 | animateIn() { 213 | this.cleanUp(); 214 | this.refs.screen.classList.add('in'); 215 | } 216 | animateOut() { 217 | this.cleanUp(); 218 | this.refs.screen.classList.add('out'); 219 | } 220 | render() { 221 | return ( 222 |
{ this.props.children }
223 | ); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /doc/css/style.css: -------------------------------------------------------------------------------- 1 | /* Webfont: Lato-Light */@font-face { 2 | font-family: 'LatoWebLight'; 3 | src: url('../font/Lato-Light.eot'); /* IE9 Compat Modes */ 4 | src: url('../font/Lato-Light.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 5 | url('../font/Lato-Light.woff2') format('woff2'), /* Modern Browsers */ 6 | url('../font/Lato-Light.woff') format('woff'), /* Modern Browsers */ 7 | url('../font/Lato-Light.ttf') format('truetype'); 8 | font-style: normal; 9 | font-weight: normal; 10 | text-rendering: optimizeLegibility; 11 | } 12 | 13 | /* Webfont: Lato-Regular */@font-face { 14 | font-family: 'LatoWeb'; 15 | src: url('../font/Lato-Regular.eot'); /* IE9 Compat Modes */ 16 | src: url('../font/Lato-Regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ 17 | url('../font/Lato-Regular.woff2') format('woff2'), /* Modern Browsers */ 18 | url('../font/Lato-Regular.woff') format('woff'), /* Modern Browsers */ 19 | url('../font/Lato-Regular.ttf') format('truetype'); 20 | font-style: normal; 21 | font-weight: normal; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | html, body { 26 | margin: 0; 27 | padding: 0; 28 | font-family: 'Lato', 'LatoWebLight', 'Myriad Pro', 'Helvetica'; 29 | font-weight: 300; 30 | font-size: 12px; 31 | color: #333; 32 | } 33 | 34 | .font-light { 35 | font-family: 'Lato', 'LatoWebLight', 'Myriad Pro', 'Helvetica'; 36 | font-weight: 300; 37 | } 38 | 39 | .font-regular { 40 | font-family: 'Lato', 'LatoWeb', 'Myriad Pro', 'Helvetica'; 41 | font-weight: 400; 42 | } 43 | 44 | .block { 45 | width: 90%; 46 | margin: 0 auto; 47 | max-width: 1000px; 48 | font-size: 1.3rem; 49 | } 50 | 51 | 52 | /* Repo */ 53 | 54 | .repo { 55 | position: relative; 56 | padding: 0; 57 | text-align: center; 58 | min-height: 100vh; 59 | background: #fafafa; 60 | } 61 | 62 | .repo .title { 63 | font-size: 4rem; 64 | padding: 20vh 0; 65 | background-color: #1d1d1d; 66 | color: #2852fd; 67 | } 68 | 69 | .repo .subtitle { 70 | padding: 1.2rem; 71 | font-size: 1.3rem; 72 | color: #c5c5c5; 73 | } 74 | 75 | .repo .intro { 76 | padding: 6rem 0; 77 | } 78 | 79 | .repo .button-group .button { 80 | display: inline-block; 81 | width: 120px; 82 | font-size: 1.2rem; 83 | padding: .6rem 0; 84 | color: #333; 85 | background-color: #eee; 86 | border-radius: 3px; 87 | text-decoration: none; 88 | transition: all ease .2s; 89 | } 90 | 91 | .repo .button-group .button:hover { 92 | cursor: pointer; 93 | background-color: #ccc; 94 | } 95 | 96 | .repo .block .item { 97 | font-size: 1.8rem; 98 | padding: 1.3rem; 99 | color: #555; 100 | } 101 | 102 | /* Document */ 103 | 104 | .document { 105 | min-height: 100vh; 106 | background: #fafafa; 107 | padding: 2rem 0; 108 | } 109 | 110 | .document .bigtitle { 111 | padding: 1rem 0; 112 | font-size: 3rem; 113 | } 114 | 115 | .document .title { 116 | padding: 1rem 0; 117 | font-size: 2rem; 118 | color: rgb(7,120,215); 119 | } 120 | 121 | .document .text { 122 | padding: 1rem 0; 123 | font-size: 1.5rem; 124 | } 125 | 126 | /* Screen */ 127 | 128 | .screen { 129 | position: absolute; 130 | width: 100%; 131 | height: 100%; 132 | top: 0; 133 | left: 0; 134 | perspective: 150vw; 135 | } 136 | 137 | .screen > .title { 138 | position: absolute; 139 | left: 10%; 140 | top: 10%; 141 | font-size: 3rem; 142 | color: #333; 143 | } 144 | 145 | .screen > .text { 146 | position: absolute; 147 | left: 10%; 148 | top: calc(10% + 4rem); 149 | font-size: 1.5rem; 150 | color: #888; 151 | } 152 | 153 | /* Screen 1 */ 154 | 155 | .screen-1-base, 156 | .screen-2-base { 157 | position: absolute; 158 | width: 60%; 159 | height: 50%; 160 | left: 50%; 161 | top: 50%; 162 | background: #ddd; 163 | border-radius: 3px; 164 | overflow: hidden; 165 | box-shadow: 5px 5px 5px rgba(233,233,233,.8); 166 | } 167 | 168 | .screen-1-base { 169 | transform: translateX(-50%) translateY(-50%); 170 | } 171 | 172 | .screen-1-base .block { 173 | position: absolute; 174 | height: 80%; 175 | border-radius: 3px; 176 | } 177 | 178 | .screen-1-base .block .image { 179 | position: absolute; 180 | width: 20%; 181 | height: 20%; 182 | left: 30%; 183 | top: 50%; 184 | 185 | transform: translateX(-50%) translateY(-50%); 186 | background-image: url(../image/screen.svg); 187 | background-position: center; 188 | background-repeat: no-repeat; 189 | background-size: contain; 190 | } 191 | 192 | .screen-1-base .block .text { 193 | position: absolute; 194 | width: 35%; 195 | height: 20%; 196 | left: 65%; 197 | top: 55%; 198 | font-size: 2vw; 199 | color: rgba(0,57,179,1); 200 | overflow: hidden; 201 | text-overflow: ellipsis; 202 | white-space: nowrap; 203 | 204 | transform: translateX(-50%) translateY(-50%); 205 | } 206 | 207 | .screen-1-base .block.block-1 { 208 | background: rgba(79, 127, 232, .9); 209 | top: 10%; 210 | left: 10%; 211 | width: 50%; 212 | } 213 | 214 | .screen-1-base .block.block-2 { 215 | background: rgba(151,183,242,.9); 216 | top: 10%; 217 | left: 65%; 218 | width: 25%; 219 | } 220 | 221 | .screen-1-base .block.block-3 { 222 | background: #f5f5f5; 223 | top: 100%; 224 | left: 0; 225 | width: 100%; 226 | height: 100%; 227 | transform: scaleX(0.8) scaleY(0.8); 228 | overflow: hidden; 229 | } 230 | 231 | .react-screen.in .screen-1-base .block.block-1, 232 | .react-screen.in .screen-1-base .block.block-2 { 233 | animation-delay: .3s; 234 | animation-duration: 1s; 235 | animation-timing-function: ease; 236 | animation-fill-mode: forwards; 237 | animation-name: ReactScreen-1-Scroll; 238 | } 239 | 240 | .react-screen.in .screen-1-base .block.block-3 { 241 | animation-delay: .3s, 1.3s; 242 | animation-duration: 1s, .8s; 243 | animation-timing-function: ease; 244 | animation-fill-mode: forwards; 245 | animation-name: ReactScreen-1-Screen-Scroll, ReactScreen-1-Resize; 246 | } 247 | 248 | .react-screen.out .screen-1-base .block.block-1, 249 | .react-screen.out .screen-1-base .block.block-2 { 250 | animation: none; 251 | transform: translateY(-113%); 252 | } 253 | 254 | .react-screen.out .screen-1-base .block.block-3 { 255 | animation: none; 256 | transform: translateY(-100%) scaleX(1) scaleY(1); 257 | } 258 | 259 | @keyframes ReactScreen-1-Scroll { 260 | to { 261 | transform: translateY(-113%); 262 | } 263 | } 264 | 265 | @keyframes ReactScreen-1-Screen-Scroll { 266 | from { 267 | transform: scaleX(0.8) scaleY(0.8); 268 | } 269 | to { 270 | transform: translateY(-100%) scaleX(0.8) scaleY(0.8);; 271 | } 272 | } 273 | 274 | @keyframes ReactScreen-1-Resize { 275 | from { 276 | transform: translateY(-100%) scaleX(0.8) scaleY(0.8); 277 | } 278 | to { 279 | transform: translateY(-100%) scaleX(1) scaleY(1); 280 | } 281 | } 282 | 283 | /* Screen 2 */ 284 | .screen-2-base { 285 | transform: translateX(-50%) translateY(-50%); 286 | } 287 | 288 | .screen-2-base .image { 289 | position: absolute; 290 | top: 0; 291 | left: 0; 292 | width: 100%; 293 | height: 100%; 294 | transform: translateY(100%); 295 | 296 | background-image: url(../image/sierra.jpg); 297 | background-position: center; 298 | background-size: cover; 299 | background-repeat: no-repeat; 300 | } 301 | 302 | .screen-2-base .text { 303 | position: absolute; 304 | top: 15%; 305 | left: 0; 306 | width: 100%; 307 | text-align: center; 308 | color: white; 309 | font-size: 3vw; 310 | font-family: 'Lato', 'LatoWeb'; 311 | font-weight: 400; 312 | opacity: 0; 313 | } 314 | 315 | .screen-2-base .button { 316 | position: absolute; 317 | top: 50%; 318 | left: 50%; 319 | width: 70px; 320 | font-size: 1vw; 321 | padding: .3vw 1.3vw; 322 | border-radius: 3px; 323 | background: rgba(39, 87, 232, .9); 324 | text-align: center; 325 | color: white; 326 | opacity: 0; 327 | } 328 | 329 | .react-screen.in .screen-2-base .image { 330 | animation-delay: .2s; 331 | animation-duration: 1s; 332 | animation-timing-function: ease; 333 | animation-fill-mode: forwards; 334 | animation-name: ReactScreen-2-Image; 335 | } 336 | 337 | .react-screen.in .screen-2-base .text { 338 | animation-delay: 1.2s; 339 | animation-duration: .6s; 340 | animation-timing-function: ease; 341 | animation-fill-mode: forwards; 342 | animation-name: ReactScreen-2-Text; 343 | } 344 | 345 | .react-screen.in .screen-2-base .button { 346 | animation-delay: 1.8s; 347 | animation-duration: .6s; 348 | animation-timing-function: ease; 349 | animation-fill-mode: forwards; 350 | animation-name: ReactScreen-2-Button; 351 | } 352 | 353 | .react-screen.out .screen-2-base .image, 354 | .react-screen.out .screen-2-base .text, 355 | .react-screen.out .screen-2-base .button { 356 | animation: none; 357 | } 358 | 359 | .react-screen.out .screen-2-base .image { 360 | transform: none; 361 | } 362 | 363 | .react-screen.out .screen-2-base .text { 364 | opacity: 1; 365 | transform: none; 366 | } 367 | 368 | .react-screen.out .screen-2-base .button { 369 | opacity: 1; 370 | transform: translateX(-50%) translateY(-100%); 371 | } 372 | 373 | @keyframes ReactScreen-2-Image { 374 | from { 375 | transform: translateY(100%); 376 | } 377 | 378 | to { 379 | transform: none; 380 | } 381 | } 382 | 383 | @keyframes ReactScreen-2-Text { 384 | from { 385 | opacity: 0; 386 | transform: translateY(-100%); 387 | } 388 | 389 | to { 390 | opacity: 1; 391 | transform: translateY(0); 392 | } 393 | } 394 | 395 | @keyframes ReactScreen-2-Button { 396 | from { 397 | opacity: 0; 398 | transform: translateX(-50%) translateY(0); 399 | } 400 | 401 | to { 402 | opacity: 1; 403 | transform: translateX(-50%) translateY(-100%); 404 | } 405 | } 406 | 407 | /* Screen 3 */ 408 | 409 | .rec { 410 | /*transform: translateX(-50%) translateY(-50%);*/ 411 | transform: translateX(-50%) translateY(-50%) rotateX(60deg) rotateZ(50deg); 412 | 413 | border-radius: 3px; 414 | } 415 | 416 | .rec-base-1 { 417 | position: absolute; 418 | width: 40%; 419 | height: 40%; 420 | left: 50%; 421 | top: 50%; 422 | background: rgba(0, 57, 179, .9); 423 | box-shadow: 10px 10px 5px rgba(233,233,233,.8); 424 | } 425 | 426 | .rec-base-2 { 427 | position: absolute; 428 | width: 40%; 429 | height: 40%; 430 | left: 50%; 431 | top: 45%; 432 | opacity: 0; 433 | } 434 | 435 | .rec-base-3 { 436 | position: absolute; 437 | width: 40%; 438 | height: 40%; 439 | left: 50%; 440 | top: 40%; 441 | opacity: 0; 442 | } 443 | 444 | .rec-block-1 { 445 | position: absolute; 446 | width: 85%; 447 | height: 100%; 448 | left: 1%; 449 | top: 1%; 450 | background: rgba(79, 127, 232, .9); 451 | border-radius: 3px; 452 | } 453 | 454 | .rec-block-2 { 455 | position: absolute; 456 | width: 12%; 457 | height: 100%; 458 | left: 87%; 459 | top: 1%; 460 | background: rgba(104,146,237,.9); 461 | border-radius: 3px; 462 | } 463 | 464 | .rec-block-3 { 465 | position: absolute; 466 | width: 30%; 467 | height: 50%; 468 | left: 2%; 469 | top: 1%; 470 | background: rgba(151,183,242,.9); 471 | border-radius: 3px; 472 | } 473 | 474 | .rec-block-4 { 475 | position: absolute; 476 | width: 50%; 477 | height: 100%; 478 | left: 33%; 479 | top: 1%; 480 | background: rgba(190,208,247,.9); 481 | border-radius: 3px; 482 | } 483 | 484 | .react-screen.in .rec { 485 | animation-duration: .7s; 486 | animation-timing-function: ease; 487 | animation-fill-mode: forwards; 488 | } 489 | 490 | .react-screen.in .rec-base-1 { 491 | animation-name: ReactScreenFlyInBase; 492 | } 493 | 494 | .react-screen.in .rec-base-2 { 495 | animation-name: ReactScreenFlyInElements; 496 | animation-delay: .2s; 497 | } 498 | 499 | .react-screen.in .rec-base-3 { 500 | animation-name: ReactScreenFlyInElements2; 501 | animation-delay: .4s; 502 | } 503 | 504 | .react-screen.out .rec { 505 | animation: none; 506 | opacity: 1; 507 | } 508 | 509 | .react-screen.in .rec-base-1 { 510 | top: 50%; 511 | } 512 | 513 | .react-screen.in .rec-base-2 { 514 | top: 45%; 515 | } 516 | 517 | .react-screen.in .rec-base-3 { 518 | top: 40%; 519 | } 520 | 521 | @keyframes ReactScreenFlyInBase { 522 | from { 523 | top: 65%; 524 | opacity: .2; 525 | } 526 | 527 | to { 528 | top: 50%; 529 | opacity: 1; 530 | } 531 | } 532 | 533 | @keyframes ReactScreenFlyInElements { 534 | from { 535 | top: 55%; 536 | opacity: 0; 537 | } 538 | 539 | to { 540 | top: 45%; 541 | opacity: 1; 542 | } 543 | } 544 | 545 | @keyframes ReactScreenFlyInElements2 { 546 | from { 547 | top: 50%; 548 | opacity: 0; 549 | } 550 | 551 | to { 552 | top: 40%; 553 | opacity: 1; 554 | } 555 | } --------------------------------------------------------------------------------