前些天发现了一个人工智能学习网站,通俗易懂,风趣幽默,最重要的屌图甚多,忍不住分享一下给大家。点击跳转到网站。
我们先看一下展示:
代码展示:
<form action="">
<div class="form-group">
<label for="password">Password</label>
<input id="password" type="password" required />
<button type="button" title="Reveal Password" aria-pressed="false">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="eye-open">
<path d="M1 12C1 12 5 4 12 4C19 4 23 12 23 12V20H12H1V12Z" fill="#D9D9D9" stroke="black" stroke-width="1.5" stroke-linejoin="round" />
</mask>
<mask id="eye-closed">
<path d="M1 12C1 12 5 20 12 20C19 20 23 12 23 12V20H12H1V12Z" fill="#D9D9D9" />
</mask>
</defs>
<path class="lid lid--upper" d="M1 12C1 12 5 4 12 4C19 4 23 12 23 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path class="lid lid--lower" d="M1 12C1 12 5 20 12 20C19 20 23 12 23 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<g mask="url(#eye-open)">
<g class="eye">
<circle cy="12" cx="12" r="4" fill="currentColor" />
<circle cy="11" cx="13" r="1" fill="black" />
</g>
</g>
</svg>
<span class="sr-only">Reveal</span>
</button>
</div>
</form>
@font-face {
font-family: "Geist Mono";
src: url("https://assets.codepen.io/605876/GeistMonoVariableVF.ttf") format("truetype");
}
:root {
--grid-offset: calc(50% + 80px);
--color: hsl(0 0% 6%);
--bg: hsl(0 0% 96%);
--color-alpha: hsl(0 0% 60%);
--selection: hsl(0 0% 80%);
--bg-size: 180px;
--grid-line: hsl(0 0% 80%);
--input-bg: hsl(0 0% 100% / 0.2);
--grid-accent: hsl(280 0% 10% / 0.1);
--glint: white;
--button-shade: 80%;
}
:root:focus-within {
--grid-accent: hsl(280 0% 10% / 0.35);
}
@media(prefers-color-scheme: dark) {
:root {
--button-shade: 30%;
--glint: black;
--grid-accent: hsl(280 0% 80% / 0.1);
--selection: hsl(0 0% 20%);
--color: hsl(0 0% 98%);
--bg: hsl(0 0% 6%);
--color-alpha: hsl(0 0% 50%);
--grid-line: hsl(0 0% 12%);
--input-bg: hsl(0 0% 0% / 0.2);
}
:root:focus-within {
--grid-accent: hsl(280 0% 80% / 0.35);
}
}
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
font-family: 'Geist Mono', sans-serif, system-ui;
color: var(--color);
background: var(--bg);
/* background: black;*/
}
body::before {
content: "";
transition: background 0.2s;
background:
/* How to create one square */
linear-gradient(var(--grid-accent) 0 2px, transparent 2px calc(100% - 2px), var(--grid-accent) calc(100% - 2px)) calc((var(--grid-offset) - (var(--bg-size) * 2)) - 1px) calc((var(--grid-offset) - var(--bg-size)) - 1px) / calc(var(--bg-size) + 2px) calc(var(--bg-size) + 2px) no-repeat,
linear-gradient(90deg, var(--grid-accent) 0 2px, transparent 2px calc(100% - 2px), var(--grid-accent) calc(100% - 2px)) calc((var(--grid-offset) - (var(--bg-size) * 2)) - 1px) calc((var(--grid-offset) - var(--bg-size)) - 1px) / calc(var(--bg-size) + 2px) calc(var(--bg-size) + 2px) no-repeat,
linear-gradient(transparent calc(var(--bg-size) - 2px), var(--grid-line) calc(var(--bg-size) - 2px) var(--bg-size)) var(--grid-offset) var(--grid-offset) / 100% var(--bg-size),
linear-gradient(90deg, transparent calc(var(--bg-size) - 2px), var(--grid-line) calc(var(--bg-size) - 2px) var(--bg-size)) var(--grid-offset) var(--grid-offset) / var(--bg-size) 100%, transparent;
/* background: var(--bg);*/
position: fixed;
inset: 0;
height: 100vh;
width: 100vw;
-webkit-mask: radial-gradient(circle at 0% 0%, hsl(0 0% 100% / 0.5), transparent);
}
.form-group:focus-within label {
color: var(--color);
}
.form-group:focus-within input {
border-color: var(--color);
color: var(--color);
}
.form-group:focus-within button {
color: var(--color);
}
input {
font-family: "Geist Mono", monospace;
font-size: 1.75rem;
padding: 1rem 2rem;
padding-right: 4rem;
letter-spacing: 0.2ch;
border-radius: 6px;
color: var(--color-alpha);
border-color: var(--color-alpha);
border-style: solid;
background: var(--input-bg);
outline: none;
transition: border-color 0.2s, color 0.2s
}
label {
position: absolute;
color: var(--color-alpha);
bottom: calc(100% + 0.5rem);
letter-spacing: 0.2ch;
transition: color 0.2s;
}
.form-group {
position: relative;
}
.eye circle:nth-of-type(2) {
fill: var(--glint);
}
button {
padding: 0;
display: grid;
place-items: center;
height: 100%;
aspect-ratio: 1;
border-radius: 12px;
border: 0;
background: linear-gradient(hsl(0 0% var(--button-shade) / calc(var(--active, 0) * 0.5)), hsl(0 0% var(--button-shade) / calc(var(--active, 0) * 0.5))) padding-box;
border: 6px solid transparent;
transition: background 0.125s;
color: var(--color-alpha);
position: absolute;
right: 0;
z-index: 2;
top: 50%;
cursor: pointer;
translate: 0 -50%;
outline: 0;
}
input::selection {
background: var(--selection);
}
button:is(:focus-visible, :hover) {
--active: 1;
}
button svg {
width: 75%;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
import { gsap } from 'https://cdn.skypack.dev/gsap@3.11.0';
gsap.registerPlugin(ScrambleTextPlugin, MorphSVGPlugin);
const BLINK_SPEED = 0.075;
const TOGGLE_SPEED = 0.125;
const ENCRYPT_SPEED = 1;
let busy = false;
const EYE = document.querySelector('.eye');
const TOGGLE = document.querySelector('button');
const INPUT = document.querySelector('#password');
const PROXY = document.createElement('div');
// 'upperAndLowerCase'
const chars =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~,.<>?/;":][}{+_)(*&^%$#@!±=-§';
let blinkTl;
const BLINK = () => {
const delay = gsap.utils.random(2, 8);
const duration = BLINK_SPEED;
const repeat = Math.random() > 0.5 ? 3 : 1;
blinkTl = gsap.timeline({
delay,
onComplete: () => BLINK(),
repeat,
yoyo: true }).
to('.lid--upper', {
morphSVG: '.lid--lower',
duration }).
to('#eye-open path', {
morphSVG: '#eye-closed path',
duration },
0);
};
BLINK();
const posMapper = gsap.utils.mapRange(-100, 100, 30, -30);
let reset;
const MOVE_EYE = ({ x, y }) => {
if (reset) reset.kill();
reset = gsap.delayedCall(2, () => {
gsap.to('.eye', { xPercent: 0, yPercent: 0, duration: 0.2 });
});
const BOUNDS = EYE.getBoundingClientRect();
// Get distance and angle between two points
gsap.set('.eye', {
xPercent: gsap.utils.clamp(-30, 30, posMapper(BOUNDS.x - x)),
yPercent: gsap.utils.clamp(-30, 30, posMapper(BOUNDS.y - y)) });
};
window.addEventListener('pointermove', MOVE_EYE);
// Trick is to animate from discs and to discs.
TOGGLE.addEventListener('click', () => {
if (busy) return;
const isText = INPUT.matches('[type=password]');
const val = INPUT.value;
busy = true;
// Need to stop the blink here and kill it off.
TOGGLE.setAttribute('aria-pressed', isText);
const duration = TOGGLE_SPEED;
if (isText) {
if (blinkTl) blinkTl.kill();
gsap.timeline({
onComplete: () => {
busy = false;
} })
// Close the eye first and kill the TL
.to('.lid--upper', {
morphSVG: '.lid--lower',
duration }).
to('#eye-open path', {
morphSVG: '#eye-closed path',
duration },
0)
// Decrypt the text input
.to(PROXY, {
duration: ENCRYPT_SPEED,
onStart: () => {
INPUT.type = 'text';
},
onComplete: () => {
PROXY.innerHTML = '';
INPUT.value = val;
},
scrambleText: {
chars,
text:
INPUT.value.charAt(INPUT.value.length - 1) === ' ' ?
`${INPUT.value.slice(0, INPUT.value.length - 1)}${chars.charAt(
Math.floor(Math.random() * chars.length))
}` :
INPUT.value },
onUpdate: () => {
const len = val.length - PROXY.innerText.length;
INPUT.value = `${PROXY.innerText}${new Array(len).fill('?').join('')}`;
} },
0);
} else {
gsap.timeline({
onComplete: () => {
BLINK();
busy = false;
} }).
to('.lid--upper', {
morphSVG: '.lid--upper',
duration }).
to('#eye-open path', {
morphSVG: '#eye-open path',
duration },
0).
to(PROXY, {
duration: ENCRYPT_SPEED,
onComplete: () => {
INPUT.type = 'password';
INPUT.value = val;
PROXY.innerHTML = '';
},
scrambleText: {
chars,
text: new Array(INPUT.value.length).fill('?').join('') },
onUpdate: () => {
INPUT.value = `${PROXY.innerText}${val.slice(
PROXY.innerText.length,
val.length)
}`;
} },
0);
}
});
const FORM = document.querySelector('form');
FORM.addEventListener('submit', event => event.preventDefault());