Skip to content

Instantly share code, notes, and snippets.

@iAMNABHON
Created August 23, 2021 21:39
Show Gist options
  • Select an option

  • Save iAMNABHON/3d934a151fd1d7c5189894c5f8f1e75f to your computer and use it in GitHub Desktop.

Select an option

Save iAMNABHON/3d934a151fd1d7c5189894c5f8f1e75f to your computer and use it in GitHub Desktop.
Manual loader
<!-- Inspired by Zach Leatherman's tweet -->
<!-- https://twitter.com/zachleat/status/1427308678949089287 -->
<div class="loader">
<div class="loader_text"></div>
<div class="loader_wheel">
<div class="loader_arrows"></div>
</div>
<div class="loader_bar"></div>
</div>
<div class="postLoader hide">
<div class="postLoader_text">LOADED</div>
<button class="postLoader_btn" onclick="resetLoader();">Reload</button>
</div>
const loader = document.querySelector('.loader');
const postLoader = document.querySelector('.postLoader');
const text = document.querySelector('.loader_text');
loader.addEventListener('mousedown', loaderMouseStart);
loader.addEventListener('mousemove', loaderMouseMove);
loader.addEventListener('mouseup', loaderMouseEnd);
loader.addEventListener('mouseleave', loaderMouseEnd);
let loaderState, loaderAngle, loaderWidth, LoaderWheelStartAngle, loaderMouseStartAngle;
resetLoader();
function resetLoader() {
loaderState = 'Idle';
loaderAngle = 0;
loaderWidth = 0;
loader.classList.remove('hide');
postLoader.classList.add('hide');
setCssProperties(0, 0);
setLoaderText();
}
function loaderMouseStart(e) {
if (loaderState === 'On') {
return false;
}
LoaderWheelStartAngle = loaderAngle;
loaderMouseStartAngle = getAngle(e);
loaderState = 'On';
}
function loaderMouseMove(e) {
if (loaderState !== 'On') {
return false;
}
const lastAngle = loaderAngle;
const thisMouseAngle = getAngle(e);
loaderAngle = LoaderWheelStartAngle + (thisMouseAngle - loaderMouseStartAngle);
const wChange = Math.min(5, Math.max(-5, (loaderAngle + 360) - (lastAngle + 360)));
loaderWidth = Math.min(100, Math.max(0, loaderWidth + wChange * 0.025));
if (loaderWidth >= 100) {
loaded();
} else {
setCssProperties(loaderAngle, loaderWidth);
setLoaderText(loaderWidth);
}
}
function loaderMouseEnd(e) {
loaderState = 'Idle';
}
function loaded() {
loader.classList.add('hide');
postLoader.classList.remove('hide');
}
function getAngle(e) {
return Math.atan2((e.y - (window.innerHeight / 2)), (e.x - (window.innerWidth / 2))) * 180 / Math.PI;
}
function setLoaderText(w=0) {
switch (true) {
case w > 80:
text.innerHTML = 'Almost there...';
break;
case w > 60:
text.innerHTML = 'Keep going...';
break;
case w > 40:
text.innerHTML = `You're doing good...`;
break;
case w > 20:
text.innerHTML = `That's it...`;
break;
case w > 0:
text.innerHTML = 'loading...';
break;
default:
text.innerHTML = 'Crank the wheel<br>to start loading';
break;
}
}
function setCssProperties(a, w) {
loader.style.setProperty('--loaderWheelAngle', `${a}deg`);
loader.style.setProperty('--loaderBarWidth', `${w}%`);
}
<script src="https://assets.codepen.io/1948355/twitterButton-2.1.0.js"></script>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&display=swap');
*, *::before, *::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
font-family: 'Open Sans', sans-serif;
background-color: #111;
color: #fff;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.hide { display: none; }
.loader {
position: relative;
width: 320px; height: 320px;
text-align: center;
font-size: 24px;
user-select: none;
--loaderBarWidth: 0;
--loaderWheelAngle: 0;
&_text {
position: absolute;
bottom: 220px; left: 0;
width: 320px;
}
&_wheel {
position: absolute;
top: 110px; left: 110px;
border-radius: 50%;
background-image: repeating-conic-gradient(#111, #444, #111 30deg);
border: 3px solid;
transform: rotate(var(--loaderWheelAngle));
}
&_arrows {
position: relative;
width: 100px; height: 100px;
background-color: #000;
border-radius: 50%;
mix-blend-mode: lighten;
&::before, &::after {
content: '';
position: absolute;
top: 0; left: 0;
width: 50%; height: 100%;
background-image:
conic-gradient(from 45deg at 35px 77px, #fff 90deg, #fff0 90deg),
radial-gradient(circle at 50px 57px, #000 25px, #0000 26px),
radial-gradient(circle at 50px 43px, #fff 29px, #fff0 30px)
;
}
&::after {
transform: rotate(180deg);
transform-origin: right;
}
}
&_bar {
position: absolute;
top: 240px; left: 0;
width: 320px; height: 40px;
border: 2px solid;
&::after {
content: '';
position: absolute;
top: 0; left: 0;
width: var(--loaderBarWidth, 0); height: 100%;
background-color: #798;
}
}
}
.postLoader {
position: relative;
width: 320px;
text-align: center;
user-select: none;
&_text {
font-size: 24px;
margin-bottom: 0.5em;
}
&_btn {
padding: 0.5em 1em;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment