JSFiddle - React, Tailwind, and code Playground
by ABB_2020
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Power switch</title>
</head>
<body>
<a id="myButton">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="90" height="90" viewbox="0 0 540 540">
<defs>
<style type="text/css">
.off {stroke: var(--off);}
.power {
stroke: var(--on);
stroke-dasharray: 1000;
animation: powering 3s linear 0s 1 normal forwards;
}
@keyframes powering {
0% {stroke-dashoffset: 1000;}
100% {stroke-dashoffset: 0;}
}
.blink {
stroke: var(--on);
animation: blinking 2s ease-in-out 0s infinite;
}
@keyframes blinking {
0% {visibility: hidden;}
30% {visibility: hidden;}
100% {visibility: visible;}
}
.on {stroke: var(--on);}
</style>
</defs>
<path fill="none" stroke="var(--off)" stroke-width="78" stroke-linecap="round" d="M400,143 a200,200 0 1,1 -260,0" />
<g>
<path class="off" id="myIcon1" stroke-width="80" stroke-linecap="round" fill="none" d="M400,143 a200,200 0 1,1 -260,0" />
<line class="off" id="myIcon2" stroke-width="80" stroke-linecap="round" x1="270" y1="240" x2="270" y2="45" />
</g>
</svg>
</a>
</body>
</html>
CSS
:root {
--bg: #405480;
--off: #2C303A;
--on: #114B8E;
}
html, body {
background: var(--bg);
color: #f5f5f5;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
a {
display: block;
cursor: pointer;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
padding: 35px 120px;
line-height: 1;
white-space: nowrap;
color: #fff;
border-radius: 12px;
border: 1px solid #00397C;
box-shadow: 0 3px 2px rgba(0, 0, 0, 0.24),
0 9px 4px rgba(22, 21, 21, 0.45),
15px 15px 10px rgba(22, 21, 21, 0.2),
inset 0 -3px 6px rgba(0, 0, 0, 0.3),
inset 0 2px 0 rgba(255, 255, 255, 0.27),
inset 0 4px 6px #405480,
inset 1px 2px 3px 0px rgba(0, 0, 0, 0);
}
a:hover:not(.lock) {
box-shadow: 0 3px 2px rgba(0, 0, 0, 0.24),
0 0 0 rgba(22, 21, 21, 0),
5px 5px 10px rgba(22, 21, 21, 0.2),
inset 0 -3px 6px rgba(0, 0, 0, 0.3),
inset 0 2px 1px rgba(255, 255, 255, 0.2),
inset 0px 4px 6px 0px #405480,
inset 1px 2px 3px 0px rgba(0, 0, 0, 0);
}
a:active:not(.lock) {
box-shadow: 0 1px 1px 0 rgba(255, 255, 255, 0.32),
1px 1px 10px rgba(22, 21, 21, 0.2),
5px 5px 10px rgba(22, 21, 21, 0),
inset 0 3px 6px rgba(0, 0, 0, 0.3),
inset 6px 6px 10px rgba(0, 0, 0, 0.3),
inset 0 -2px 6px rgba(255, 255, 255, 0.1),
inset 1px 2px 3px 0px rgba(0, 0, 0, 0.5);
}
.lock {
cursor: not-allowed;
box-shadow: 0 1px 1px 0 rgba(255, 255, 255, 0.32),
1px 1px 10px rgba(22, 21, 21, 0.2),
5px 5px 10px rgba(22, 21, 21, 0),
inset 0 3px 6px rgba(0, 0, 0, 0.3),
inset 6px 6px 10px rgba(0, 0, 0, 0.3),
inset 0 -2px 6px rgba(255, 255, 255, 0.1),
inset 1px 2px 3px 0px rgba(0, 0, 0, 0.5);
}
JavaScript
/*
L'icone on-off est constituée d'un arc de cercle (symbole 'off' nommé myIcon1) et d'un trait (symbole 'on' nommé myIcon2)
La classe de ces symboles SVG est définie comme suit :
myIcon1 myIcon2 myButton
--------------------------
off off état initial
power off appui sur le bouton
power blink disabled appui sur le bouton de plus de 3 secondes
on on disabled après wake-on-LAN et ping réussi (en test: après 10 secondes)
off off après extinction et ping en échec (en test : 1 minute)
*/
var wolTimeout, pingTimeout, suspendTimeout;
['mousedown', 'touchstart', 'keypress'].forEach(e => {
document.getElementById('myButton').addEventListener(e, ev => {
if((e != 'keypress' || (e == 'keypress' && ev.which == 32)) && document.getElementById('myIcon1').classList.contains('off')) {
document.getElementById('myIcon1').classList.replace('off', 'power');
wolTimeout = setTimeout(function() {
document.getElementById('myIcon2').classList.replace('off', 'blink');
document.getElementById('myButton').classList.add('lock');
}, 3000);
pingTimeout = setTimeout(function() {
document.getElementById('myIcon1').classList.replace('power', 'on');
document.getElementById('myIcon2').classList.replace('blink', 'on');
}, 10000);
suspendTimeout = setTimeout(function() {
document.getElementById('myIcon1').classList.replace('on', 'off');
document.getElementById('myIcon2').classList.replace('on', 'off');
document.getElementById('myButton').classList.remove('lock');
}, 60000);
}
})
});
['mouseup', 'touchend', 'keyup'].forEach(e => {
document.getElementById('myButton').addEventListener(e, ev => {
if((e != 'keyup' || (e == 'keyup' && ev.which == 32)) && document.getElementById('myIcon1').classList.contains('power') && document.getElementById('myIcon2').classList.contains('off'))...