今天继续分享一个用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>