<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>鱼缸漏水加点水吧</title>
<style>
html {
font-size: 5vh;
}
@media screen and (min-height: 400px) {
html {
font-size: 19px;
}
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #eb80b1;
}
@keyframes swimming {
0%,
100% {
transform: translateX(0);
}
22.5% {
transform: translateX(2.5rem) skewY(-5deg);
}
45% {
transform: translateX(6rem) translateY(-1rem) skewY(5deg);
}
55% {
transform: translateX(5rem) translateY(-0.5rem) scaleX(-1);
}
95% {
transform: translateX(0) scaleX(-1) skewY(10deg);
}
}
@keyframes dead {
0%,
100% {
transform: translateX(2.5rem);
}
22.5% {
transform: translateX(2.5rem) translateY(-1rem) skewY(-5deg);
}
45% {
transform: translateX(2.5rem) skewY(5deg);
}
55% {
transform: translateX(2.5rem) translateY(-1rem) skewY(-5deg);
}
95% {
transform: translateX(2.5rem) skewY(5deg);
}
}
.fishbowl {
position: relative;
width: 15rem;
height: 15rem;
}
.fishbowl__background {
position: relative;
width: 100%;
height: 100%;
border-radius: 50% 50% 40% 40%;
background: linear-gradient(transparent 10%, #fff 150%);
border-bottom: 1px solid #fff;
}
.fishbowl:before {
content: '';
position: absolute;
bottom: 9.5rem;
left: 2rem;
width: 100%;
height: 30%;
border-radius: 50%;
box-shadow: -4rem 10rem 1rem 0 rgba(0, 0, 56, 0.3);
transform: rotate(5deg);
}
.fishbowl:after {
content: '';
position: absolute;
top: 12.5%;
left: 2.5%;
width: 95%;
height: 85%;
border-radius: 40%;
background: linear-gradient(135deg, transparent 50%, #fff 150%);
}
.fishbowl__bottom {
position: absolute;
bottom: 5%;
left: 17.5%;
width: 65%;
height: 20%;
border-radius: 50%;
background: linear-gradient(#f5fccd, #ff7d66 200%);
}
.fishbowl__decoration {
position: absolute;
top: 20%;
left: 5%;
width: 90%;
height: 75%;
}
.fishbowl__seaweed {
position: absolute;
width: 0;
height: 0;
border-left: 0.5rem solid transparent;
border-right: 0.5rem solid transparent;
border-bottom: 5rem solid #80c0a1;
}
.fishbowl__seaweed--1 {
bottom: 15%;
right: 20%;
border-bottom: 5rem solid #80c0a1;
}
.fishbowl__seaweed--2 {
bottom: 10%;
right: 30%;
border-bottom: 8rem solid #80c0a1;
}
.fishbowl__seaweed--3 {
bottom: 15%;
right: 40%;
border-bottom: 6rem solid #80c0a1;
}
.fishbowl__water {
position: absolute;
bottom: 5%;
left: 5%;
width: 90%;
height: 80%;
border-radius: 40% 40% 4.8rem 4.8rem;
transition: height 0.3s ease;
overflow: hidden;
}
.fishbowl__water-color {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: calc(1% * var(--filling, 90));
background: linear-gradient(transparent -50%, #419197 250%);
border-radius: 20% 20% 4rem 4rem;
transition: height 0.5s linear;
}
.fishbowl__water-color:after {
content: '';
position: absolute;
top: 0;
left: 5%;
width: 90%;
height: 3rem;
border-radius: 50%;
background: linear-gradient(transparent 0%, #419197 250%);
box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.5);
}
.fishbowl__top {
position: absolute;
top: 5%;
left: 15%;
width: 70%;
height: 20%;
border-radius: 50%;
box-shadow: 0 2px 2px 3px rgba(255, 255, 255, 0.3);
}
.fishbowl__fish {
position: absolute;
bottom: 25%;
left: 18%;
width: 2rem;
height: 1rem;
border-radius: 50%;
background: linear-gradient(#fff -200%, orange);
box-shadow: 0 2rem 4px -2px rgba(0, 0, 56, 0.3);
transition-property: bottom, transform, box-shadow;
transition-duration: 1s;
transition-timing-function: ease;
animation: swimming;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
}
.fishbowl__fish:after {
content: '';
position: absolute;
top: 15%;
right: 15%;
width: 0.25rem;
height: 0.25rem;
border-radius: 50%;
background: radial-gradient(circle at 0 0, #fff -100%, #12486b);
transition: height 0.5s ease;
}
.fishbowl__fish--dying {
bottom: 10%;
box-shadow: 0 1rem 4px -2px rgba(0, 0, 56, 0.3);
}
.fishbowl__fish--dying .fishbowl__fish-tail {
box-shadow: 0 1rem 4px -2px rgba(0, 0, 56, 0.3);
}
.fishbowl__fish--dead {
animation: dead;
animation-duration: 2s;
animation-iteration-count: 2;
animation-fill-mode: forwards;
box-shadow: none;
}
.fishbowl__fish--dead .fishbowl__fish-tail {
box-shadow: none;
}
.fishbowl__fish--dead:after {
height: 0.125rem;
}
.fishbowl__fish--floating {
bottom: max(calc(var(--filling, 0) * 1% - 15%), 10%);
transform: translateX(2.5rem);
animation: none;
box-shadow: none;
}
.fishbowl__fish--floating:after {
height: 2px;
}
.fishbowl__fish--floating .fishbowl__fish-tail {
box-shadow: none;
}
.fishbowl__fish-tail {
position: absolute;
top: 0;
left: -0.75rem;
width: 0;
height: 0;
border-top: 0.5rem solid transparent;
border-bottom: 0.5rem solid transparent;
border-left: 0.94rem solid orange;
box-shadow: 0 2rem 4px -2px rgba(0, 0, 56, 0.3);
transition: box-shadow 1s ease;
}
.fishbowl__pool {
position: absolute;
right: 0;
bottom: -5%;
width: 50%;
height: 15%;
border-radius: 50%;
background: linear-gradient(#fff -100%, #419197);
opacity: 0.5;
}
.fishbowl__pool:after {
content: '';
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
border-right: 2px solid #fff;
border-radius: 50%;
animation: wave;
animation-duration: 3s;
animation-iteration-count: infinite;
opacity: 0.5;
}
@keyframes wave {
from {
top: 25%;
left: 25%;
width: 50%;
height: 50%;
}
to {
top: 10%;
left: 10%;
width: 80%;
height: 80%;
}
}
.fishbowl__tap {
position: absolute;
bottom: 0;
left: -3rem;
width: 12rem;
height: 15.9rem;
cursor: pointer;
}
.fishbowl__tap--active .fishbowl__tap-stream {
animation: stream;
animation-duration: 0.5s;
}
@keyframes stream {
0% {
height: 0;
}
50% {
top: 2rem;
height: calc(14rem - var(--filling) * 0.1rem);
}
100% {
top: calc(2rem + 14rem - var(--filling) * 0.1rem);
height: 0;
}
}
.fishbowl__tap--active .fishbowl__tap-handle {
animation: handle;
animation-duration: 0.5s;
}
@keyframes handle {
from {
transform: rotate(45deg);
}
to {
transform: rotate(405deg);
}
}
.fishbowl__tap-base {
position: absolute;
bottom: 0;
left: 0;
width: 2rem;
height: 14rem;
border-radius: 0 0 1.2rem 1.2rem;
box-shadow: inset -1px -1px 0 0px rgba(255, 255, 255, 0.5);
background: linear-gradient(#919ea3, #66777f 150%);
}
.fishbowl__tap-base:before {
content: '';
position: absolute;
z-index: -1;
bottom: 4rem;
right: 15rem;
width: 100%;
height: 100%;
border-radius: 1rem 1rem 0 0;
box-shadow: -4rem 10rem 1rem 0 rgba(0, 0, 56, 0.3);
transform: rotate(-70deg);
}
.fishbowl__tap-base:after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.4) 60%,
transparent 200%
);
border-radius: 0 0 1.2rem 1.2rem;
}
.fishbowl__tap-handle {
position: absolute;
left: -1rem;
bottom: 6rem;
width: 2rem;
height: 2rem;
border-radius: 0.2rem;
border-top: 1px solid #fff;
border-right: 1px solid rgba(255, 255, 255, 0.5);
background: radial-gradient(circle at 0 0, #fff -100%, #919ea3);
transform: rotate(45deg);
}
.fishbowl__tap-handle:after {
content: '';
position: absolute;
top: 0.5rem;
left: 0.5rem;
width: 1rem;
height: 1rem;
border-radius: 50%;
background: radial-gradient(circle at 0 0, #fff -200%, #419197);
}
.fishbowl__tap-stream {
position: absolute;
top: 2rem;
left: 6.25rem;
width: 1.5rem;
height: 0;
background: linear-gradient(#fff -100%, #419197);
border-radius: 1rem;
opacity: 0.3;
}
.fishbowl__tap-head {
position: absolute;
top: 0;
left: 0;
width: 4rem;
height: 0rem;
border-radius: 50% 50% 0 0;
border-top: 2rem solid #919ea3;
border-left: 2rem solid #919ea3;
border-right: 2rem solid #919ea3;
box-shadow: 1px -1px 0 0 #fff;
}
.fishbowl__tap-head:before {
content: '';
position: absolute;
z-index: -1;
bottom: 3rem;
right: 23rem;
width: 150%;
height: 200%;
box-shadow: -4rem 10rem 1rem 1rem rgba(0, 0, 56, 0.3);
transform: rotate(2deg) skewX(60deg);
}
.fishbowl__tap-head:after {
content: '';
position: absolute;
top: -2rem;
left: -2rem;
width: 8rem;
height: 2rem;
background: linear-gradient(
transparent,
rgba(255, 255, 255, 0.4) 60%,
transparent 200%
);
border-radius: 50% 50% 0 50%;
}
.fishbowl__tap-end {
position: absolute;
left: 6rem;
top: 1.5rem;
width: 2rem;
height: 1rem;
border-radius: 50%;
background: linear-gradient(#fff -70%, #919ea3);
}
.fishbowl__tap-text {
position: absolute;
top: 4rem;
left: -6rem;
color: #fff;
font-family: 'Arial', sans-serif;
font-size: 0.875rem;
}
.fishbowl__tap-text:after {
content: '';
position: absolute;
bottom: -1rem;
right: -1rem;
width: 2rem;
height: 1px;
background-color: #fff;
transform: rotate(45deg);
}
@media screen and (max-width: 420px) {
.fishbowl {
left: 13%;
}
.fishbowl__tap-text {
width: 2rem;
top: 1rem;
left: -3.5rem;
}
}
</style>
</head>
<body>
<div id="fishbowl" class="fishbowl">
<div class="fishbowl__pool"></div>
<div class="fishbowl__background"></div>
<div class="fishbowl__bottom"></div>
<div class="fishbowl__decoration">
<div class="fishbowl__seaweed fishbowl__seaweed--1"></div>
<div class="fishbowl__seaweed fishbowl__seaweed--2"></div>
<div class="fishbowl__seaweed fishbowl__seaweed--3"></div>
</div>
<div class="fishbowl__water">
<div id="fish" class="fishbowl__fish">
<div class="fishbowl__fish-tail"></div>
</div>
<div class="fishbowl__water-color"></div>
</div>
<div class="fishbowl__top"></div>
<div id="tap" class="fishbowl__tap">
<div class="fishbowl__tap-base"></div>
<div class="fishbowl__tap-handle"></div>
<div class="fishbowl__tap-stream"></div>
<div class="fishbowl__tap-end"></div>
<div class="fishbowl__tap-head"></div>
<div class="fishbowl__tap-text">加点水吧</div>
</div>
</div>
<script>
let fill = 90;
let intervalId = null;
const fishbowl = document.getElementById('fishbowl');
const fish = document.getElementById('fish');
const tap = document.getElementById('tap');
const emptyingFn = () =>
setInterval(() => {
fill = fill - 1;
fishbowl.style = `--filling:${fill}`;
if (fill <= 0) {
clearInterval(intervalId);
} else if (fill < 20) {
fish.classList.add('fishbowl__fish--dead');
} else if (fill < 50) {
fish.classList.add('fishbowl__fish--dying');
} else {
fish.classList.remove('fishbowl__fish--dying');
fish.classList.remove('fishbowl__fish--dead');
}
}, 200);
intervalId = emptyingFn();
tap.addEventListener('click', () => {
tap.classList.add('fishbowl__tap--active');
setTimeout(() => tap.classList.remove('fishbowl__tap--active'), 500);
if (fill <= 0) {
intervalId = emptyingFn();
fish.classList.add('fishbowl__fish--floating');
}
fill = Math.min(fill + 20, 90);
});
</script>
</body>
</html>