渡一教育:笑脸动画
效果预览
此演示仅在桌面端浏览器中可用
html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>wanglei.live</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<p>你对我们的印象是</p>
<div class="face">
<div class="eye left animate"></div>
<div class="eye right animate"></div>
<div class="mouse animate"></div>
</div>
<input type="range" min="0" max="1" step="0.1" class="range" />
</div>
<script src="./index.js"></script>
</body>
</html>js
js
const inp = document.querySelector("input");
const container = document.querySelector(".container");
function cal() {
container.style.setProperty("--progress", inp.value);
}
inp.oninput = cal;
cal();css
css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
align-items: center;
flex-direction: column;
}
.container {
--progress: 0.5;
margin: 50px auto;
display: flex;
align-items: center;
flex-direction: column;
row-gap: 20px;
font-size: 20px;
--hue1: calc(120 * var(--progress));
--hue2: calc(330 + var(--hue1));
--color1: hsl(var(--hue1), 90%, 55%);
--color2: hsl(var(--hue2), 90%, 45%);
}
.animate {
animation-duration: 0.5s;
animation-delay: calc(var(--progress) * -1s);
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-play-state: paused;
}
.range {
background-color: #e3e4e8;
background-image: linear-gradient(to right, var(--color1), var(--color2));
background-size: calc(100% * var(--progress)) 100%;
background-repeat: no-repeat;
border-radius: 0.25em;
display: block;
width: 100%;
height: 0.5em;
appearance: none; /* 清除默认样式 */
}
/* 拖动按钮 */
.range::-webkit-slider-thumb {
background-color: #fff;
border: 0;
border-radius: 50%;
box-shadow: 0 0.125em 0.5em hsl(0, 0%, 0%, 0.5);
width: 1.5em;
height: 1.5em;
transition: background-color 0.15s linear;
--webkit-appearance: none;
appearance: none;
}
.range:focus::-webkit-slider-thumb,
.range:-webkit-slider-thumb:hover {
background-color: #efefef;
}
.face {
width: 80px;
height: 80px;
/* 135deg表示从左上到右下的渐变 */
background-image: linear-gradient(135deg, var(--color1), var(--color2));
border-radius: 50%;
margin-bottom: 30px;
position: relative;
}
.eye {
position: absolute;
width: 20%;
height: 20%;
background: #fff;
top: 30%;
left: 50%;
border-radius: 50%;
margin-left: -10%;
}
.eye.left {
transform: translateX(-90%);
animation-name: leftEyeChange;
}
.eye.right {
transform: translateX(90%);
animation-name: rightEyeChange;
}
@keyframes leftEyeChange {
0% {
clip-path: polygon(0 75%, 100% 0, 100% 100%, 0 100%);
}
50%,
100% {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
}
@keyframes rightEyeChange {
0% {
clip-path: polygon(0 0, 100% 70%, 100% 100%, 0 100%);
}
50%,
100% {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
}
.mouse {
position: absolute;
--w: 32px;
--h: 32px;
width: var(--w);
height: var(--h);
top: 66px;
left: 30%;
border-radius: var(--w);
box-shadow: inset 0 2px 0 #fff;
animation-name: mouseChange;
transform: translateY(calc(var(--h) / -2));
}
@keyframes mouseChange {
50% {
height: 4px;
box-shadow: inset 0 4px 0 #fff;
transform: translateY(calc(var(--h) / -3));
clip-path: inset(0% 0% 0% 0%);
}
50.1% {
height: 4px;
box-shadow: inset 0 -4px 0 #fff;
transform: translateY(calc(var(--h) / -3));
clip-path: inset(50% 0% 0% 0%);
}
to {
height: var(--h);
box-shadow: inset 0 -50px 0 #fff;
transform: translateY(calc(var(--h) / -1));
clip-path: inset(50% 0% 0% 0%);
}
}