feature (loader): awesome loader on intial page load

This commit is contained in:
Mickael KERJEAN 2019-03-15 16:35:47 +11:00
parent 63670050ff
commit c2361c105a
3 changed files with 330 additions and 3 deletions

View file

@ -60,4 +60,4 @@ Filestash can be used in different settings:
# Credits # Credits
- [Contributors](https://github.com/mickael-kerjean/filestash/graphs/contributors) and folks developing awesome libraries (libvips, libraw, ...) - [Contributors](https://github.com/mickael-kerjean/filestash/graphs/contributors) and folks developing awesome libraries (libvips, libraw, ...)
- Logo derived from the work of [ssnjrthegr8](https://github.com/ssnjrthegr8), Iconography from [flaticon](https://www.flaticon.com/), [fontawesome](https://fontawesome.com) and [material](https://material.io/icons/) - Logo derived from the work of [ssnjrthegr8](https://github.com/ssnjrthegr8), Iconography from [flaticon](https://www.flaticon.com/), [fontawesome](https://fontawesome.com) and [material](https://material.io/icons/), loader adapted from [Mr Alien](https://codepen.io/mr_alien/pen/FDLjg)

View file

@ -33,7 +33,268 @@
$style = document.querySelector("style"); $style = document.querySelector("style");
$style.innerText = $style.innerText.replace("#f2f3f5", "#9AD1ED") $style.innerText = $style.innerText.replace("#f2f3f5", "#9AD1ED")
} }
window.initTime = new Date();
window.setTimeout(function(){
var $loader = document.querySelector(".index-loader");
if($loader) $loader.removeAttribute("style");
}, 2000);
</script> </script>
<div class="index-loader" style="display:none">
<div class="guy">
<span>
<span></span>
<span></span>
<span></span>
<span></span>
</span>
<div class="base">
<span></span>
<div class="face"></div>
</div>
</div>
<div class="longfazers">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<style>
.guy {
position: absolute;
top: 50%;
margin-left: -50px;
left: 40%;
animation: speeder 1s linear infinite;
}
.guy > span {
height: 5px;
width: 35px;
background: #626466;
position: absolute;
top: -19px;
left: 60px;
border-radius: 2px 10px 1px 0;
}
.base span {
position: absolute;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-right: 100px solid #626466;
border-bottom: 6px solid transparent;
}
.base span:before {
content: "";
height: 22px;
width: 22px;
border-radius: 50%;
background: #626466;
position: absolute;
right: -110px;
top: -16px;
}
.base span:after {
content: "";
position: absolute;
width: 0;
height: 0;
border-top: 0 solid transparent;
border-right: 55px solid #626466;
border-bottom: 16px solid transparent;
top: -16px;
right: -98px;
}
.face {
position: absolute;
height: 12px;
width: 20px;
background: #626466;
border-radius: 20px 20px 0 0;
transform: rotate(-40deg);
right: -125px;
top: -15px;
}
.face:after {
content: "";
height: 12px;
width: 12px;
background: #626466;
right: 4px;
top: 7px;
position: absolute;
transform: rotate(40deg);
transform-origin: 50% 50%;
border-radius: 0 0 0 2px;
}
.guy > span > span:nth-child(1),
.guy > span > span:nth-child(2),
.guy > span > span:nth-child(3),
.guy > span > span:nth-child(4) {
width: 30px;
height: 1px;
background: #626466;
position: absolute;
animation: fazer1 .2s linear infinite;
}
.guy > span > span:nth-child(2) {
top: 3px;
animation: fazer2 .4s linear infinite;
}
.guy > span > span:nth-child(3) {
top: 1px;
animation: fazer3 .4s linear infinite;
animation-delay: -1s;
}
.guy > span > span:nth-child(4) {
top: 4px;
animation: fazer4 1s linear infinite;
animation-delay: -1s;
}
@keyframes fazer1 {
0% {
left: 0;
}
100% {
left: -80px;
opacity: 0;
}
}
@keyframes fazer2 {
0% {
left: 0;
}
100% {
left: -100px;
opacity: 0;
}
}
@keyframes fazer3 {
0% {
left: 0;
}
100% {
left: -50px;
opacity: 0;
}
}
@keyframes fazer4 {
0% {
left: 0;
}
100% {
left: -150px;
opacity: 0;
}
}
@keyframes speeder {
0% {
transform: translate(1px, 1px) rotate(0deg);
}
10% {
transform: translate(-1px, -1px) rotate(-1deg);
}
20% {
transform: translate(-2px, 0px) rotate(1deg);
}
30% {
transform: translate(1px, 2px) rotate(0deg);
}
40% {
transform: translate(1px, -1px) rotate(1deg);
}
50% {
transform: translate(-1px, 3px) rotate(-1deg);
}
60% {
transform: translate(-1px, 1px) rotate(0deg);
}
70% {
transform: translate(3px, 1px) rotate(-1deg);
}
80% {
transform: translate(-2px, -1px) rotate(1deg);
}
90% {
transform: translate(2px, 1px) rotate(0deg);
}
}
.longfazers {
overflow: hidden;
position: absolute;
width: 100%;
height: 100%;
}
.longfazers span {
position: absolute;
height: 2px;
width: 20%;
background: #626466;
}
.longfazers span:nth-child(1) {
top: 20%;
animation: lf .6s linear infinite;
animation-delay: -5s;
}
.longfazers span:nth-child(2) {
top: 40%;
animation: lf2 .8s linear infinite;
animation-delay: -1s;
}
.longfazers span:nth-child(3) {
top: 60%;
animation: lf3 .6s linear infinite;
}
.longfazers span:nth-child(4) {
top: 80%;
animation: lf4 .5s linear infinite;
animation-delay: -3s;
}
@keyframes lf {
0% {
left: 200%;
}
100% {
left: -200%;
opacity: 0;
}
}
@keyframes lf2 {
0% {
left: 200%;
}
100% {
left: -200%;
opacity: 0;
}
}
@keyframes lf3 {
0% {
left: 200%;
}
100% {
left: -100%;
opacity: 0;
}
}
@keyframes lf4 {
0% {
left: 200%;
}
100% {
left: -100%;
opacity: 0;
}
}
</style>
<noscript> <noscript>
<div> <div>
<h2>Error: Javascript is off</h2> <h2>Error: Javascript is off</h2>

View file

@ -2,16 +2,82 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import Router from './router'; import Router from './router';
import { Config } from "./model/" import { Config } from "./model/";
import './assets/css/reset.scss'; import './assets/css/reset.scss';
const $loader = document.querySelector(".index-loader");
const $loader_guy = $loader.querySelector(".guy");
const $loader_particules = $loader.querySelector(".longfazers");
window.addEventListener("DOMContentLoaded", () => { window.addEventListener("DOMContentLoaded", () => {
const className = 'ontouchstart' in window ? 'touch-yes' : 'touch-no'; const className = 'ontouchstart' in window ? 'touch-yes' : 'touch-no';
document.body.classList.add(className); document.body.classList.add(className);
Config.refresh().then(() => { function render(){
ReactDOM.render(<Router/>, document.getElementById('main')); ReactDOM.render(<Router/>, document.getElementById('main'));
return Promise.resolve();
};
function waitFor(n){
return new Promise((done) => {
window.setTimeout(() => {
window.requestAnimationFrame(() => done());
}, n);
});
}
function removeLoaderWithAnimation(){
if(!$loader) return Promise.resolve();
if(!$loader.animate){
$loader.remove();
return Promise.resolve();
}
const moveTheGuy = () => {
return new Promise((done) => {
$loader_guy.animate([
{ left: "40%", opacity: 1 },
{ left: "110%", opacity: 0.5 }
], {
easing: "ease-out",
duration: 1000,
iterations: 1,
}).onfinish = () => {
done();
};
});
};
const FadeParticules = () => {
return new Promise((done) => {
$loader_particules.animate([
{ opacity: 1 },
{ opacity: 0 }
], {
duration: 500,
iterations: 1,
}).onfinish = () => {
$loader_particules.remove();
done();
};
});
};
return Promise.all([moveTheGuy(), FadeParticules()]).then(() => {
$loader.remove();
});
}
function removeLoader(){
if($loader) $loader.remove();
return Promise.resolve();
}
Config.refresh().then(() => {
const timeSinceBoot = new Date() - window.initTime;
if(timeSinceBoot >= 2000){
const timeoutToAvoidFlickering = timeSinceBoot > 2500 ? 0 : 500;
return waitFor(timeoutToAvoidFlickering)
.then(removeLoaderWithAnimation)
.then(render);
}
return removeLoader().then(render);
}); });
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {