发现一个比较有意思的前端
开灯!关灯!
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8" />
<title>开灯!关灯!</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<style>
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--bg: hsl(var(--hue), 10%, 10%);
--fg: hsl(var(--hue), 10%, 90%);
--primary: hsl(var(--hue), 90%, 50%);
--primary2: hsl(var(--hue), 90%, 70%);
--primary2-t: hsla(var(--hue), 90%, 70%, 0);
--border: hsl(var(--hue), 10%, 30%);
--border-hover: hsl(var(--hue), 10%, 50%);
--trans-dur: 0.3s;
--trans-timing: cubic-bezier(0.65, 0, 0.35, 1);
font-size: calc(14px + (70 - 14) * (100vw - 280px) / (3840 - 280));
}
body,
button {
color: var(--fg);
font: 1em/1.5 sans-serif;
transition: background-color calc(var(--trans-dur) * 0.5) steps(1, end),
box-shadow var(--trans-dur) var(--trans-timing),
color calc(var(--trans-dur) * 0.5) steps(1, end);
}
body {
background-color: var(--bg);
display: flex;
height: 100vh;
}
.plugs {
background-color: transparent;
border-radius: 0.375em;
box-shadow: 0 0 0 0.0625em var(--border), 0 0 0 0.25em var(--primary2-t);
cursor: pointer;
display: block;
margin: auto;
outline: transparent;
position: relative;
-webkit-appearance: none;
appearance: none;
-webkit-tap-highlight-color: transparent;
}
.plugs:hover {
box-shadow: 0 0 0 0.0625em var(--border-hover), 0 0 0 0.25em var(--primary2-t);
}
.plugs:focus-visible {
box-shadow: 0 0 0 0.0625em var(--primary), 0 0 0 0.25em var(--primary2);
}
.plugs__img {
display: block;
position: relative;
top: 0;
left: 0;
width: 16em;
height: auto;
}
.plugs__img-left,
.plugs__img-left-seg,
.plugs__img-left-head,
.plugs__img-right,
.plugs__img-right-seg,
.plugs__img-right-head,
.plugs__img-prong,
.plugs__img-spark-1-x,
.plugs__img-spark-1-y,
.plugs__img-spark-2-x,
.plugs__img-spark-2-y,
.plugs__img-spark-3-x,
.plugs__img-spark-3-y {
animation-duration: calc(var(--trans-dur) * 3);
animation-timing-function: var(--trans-timing);
}
.plugs__img-left-head,
.plugs__img-right-head {
transform-origin: 2px 0;
}
.plugs__img-left {
transform: translate(13px, 10px) rotate(0);
}
.plugs__img-right {
transform: translate(57px, 10px) rotate(0);
}
.plugs__img-prong {
stroke-dashoffset: 0;
}
.plugs__img-spark-1-x,
.plugs__img-spark-2-x,
.plugs__img-spark-3-x {
animation-timing-function: linear;
}
.plugs__img-spark-1-y,
.plugs__img-spark-2-y,
.plugs__img-spark-3-y {
animation-timing-function: cubic-bezier(0.35, 1, 0.65, 1);
}
.plugs[aria-pressed='false'] .plugs__img-left {
animation-name: left-swing-tail-off;
}
.plugs[aria-pressed='false'] .plugs__img-left-seg {
animation-name: left-swing-seg-off;
}
.plugs[aria-pressed='false'] .plugs__img-left-seg--flip {
animation-name: left-swing-seg-off-2;
}
.plugs[aria-pressed='false'] .plugs__img-left-head {
animation-name: left-swing-head-off;
}
.plugs[aria-pressed='false'] .plugs__img-right {
animation-name: right-swing-tail-off;
}
.plugs[aria-pressed='false'] .plugs__img-right-seg {
animation-name: right-swing-seg-off;
}
.plugs[aria-pressed='false'] .plugs__img-right-seg--flip {
animation-name: right-swing-seg-off-2;
}
.plugs[aria-pressed='false'] .plugs__img-right-head {
animation-name: right-swing-head-off;
}
.plugs[aria-pressed='false'] .plugs__img-prong {
animation-name: prongs-off;
animation-timing-function: cubic-bezier(0.35, 0, 0.65, 0);
}
.plugs[aria-pressed='false'] .plugs__img-spark-1-x {
animation-name: spark-1-x;
}
.plugs[aria-pressed='false'] .plugs__img-spark-1-y {
animation-name: spark-1-y;
}
.plugs[aria-pressed='false'] .plugs__img-spark-2-x {
animation-name: spark-2-x;
}
.plugs[aria-pressed='false'] .plugs__img-spark-2-y {
animation-name: spark-2-y;
}
.plugs[aria-pressed='false'] .plugs__img-spark-3-x {
animation-name: spark-3-x;
}
.plugs[aria-pressed='false'] .plugs__img-spark-3-y {
animation-name: spark-3-y;
}
.plugs[aria-pressed='true'] .plugs__img-left {
animation-name: left-swing-tail-on;
transform: translate(13px, 10px) rotate(-90deg);
}
.plugs[aria-pressed='true'] .plugs__img-left-seg {
animation-name: left-swing-seg-on;
}
.plugs[aria-pressed='true'] .plugs__img-left-seg--flip {
animation-name: right-swing-seg-on;
}
.plugs[aria-pressed='true'] .plugs__img-left-head {
animation-name: left-swing-head-on;
}
.plugs[aria-pressed='true'] .plugs__img-right {
animation-name: right-swing-tail-on;
transform: translate(57px, 10px) rotate(90deg);
}
.plugs[aria-pressed='true'] .plugs__img-right-seg {
animation-name: right-swing-seg-on;
}
.plugs[aria-pressed='true'] .plugs__img-right-seg--flip {
animation-name: left-swing-seg-on;
}
.plugs[aria-pressed='true'] .plugs__img-right-head {
animation-name: right-swing-head-on;
}
.plugs[aria-pressed='true'] .plugs__img-prong {
animation-name: prongs-on;
animation-timing-function: cubic-bezier(0.35, 1, 0.65, 1);
stroke-dashoffset: 2;
}
.plugs__label {
overflow: hidden;
position: absolute;
width: 0;
height: 0;
}
/* Dark theme */
[data-dark='false'] {
--bg: hsl(var(--hue), 10%, 90%);
--fg: hsl(var(--hue), 10%, 10%);
--border: hsl(var(--hue), 10%, 70%);
}
[data-dark='false'] body,
[data-dark='false'] button {
transition-duration: calc(var(--trans-dur) * 2.25), var(--trans-dur),
calc(var(--trans-dur) * 2.25);
}
/* Animations */
@keyframes prongs-off {
from {
stroke-dashoffset: 2;
}
17.5%,
to {
stroke-dashoffset: 0;
}
}
@keyframes left-swing-tail-off {
from {
transform: translate(13px, 10px) rotate(-90deg);
}
25% {
transform: translate(13px, 10px) rotate(-32deg);
}
50% {
transform: translate(13px, 10px) rotate(2deg);
}
75% {
transform: translate(13px, 10px) rotate(-1deg);
}
to {
transform: translate(13px, 10px) rotate(0);
}
}
@keyframes left-swing-seg-off {
from {
transform: translate(0, 1px) rotate(0);
}
25% {
transform: translate(0, 1px) rotate(-10deg);
}
50% {
transform: translate(0, 1px) rotate(2deg);
}
75% {
transform: translate(0, 1px) rotate(-1deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes left-swing-seg-off-2 {
from {
transform: translate(0, 1px) rotate(0);
}
25% {
transform: translate(0, 1px) rotate(10deg);
}
50% {
transform: translate(0, 1px) rotate(2deg);
}
75% {
transform: translate(0, 1px) rotate(-1deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes left-swing-head-off {
from {
transform: translate(-2.5px, 1px) rotate(0);
}
25% {
transform: translate(-2.5px, 1px) rotate(-10deg);
}
50% {
transform: translate(-2.5px, 1px) rotate(2deg);
}
75% {
transform: translate(-2.5px, 1px) rotate(-1deg);
}
to {
transform: translate(-2.5px, 1px) rotate(0);
}
}
@keyframes right-swing-tail-off {
from {
transform: translate(57px, 10px) rotate(90deg);
}
25% {
transform: translate(57px, 10px) rotate(32deg);
}
50% {
transform: translate(57px, 10px) rotate(-2deg);
}
75% {
transform: translate(57px, 10px) rotate(1deg);
}
to {
transform: translate(57px, 10px) rotate(0);
}
}
@keyframes right-swing-seg-off {
from {
transform: translate(0, 1px) rotate(0);
}
25% {
transform: translate(0, 1px) rotate(10deg);
}
50% {
transform: translate(0, 1px) rotate(-2deg);
}
75% {
transform: translate(0, 1px) rotate(1deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes right-swing-seg-off-2 {
from {
transform: translate(0, 1px) rotate(0);
}
25% {
transform: translate(0, 1px) rotate(-10deg);
}
50% {
transform: translate(0, 1px) rotate(-2deg);
}
75% {
transform: translate(0, 1px) rotate(1deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes right-swing-head-off {
from {
transform: translate(-2.5px, 1px) rotate(0);
}
25% {
transform: translate(-2.5px, 1px) rotate(10deg);
}
50% {
transform: translate(-2.5px, 1px) rotate(-2deg);
}
75% {
transform: translate(-2.5px, 1px) rotate(1deg);
}
to {
transform: translate(-2.5px, 1px) rotate(0);
}
}
@keyframes prongs-on {
from,
70% {
stroke-dashoffset: 0;
}
90%,
to {
stroke-dashoffset: 2;
}
}
@keyframes left-swing-tail-on {
from {
transform: translate(13px, 10px) rotate(0);
}
50% {
transform: translate(13px, 10px) rotate(-32deg);
}
to {
transform: translate(13px, 10px) rotate(-90deg);
}
}
@keyframes left-swing-seg-on {
from {
transform: translate(0, 1px) rotate(0);
}
50% {
transform: translate(0, 1px) rotate(-10deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes left-swing-head-on {
from {
transform: translate(-2.5px, 1px) rotate(0);
}
50% {
transform: translate(-2.5px, 1px) rotate(-10deg);
}
to {
transform: translate(-2.5px, 1px) rotate(0);
}
}
@keyframes right-swing-tail-on {
from {
transform: translate(57px, 10px) rotate(0);
}
50% {
transform: translate(57px, 10px) rotate(32deg);
}
to {
transform: translate(57px, 10px) rotate(90deg);
}
}
@keyframes right-swing-seg-on {
from {
transform: translate(0, 1px) rotate(0);
}
50% {
transform: translate(0, 1px) rotate(10deg);
}
to {
transform: translate(0, 1px) rotate(0);
}
}
@keyframes right-swing-head-on {
from {
transform: translate(-2.5px, 1px) rotate(0);
}
50% {
transform: translate(-2.5px, 1px) rotate(10deg);
}
to {
transform: translate(-2.5px, 1px) rotate(0);
}
}
@keyframes spark-1-x {
from,
12.5% {
r: 1px;
transform: translate(0, 0);
}
37.5%,
to {
r: 0;
transform: translate(-10px, 0);
}
}
@keyframes spark-1-y {
from {
animation-timing-function: steps(1, end);
transform: translate(0, 0);
visibility: hidden;
}
12.5% {
animation-timing-function: linear;
transform: translate(0, 0);
visibility: visible;
}
37.5%,
to {
transform: translate(0, -9px);
}
}
@keyframes spark-2-x {
from,
12.5% {
r: 1px;
transform: translate(0, 0);
}
37.5%,
to {
r: 0;
transform: translate(4px, 0);
}
}
@keyframes spark-2-y {
from {
animation-timing-function: steps(1, end);
transform: translate(0, 0);
visibility: hidden;
}
12.5% {
animation-timing-function: linear;
transform: translate(0, 0);
visibility: visible;
}
37.5%,
to {
transform: translate(0, -8px);
}
}
@keyframes spark-3-x {
from,
12.5% {
r: 1px;
transform: translate(0, 0);
}
37.5%,
to {
r: 0;
transform: translate(-1px, 0);
}
}
@keyframes spark-3-y {
from {
animation-timing-function: steps(1, end);
transform: translate(0, 0);
visibility: hidden;
}
12.5% {
animation-timing-function: linear;
transform: translate(0, 0);
visibility: visible;
}
37.5%,
to {
transform: translate(0, 8px);
}
}
</style>
<button class="plugs" type="button">
<svg
class="plugs__img"
viewBox="0 0 70 35"
width="700px"
height="350px"
aria-hidden="true"
>
<g
fill="none"
stroke="currentcolor"
stroke-linecap="round"
stroke-width="1"
>
<g class="plugs__img-left" transform="translate(13,10)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-left-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg plugs__img-left-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg plugs__img-left-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg plugs__img-left-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg plugs__img-left-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-seg plugs__img-left-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-left-head"
transform="translate(-2.5,1)"
>
<rect
rx="1"
ry="1"
x="0"
y="0"
width="5"
height="6"
/>
<polyline
class="plugs__img-prong"
points="1 6,1 8"
stroke-dasharray="2 2"
/>
<polyline
class="plugs__img-prong"
points="4 6,4 8"
stroke-dasharray="2 2"
/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g class="plugs__img-right" transform="translate(57,10)">
<polyline points="0 0,0 1" />
<g class="plugs__img-right-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-right-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-right-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-right-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g class="plugs__img-right-seg" transform="translate(0,1)">
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg plugs__img-right-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg plugs__img-right-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg plugs__img-right-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg plugs__img-right-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-seg plugs__img-right-seg--flip"
transform="translate(0,1)"
>
<polyline points="0 0,0 1" />
<g
class="plugs__img-right-head"
transform="translate(-2.5,1)"
>
<rect
rx="1"
ry="1"
x="0"
y="0"
width="5"
height="6"
/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g fill="currentcolor" transform="translate(35,10)">
<g class="plugs__img-spark-1-y">
<circle class="plugs__img-spark-1-x" r="0" cy="-1" />
</g>
<g class="plugs__img-spark-2-y">
<circle class="plugs__img-spark-2-x" r="0" cy="0" />
</g>
<g class="plugs__img-spark-3-y">
<circle class="plugs__img-spark-3-x" r="0" cy="1" />
</g>
</g>
</svg>
<span class="plugs__label">Power</span>
</button>
<script>
'use strict';
window.addEventListener('DOMContentLoaded', () => {
const plugs = new Plugs('button');
});
class Plugs {
constructor(buttonEl) {
var _a;
this.button = document.querySelector(buttonEl);
(_a = this.button) === null || _a === void 0
? void 0
: _a.addEventListener('click', this.toggleTheme.bind(this));
}
toggleTheme() {
var _a, _b;
const pressed =
((_a = this.button) === null || _a === void 0
? void 0
: _a.getAttribute('aria-pressed')) === 'true';
(_b = this.button) === null || _b === void 0
? void 0
: _b.setAttribute('aria-pressed', `${!pressed}`);
document.documentElement.setAttribute('data-dark', `${pressed}`);
}
}
</script>