Creating "Saw Switch" using HTML
<!DOCtype html>
<html>
<style>
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
font-size: calc(24px + (32 - 24) * (100vw - 320px) / (1280 - 320));
}
body,
input {
font: 1em/1.5 sans-serif;
}
body {
background: #abafba;
height: 100vh;
display: grid;
place-items: center;
}
.saw-switch {
border-radius: 2.5em;
width: 8em;
height: 5em;
}
.saw-switch__inner,
.saw-switch__blade,
.saw-switch__particle {
pointer-events: none;
}
.saw-switch__inner,
.saw-switch__input {
position: relative;
}
.saw-switch__inner {
display: block;
margin: 1em;
width: calc(100% - 2em);
height: calc(100% - 2em);
-webkit-tap-highlight-color: transparent;
}
.saw-switch__input {
background-color: #f42f25;
border-radius: 1.5em;
box-shadow: 0 0 0 0.2em inset;
color: #e3e4e8;
width: 100%;
height: 100%;
transition: background-color 0.25s ease-in-out;
-webkit-appearance: none;
appearance: none;
}
.saw-switch__input:before {
border-radius: 50%;
content: "";
display: block;
top: 0.5em;
left: 0.5em;
width: 2em;
height: 2em;
transition: transform 0.25s ease-in-out;
}
.saw-switch__input:checked {
background-color: #0bda16;
}
.saw-switch__input:checked:before {
transform: translateX(3em);
}
.saw-switch__input:before,
.saw-switch__blade {
background-color: #e3e4e8;
position: absolute;
}
.saw-switch__blade {
animation: revolve 99999s linear infinite;
clip-path: polygon(50% 0, 100% 100%, 0 100%);
bottom: 50%;
left: 1em;
width: 1em;
height: 1em;
transform: translate(0em, -1.4em) rotate(0deg);
transform-origin: 50% 2.4em;
}
.saw-switch__input:checked~.saw-switch__blade {
animation-duration: 1.2s;
}
.saw-switch__input~.saw-switch__blade:nth-child(3) {
animation-delay: -7142.7857142857s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(3) {
animation-delay: -0.0857142857s;
}
.saw-switch__input~.saw-switch__blade:nth-child(4) {
animation-delay: -14285.5714285714s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(4) {
animation-delay: -0.1714285714s;
}
.saw-switch__input~.saw-switch__blade:nth-child(5) {
animation-delay: -21428.3571428571s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(5) {
animation-delay: -0.2571428571s;
}
.saw-switch__input~.saw-switch__blade:nth-child(6) {
animation-delay: -28571.1428571429s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(6) {
animation-delay: -0.3428571429s;
}
.saw-switch__input~.saw-switch__blade:nth-child(7) {
animation-delay: -35713.9285714286s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(7) {
animation-delay: -0.4285714286s;
}
.saw-switch__input~.saw-switch__blade:nth-child(8) {
animation-delay: -42856.7142857143s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(8) {
animation-delay: -0.5142857143s;
}
.saw-switch__input~.saw-switch__blade:nth-child(9) {
animation-delay: -49999.5s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(9) {
animation-delay: -0.6s;
}
.saw-switch__input~.saw-switch__blade:nth-child(10) {
animation-delay: -57142.2857142857s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(10) {
animation-delay: -0.6857142857s;
}
.saw-switch__input~.saw-switch__blade:nth-child(11) {
animation-delay: -64285.0714285714s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(11) {
animation-delay: -0.7714285714s;
}
.saw-switch__input~.saw-switch__blade:nth-child(12) {
animation-delay: -71427.8571428571s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(12) {
animation-delay: -0.8571428571s;
}
.saw-switch__input~.saw-switch__blade:nth-child(13) {
animation-delay: -78570.6428571429s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(13) {
animation-delay: -0.9428571429s;
}
.saw-switch__input~.saw-switch__blade:nth-child(14) {
animation-delay: -85713.4285714286s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(14) {
animation-delay: -1.0285714286s;
}
.saw-switch__input~.saw-switch__blade:nth-child(15) {
animation-delay: -92856.2142857143s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(15) {
animation-delay: -1.1142857143s;
}
.saw-switch__input~.saw-switch__blade:nth-child(16) {
animation-delay: -99999s;
}
.saw-switch__input:checked~.saw-switch__blade:nth-child(16) {
animation-delay: -1.2s;
}
.saw-switch__particle {
background-color: #c2130a;
border-radius: 50%;
display: block;
opacity: 0;
position: fixed;
top: -0.25em;
left: -0.25em;
width: 0.5em;
height: 0.5em;
z-index: 1;
}
.saw-switch__sr {
clip: rect(1px, 1px, 1px, 1px);
overflow: hidden;
position: absolute;
width: 1px;
height: 1px;
}
/* Animations */
@keyframes revolve {
from {
transform: translate(0, -1.4em) rotate(0);
}
30% {
transform: translate(0, -1.4em) rotate(-0.5turn);
}
50% {
transform: translate(3em, -1.4em) rotate(-0.5turn);
}
80% {
transform: translate(3em, -1.4em) rotate(-1turn);
}
to {
transform: translate(0, -1.4em) rotate(-1turn);
}
}
</style>
<body>
<label class="saw-switch">
<span class="saw-switch__inner">
<input class="saw-switch__input" type="checkbox" value="on">
<span class="saw-switch__sr">Saw Switch</span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
<span class="saw-switch__blade"></span>
</span>
</label>
<script>
window.addEventListener("DOMContentLoaded", () =>
{
const sawSwitch = new SawSwitch(".saw-switch");
});
class SawSwitch
{
constructor(el)
{
this.el = document.querySelector(el);
this.input = this.el.querySelector(".saw-switch__input");
this.touching = false;
this.cursor = {
x: 0,
y: 0
};
this.isMobile = "ontouchstart" in document.documentElement;
if (this.el)
{
this.el.addEventListener(this.isMobile ? "touchmove" : "mousemove", this.updateCursor.bind(this));
this.el.addEventListener(this.isMobile ? "touchend" : "mouseout", this.stopBlood.bind(this));
}
}
updateCursor(e)
{
const event = this.isMobile ? e.touches[0] : e;
// coords
this.cursor.x = event.pageX;
this.cursor.y = event.pageY;
const
{
x,
y
} = this.cursor;
// bounds of the switch
const bounds = this.el.getBoundingClientRect();
const
{
top,
left,
width,
height
} = bounds;
// collision
const outsideX = x < left || x > left + width;
const outsideY = y < top || y > top + height;
const outsideSwitch = outsideX || outsideY;
const withinX = x >= left + width * (1 / 8) && x <= left + width * (7 / 8);
const withinY = y >= top + height * (1 / 5) && y <= top + height * (4 / 5);
const withinBlades = withinX && withinY;
if (this.input.checked && !outsideSwitch && !withinBlades)
{
if (!this.touching)
{
this.touching = true;
this.drawBlood();
}
}
else
{
this.touching = false;
}
}
drawBlood()
{
if (this.touching && this.input.checked)
{
this.createParticle(this.cursor.x, this.cursor.y);
requestAnimationFrame(this.drawBlood.bind(this));
}
}
stopBlood()
{
this.touching = false;
}
randomInt(min, max)
{
return Math.round(Math.random() * (max - min)) + min;
}
createParticle(x, y)
{
const particle = document.createElement("span");
particle.className = "saw-switch__particle";
this.el.appendChild(particle);
const size = this.randomInt(1, 6) * 0.1;
const maxD = 5;
particle.style.width = `${size}em`;
particle.style.height = `${size}em`;
const dx = +((Math.random() - 0.5) * maxD).toFixed(2);
const dy = +((Math.random() - 0.5) * maxD).toFixed(2);
const anim = particle.animate(
[
{
transform: `translate(${x}px,${y}px) scale(1)`,
opacity: 1
},
{
transform: `translate(calc(${x}px + ${dx}em),calc(${y}px + ${dy}em)) scale(0)`,
opacity: 1
}],
{
duration: this.randomInt(250, 300),
easing: "ease-out",
delay: this.randomInt(0, 50)
}
);
anim.onfinish = () =>
{
particle.remove();
};
}
}
</script>
</body>
<h1>
<span>MADE BY DEVANSH MISHRA</span>
</h1>
</html>
Comments
Post a Comment