今天继续分享一个用HTML5和CSS3实现的应用:绘制小水缸,实现动画效果。之前也分享过一些了,大家可以去了解。OK,我们往下走吧,先看下效果图:
一口可爱的小水缸,带着笑脸,冒着泡。首先我们需要绘制图形。
HTML
<label for="toggle">Turn shading off</label>
<input id="toggle" type="checkbox"/>
<div class="cauldron" style="--potion-hue: 176">
<div class="cauldron__opening">
<div class="cauldron__bubble" style="--delay: 6; --scale: 1.27; --speed: 9; --x: 57"></div>
<div class="cauldron__bubble" style="--delay: 5; --scale: 1; --speed: 5; --x: 67"></div>
<div class="cauldron__bubble" style="--delay: 4; --scale: 0.86; --speed: 7; --x: 63"></div>
<div class="cauldron__bubble" style="--delay: 0; --scale: 1.27; --speed: 9; --x: 60"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.5; --speed: 10; --x: 38"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.14; --speed: 5; --x: 66"></div>
<div class="cauldron__bubble" style="--delay: 10; --scale: 0.63; --speed: 9; --x: 74"></div>
<div class="cauldron__bubble" style="--delay: 5; --scale: 0.93; --speed: 5; --x: 61"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.29; --speed: 6; --x: 35"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1; --speed: 5; --x: 27"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.71; --speed: 9; --x: 39"></div>
<div class="cauldron__bubble" style="--delay: 8; --scale: 1.5; --speed: 9; --x: 69"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.34; --speed: 9; --x: 63"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.88; --speed: 9; --x: 34"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.11; --speed: 6; --x: 47"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.56; --speed: 6; --x: 46"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.97; --speed: 9; --x: 39"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.69; --speed: 9; --x: 73"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.12; --speed: 6; --x: 57"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.55; --speed: 5; --x: 55"></div>
<div class="cauldron__bubble" style="--delay: 7; --scale: 0.53; --speed: 5; --x: 72"></div>
<div class="cauldron__bubble" style="--delay: 4; --scale: 1.04; --speed: 8; --x: 59"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.12; --speed: 5; --x: 41"></div>
<div class="cauldron__bubble" style="--delay: 0; --scale: 0.71; --speed: 9; --x: 66"></div>
<div class="cauldron__bubble" style="--delay: 9; --scale: 0.66; --speed: 6; --x: 47"></div>
</div>
<div class="cauldron__handle cauldron__handle--left"></div>
<div class="cauldron__handle cauldron__handle--right"></div>
<div class="cauldron__foot cauldron__foot--left"></div>
<div class="cauldron__foot cauldron__foot--right"></div>
<div class="cauldron__eye cauldron__eye--left"></div>
<div class="cauldron__eye cauldron__eye--right"></div>
<div class="cauldron__mouth"></div>
</div>
我们分为了很多小块。最重要的还是CSS3这块的内容:
* {
box-sizing: border-box;
transition: background 0.15s ease, box-shadow 0.15s ease;
}
:root {
--cauldron-hue: 34;
--potion-hue: 120;
--size: 200;
--bg: #111;
}
label {
font-weight: bold;
color: #fcfcfc;
margin-bottom: 0.5rem;
}
[type='checkbox'] {
margin-bottom: 2rem;
}
:checked ~ .cauldron {
background: var(--cauldron-color);
}
:checked ~ .cauldron .cauldron__opening {
background: var(--potion-color);
box-shadow: none;
}
:checked ~ .cauldron:after,
:checked ~ .cauldron:before {
background: var(--potion-color);
box-shadow: none;
}
:checked ~ .cauldron:before {
background: transparent;
}
:checked ~ .cauldron .cauldron__handle {
background: var(--rim-color);
}
:checked ~ .cauldron .cauldron__eye {
box-shadow: none;
}
:checked ~ .cauldron .cauldron__mouth {
box-shadow: none;
}
:checked ~ .cauldron .cauldron__foot {
background: var(--inner-rim-color);
}
:checked ~ .cauldron .cauldron__bubble {
background: var(--potion-color);
}
body {
align-items: center;
display: flex;
justify-content: center;
min-height: 100vh;
background: var(--bg);
flex-direction: column;
}
.cauldron {
--rim-color: hsl(var(--cauldron-hue), 100%, 60%);
--inner-rim-color: hsl(var(--cauldron-hue), 100%, 25%);
--potion-color: hsl(var(--potion-hue), 100%, 50%);
--cauldron-color: hsl(var(--cauldron-hue), 100%, 50%);
--darkness: hsl(var(--cauldron-hue), 100%, 10%);
--lightness: hsl(var(--cauldron-hue), 100%, 85%);
--potion-stain-light: hsl(var(--potion-hue), 100%, 70%);
--potion-stain-dark: hsl(var(--potion-hue), 100%, 30%);
border-radius: 100%;
height: calc(var(--size) * 1px);
width: calc(var(--size) * 1px);
background: radial-gradient(25% 25% at 25% 55%, var(--rim-color), transparent), radial-gradient(100% 100% at -2% 50%, transparent, transparent 92%, var(--cauldron-color)), radial-gradient(100% 100% at -5% 50%, transparent, transparent 80%, var(--darkness)), linear-gradient(310deg, var(--inner-rim-color) 25%, transparent), var(--cauldron-color);
position: relative;
}
.cauldron__opening {
width: 100%;
position: absolute;
top: 0;
left: 0;
height: 35%;
background: linear-gradient(90deg, transparent, var(--potion-stain-dark)), var(--potion-color);
border: calc(var(--size) * 0.05px) solid var(--rim-color);
box-shadow: 0 0px calc(var(--size) * 0.05px) calc(var(--size) * 0.005px) var(--rim-color) inset, 0 calc(var(--size) * 0.025px) 0 calc(var(--size) * 0.025px) var(--inner-rim-color) inset, 0 10px 20px 0px var(--darkness), 0 10px 20px -10px var(--inner-rim-color);
border-radius: 100%;
}
.cauldron__opening:after {
content: '';
position: absolute;
background: linear-gradient(90deg, transparent, var(--potion-stain-dark), transparent, var(--potion-stain-light), transparent, var(--potion-stain-dark), transparent);
border-radius: 100%;
top: 8px;
right: 0;
bottom: 4px;
left: 0;
}
.cauldron__opening:before {
content: '';
position: absolute;
box-shadow: 0 0 calc(var(--size) * 0.025px) 0 var(--darkness) inset, 0 -1px calc(var(--size) * 0.015px) 0px var(--darkness) inset, 0 2px calc(var(--size) * 0.015px) 0px var(--lightness) inset, 0 0 calc(var(--size) * 0.075px) calc(var(--size) * 0.05px) var(--rim-color) inset;
border-radius: 100%;
top: calc(var(--size) * -0.05px);
right: calc(var(--size) * -0.05px);
bottom: calc(var(--size) * -0.05px);
left: calc(var(--size) * -0.05px);
}
.cauldron__handle {
height: calc(var(--size) * 0.3px);
width: calc(var(--size) * 0.3px);
position: absolute;
background: linear-gradient(0deg, var(--darkness), transparent), radial-gradient(100% 100% at 50% 50%, var(--inner-rim-color), transparent), var(--rim-color);
border-radius: 100%;
top: 30%;
z-index: -1;
}
.cauldron__handle:after {
content: '';
background: var(--bg);
height: 50%;
width: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 100%;
}
.cauldron__handle--left {
left: -14%;
}
.cauldron__handle--right {
right: -14%;
}
.cauldron__foot {
background: var(--inner-rim-color);
position: absolute;
z-index: -1;
height: calc(var(--size) * 0.3px);
width: calc(var(--size) * 0.3px);
bottom: -5%;
border-radius: 200% 0 200% 50%/200% 0 200% 50%;
}
.cauldron__foot--left {
left: 10%;
background: radial-gradient(110% 110% at 25% 50%, transparent, var(--darkness) 75%), var(--inner-rim-color);
}
.cauldron__foot--right {
right: 10%;
background: radial-gradient(110% 110% at 25% 50%, transparent, var(--darkness)), var(--inner-rim-color);
transform: rotateY(180deg);
}
.cauldron__bubble {
height: calc(var(--size) * 0.2px);
width: calc(var(--size) * 0.2px);
position: absolute;
border-radius: 100%;
top: 0;
left: calc(var(--x) * 1%);
border: 1px solid var(--potion-stain-light);
background: radial-gradient(100% 115% at 25% 25%, #fff, transparent 33%), radial-gradient(15% 15% at 75% 75%, var(--cauldron-color), transparent), radial-gradient(100% 100% at 50% 25%, transparent, var(--potion-color) 98%);
pointer-events: none;
-webkit-animation: rise calc(var(--speed) * 1s) calc(var(--delay) * -1s) infinite ease;
animation: rise calc(var(--speed) * 1s) calc(var(--delay) * -1s) infinite ease;
}
.cauldron__mouth {
position: absolute;
top: 60%;
left: 50%;
transform: translate(-50%, 0);
height: calc(var(--size) * 0.1px);
width: calc(var(--size) * 0.15px);
border-radius: 100%;
border-bottom: 4px solid #000;
box-shadow: 0px 1px 0 0 var(--lightness);
-webkit-clip-path: inset(50% 0 -10% 0);
clip-path: inset(50% 0 -10% 0);
}
.cauldron__eye {
height: calc(var(--size) * 0.075px);
width: calc(var(--size) * 0.075px);
background: #111;
border-radius: 100%;
position: absolute;
top: 50%;
box-shadow: 1px 1px 1px 0px var(--lightness), -1px -1px 1px 0 var(--inner-rim-color);
-webkit-animation: blink 4s infinite linear both;
animation: blink 4s infinite linear both;
}
.cauldron__eye--left {
left: 20%;
}
.cauldron__eye--right {
right: 20%;
}
@-webkit-keyframes rise {
0% {
transform: scale(0) translate(-50%, 0);
}
100% {
transform: scale(var(--scale)) translate(-50%, -50vh);
opacity: 0;
}
}
@keyframes rise {
0% {
transform: scale(0) translate(-50%, 0);
}
100% {
transform: scale(var(--scale)) translate(-50%, -50vh);
opacity: 0;
}
}
@-webkit-keyframes blink {
9% {
transform: scaleY(1);
}
10% {
transform: scaleY(0);
}
11% {
transform: scaleY(1);
}
12% {
transform: scaleY(0);
}
13% {
transform: scaleY(1);
}
}
@keyframes blink {
9% {
transform: scaleY(1);
}
10% {
transform: scaleY(0);
}
11% {
transform: scaleY(1);
}
12% {
transform: scaleY(0);
}
13% {
transform: scaleY(1);
}
}
结合动画和滤镜实现。这个需要很细心的去分析图形的每个节点。最后发下完整的DEMO。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>HTML5-CSS3应用:绘制小水缸,实现动画效果 | Web前端之家www.jiangweishan.com</title>
<style>
* {
box-sizing: border-box;
transition: background 0.15s ease, box-shadow 0.15s ease;
}
:root {
--cauldron-hue: 34;
--potion-hue: 120;
--size: 200;
--bg: #111;
}
label {
font-weight: bold;
color: #fcfcfc;
margin-bottom: 0.5rem;
}
[type='checkbox'] {
margin-bottom: 2rem;
}
:checked ~ .cauldron {
background: var(--cauldron-color);
}
:checked ~ .cauldron .cauldron__opening {
background: var(--potion-color);
box-shadow: none;
}
:checked ~ .cauldron:after,
:checked ~ .cauldron:before {
background: var(--potion-color);
box-shadow: none;
}
:checked ~ .cauldron:before {
background: transparent;
}
:checked ~ .cauldron .cauldron__handle {
background: var(--rim-color);
}
:checked ~ .cauldron .cauldron__eye {
box-shadow: none;
}
:checked ~ .cauldron .cauldron__mouth {
box-shadow: none;
}
:checked ~ .cauldron .cauldron__foot {
background: var(--inner-rim-color);
}
:checked ~ .cauldron .cauldron__bubble {
background: var(--potion-color);
}
body {
align-items: center;
display: flex;
justify-content: center;
min-height: 100vh;
background: var(--bg);
flex-direction: column;
}
.cauldron {
--rim-color: hsl(var(--cauldron-hue), 100%, 60%);
--inner-rim-color: hsl(var(--cauldron-hue), 100%, 25%);
--potion-color: hsl(var(--potion-hue), 100%, 50%);
--cauldron-color: hsl(var(--cauldron-hue), 100%, 50%);
--darkness: hsl(var(--cauldron-hue), 100%, 10%);
--lightness: hsl(var(--cauldron-hue), 100%, 85%);
--potion-stain-light: hsl(var(--potion-hue), 100%, 70%);
--potion-stain-dark: hsl(var(--potion-hue), 100%, 30%);
border-radius: 100%;
height: calc(var(--size) * 1px);
width: calc(var(--size) * 1px);
background: radial-gradient(25% 25% at 25% 55%, var(--rim-color), transparent), radial-gradient(100% 100% at -2% 50%, transparent, transparent 92%, var(--cauldron-color)), radial-gradient(100% 100% at -5% 50%, transparent, transparent 80%, var(--darkness)), linear-gradient(310deg, var(--inner-rim-color) 25%, transparent), var(--cauldron-color);
position: relative;
}
.cauldron__opening {
width: 100%;
position: absolute;
top: 0;
left: 0;
height: 35%;
background: linear-gradient(90deg, transparent, var(--potion-stain-dark)), var(--potion-color);
border: calc(var(--size) * 0.05px) solid var(--rim-color);
box-shadow: 0 0px calc(var(--size) * 0.05px) calc(var(--size) * 0.005px) var(--rim-color) inset, 0 calc(var(--size) * 0.025px) 0 calc(var(--size) * 0.025px) var(--inner-rim-color) inset, 0 10px 20px 0px var(--darkness), 0 10px 20px -10px var(--inner-rim-color);
border-radius: 100%;
}
.cauldron__opening:after {
content: '';
position: absolute;
background: linear-gradient(90deg, transparent, var(--potion-stain-dark), transparent, var(--potion-stain-light), transparent, var(--potion-stain-dark), transparent);
border-radius: 100%;
top: 8px;
right: 0;
bottom: 4px;
left: 0;
}
.cauldron__opening:before {
content: '';
position: absolute;
box-shadow: 0 0 calc(var(--size) * 0.025px) 0 var(--darkness) inset, 0 -1px calc(var(--size) * 0.015px) 0px var(--darkness) inset, 0 2px calc(var(--size) * 0.015px) 0px var(--lightness) inset, 0 0 calc(var(--size) * 0.075px) calc(var(--size) * 0.05px) var(--rim-color) inset;
border-radius: 100%;
top: calc(var(--size) * -0.05px);
right: calc(var(--size) * -0.05px);
bottom: calc(var(--size) * -0.05px);
left: calc(var(--size) * -0.05px);
}
.cauldron__handle {
height: calc(var(--size) * 0.3px);
width: calc(var(--size) * 0.3px);
position: absolute;
background: linear-gradient(0deg, var(--darkness), transparent), radial-gradient(100% 100% at 50% 50%, var(--inner-rim-color), transparent), var(--rim-color);
border-radius: 100%;
top: 30%;
z-index: -1;
}
.cauldron__handle:after {
content: '';
background: var(--bg);
height: 50%;
width: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 100%;
}
.cauldron__handle--left {
left: -14%;
}
.cauldron__handle--right {
right: -14%;
}
.cauldron__foot {
background: var(--inner-rim-color);
position: absolute;
z-index: -1;
height: calc(var(--size) * 0.3px);
width: calc(var(--size) * 0.3px);
bottom: -5%;
border-radius: 200% 0 200% 50%/200% 0 200% 50%;
}
.cauldron__foot--left {
left: 10%;
background: radial-gradient(110% 110% at 25% 50%, transparent, var(--darkness) 75%), var(--inner-rim-color);
}
.cauldron__foot--right {
right: 10%;
background: radial-gradient(110% 110% at 25% 50%, transparent, var(--darkness)), var(--inner-rim-color);
transform: rotateY(180deg);
}
.cauldron__bubble {
height: calc(var(--size) * 0.2px);
width: calc(var(--size) * 0.2px);
position: absolute;
border-radius: 100%;
top: 0;
left: calc(var(--x) * 1%);
border: 1px solid var(--potion-stain-light);
background: radial-gradient(100% 115% at 25% 25%, #fff, transparent 33%), radial-gradient(15% 15% at 75% 75%, var(--cauldron-color), transparent), radial-gradient(100% 100% at 50% 25%, transparent, var(--potion-color) 98%);
pointer-events: none;
-webkit-animation: rise calc(var(--speed) * 1s) calc(var(--delay) * -1s) infinite ease;
animation: rise calc(var(--speed) * 1s) calc(var(--delay) * -1s) infinite ease;
}
.cauldron__mouth {
position: absolute;
top: 60%;
left: 50%;
transform: translate(-50%, 0);
height: calc(var(--size) * 0.1px);
width: calc(var(--size) * 0.15px);
border-radius: 100%;
border-bottom: 4px solid #000;
box-shadow: 0px 1px 0 0 var(--lightness);
-webkit-clip-path: inset(50% 0 -10% 0);
clip-path: inset(50% 0 -10% 0);
}
.cauldron__eye {
height: calc(var(--size) * 0.075px);
width: calc(var(--size) * 0.075px);
background: #111;
border-radius: 100%;
position: absolute;
top: 50%;
box-shadow: 1px 1px 1px 0px var(--lightness), -1px -1px 1px 0 var(--inner-rim-color);
-webkit-animation: blink 4s infinite linear both;
animation: blink 4s infinite linear both;
}
.cauldron__eye--left {
left: 20%;
}
.cauldron__eye--right {
right: 20%;
}
@-webkit-keyframes rise {
0% {
transform: scale(0) translate(-50%, 0);
}
100% {
transform: scale(var(--scale)) translate(-50%, -50vh);
opacity: 0;
}
}
@keyframes rise {
0% {
transform: scale(0) translate(-50%, 0);
}
100% {
transform: scale(var(--scale)) translate(-50%, -50vh);
opacity: 0;
}
}
@-webkit-keyframes blink {
9% {
transform: scaleY(1);
}
10% {
transform: scaleY(0);
}
11% {
transform: scaleY(1);
}
12% {
transform: scaleY(0);
}
13% {
transform: scaleY(1);
}
}
@keyframes blink {
9% {
transform: scaleY(1);
}
10% {
transform: scaleY(0);
}
11% {
transform: scaleY(1);
}
12% {
transform: scaleY(0);
}
13% {
transform: scaleY(1);
}
}
</style>
</head>
<body>
<label for="toggle">Turn shading off</label>
<input id="toggle" type="checkbox"/>
<div class="cauldron" style="--potion-hue: 176">
<div class="cauldron__opening">
<div class="cauldron__bubble" style="--delay: 6; --scale: 1.27; --speed: 9; --x: 57"></div>
<div class="cauldron__bubble" style="--delay: 5; --scale: 1; --speed: 5; --x: 67"></div>
<div class="cauldron__bubble" style="--delay: 4; --scale: 0.86; --speed: 7; --x: 63"></div>
<div class="cauldron__bubble" style="--delay: 0; --scale: 1.27; --speed: 9; --x: 60"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.5; --speed: 10; --x: 38"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.14; --speed: 5; --x: 66"></div>
<div class="cauldron__bubble" style="--delay: 10; --scale: 0.63; --speed: 9; --x: 74"></div>
<div class="cauldron__bubble" style="--delay: 5; --scale: 0.93; --speed: 5; --x: 61"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.29; --speed: 6; --x: 35"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1; --speed: 5; --x: 27"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.71; --speed: 9; --x: 39"></div>
<div class="cauldron__bubble" style="--delay: 8; --scale: 1.5; --speed: 9; --x: 69"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.34; --speed: 9; --x: 63"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.88; --speed: 9; --x: 34"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.11; --speed: 6; --x: 47"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.56; --speed: 6; --x: 46"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.97; --speed: 9; --x: 39"></div>
<div class="cauldron__bubble" style="--delay: 6; --scale: 0.69; --speed: 9; --x: 73"></div>
<div class="cauldron__bubble" style="--delay: 3; --scale: 1.12; --speed: 6; --x: 57"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 0.55; --speed: 5; --x: 55"></div>
<div class="cauldron__bubble" style="--delay: 7; --scale: 0.53; --speed: 5; --x: 72"></div>
<div class="cauldron__bubble" style="--delay: 4; --scale: 1.04; --speed: 8; --x: 59"></div>
<div class="cauldron__bubble" style="--delay: 2; --scale: 1.12; --speed: 5; --x: 41"></div>
<div class="cauldron__bubble" style="--delay: 0; --scale: 0.71; --speed: 9; --x: 66"></div>
<div class="cauldron__bubble" style="--delay: 9; --scale: 0.66; --speed: 6; --x: 47"></div>
</div>
<div class="cauldron__handle cauldron__handle--left"></div>
<div class="cauldron__handle cauldron__handle--right"></div>
<div class="cauldron__foot cauldron__foot--left"></div>
<div class="cauldron__foot cauldron__foot--right"></div>
<div class="cauldron__eye cauldron__eye--left"></div>
<div class="cauldron__eye cauldron__eye--right"></div>
<div class="cauldron__mouth"></div>
</div>
</body>
</html>