- 做者:陳大魚頭
- github: KRISACHAN
一聲梧葉一聲秋,一點芭蕉一點愁,三更歸夢三更後。javascript
大概是由於入秋的緣故,最近的感慨比較多。css
不少的碎碎念都用都用 HTML 跟 CSS 來記錄在個人codepen codepen.io/krischan77 至上,眼見積累到了一些了,就選出幾個來與你們一同分享。html
(免責聲明:有些效果是我在網上看到以爲好,而後臨摹下來的,創意不是原創,可是代碼是本身手寫的,若是有看到相似的效果,歡迎你們用來做對比。)前端
文章篇幅有限,所以有些太長的代碼會進行壓縮,請兩句。java
這是兩個帶有彈性勢能的彈跳盒,實現的主要思路就是利用 @keyframes
來控制 盒子的 scale
跟 translate
,從而在視覺上達成彈跳的效果。git
(關於「洋溢着青春的活力」動效的說明,這個動效出處是第五屆CSS大會上騰訊CDC高級前端開發陳在真老師以「CSS TIME」爲主題的演講中的講解示例,主題連接在此:www.yuque.com/cssconf/5th… 當時魚頭我是想模仿下來來着,後來由於以爲關鍵幀調試麻煩,就直接CV了源碼,時間一過就忘了這事,當成是原創的了。在這裏對陳在真老師表示萬分抱歉,同時也給讀者們表示萬分抱歉,是個人失誤)github
效果地址:codepen.io/krischan77/…web
具體代碼:面試
<style> html, body, div { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; } .盒子組 { width: 200px; height: 200px; position: absolute; left: 50%; top: 30px; transform: translateX(-50%); } .大盒子 { width: 100px; height: 100px; transform: scale(1, 1) translate(0, 0px); animation: 大盒子跳 1s 0.3s linear infinite; background: #3170a7; margin: 100px auto; } .小盒子 { width: 60px; height: 60px; transform: scale(1, 1) translate(0, 0px); animation: 小盒子跳 1s 0.3s linear infinite; background: #40a070; margin: 0 auto; position: relative; top: -60px; } @keyframes 大盒子跳 { 0% { transform: scale(1, 1) translate(0, 0px); } 15% { transform: scale(1.13, 0.87) translate(0, 0px); } 30% { transform: scale(0.92, 1.08) translate(0, -40px); } 45% { transform: scale(1.05, 0.95) translate(0, 0px); } 60% { transform: scale(0.93, 1.02) translate(0, -20px); } 75% { transform: scale(1, 1) translate(0, 0px); } 100% { transform: scale(1, 1) translate(0, 0px); } } @keyframes 小盒子跳 { 0% { transform: scale(1, 1) translate(0, 0px); } 50% { transform: scale(1, 1) translate(0, 0px); } 60% { transform: scale(1.13, 0.87) translate(0, 0px); } 70% { transform: scale(0.92, 1.08) translate(0, -40px); } 80% { transform: scale(1.05, 0.95) translate(0, 0px); } 90% { transform: scale(0.98, 1.02) translate(0, -20px); } 100% { transform: scale(1, 1) translate(0, 0px); } } </style>
<div class="盒子組">
<div class="大盒子">
<div class="小盒子"></div>
</div>
</div>
複製代碼
這是在好久以前一個網友面試時被問到的問題,當時題目是如何用純CSS實現物體根據鼠標進入盒子的方向移動,一道挺有意思的題目,當時在羣裏各位大佬的討論下,就有了這樣的實現。微信
實現思路主要是在盒子四個不一樣的方位定位好子盒子,而後隱藏的同時讓它們稍稍進入父盒子裏一點,那麼再鼠標划進去時,就能觸發該方位隱藏的子盒子的 hover
事件,利用這個障眼法從而達到題目的效果。
代碼以下:
<style> body { padding: 2em; text-align: center; } .block { position: relative; display: inline-block; overflow:hidden; width: 10em; height: 10em; vertical-align: middle; -webkit-transform: translateZ(0); } .block_hoverer { position: absolute; z-index: 1; width: 100%; height: 100%; opacity: 0; transition: all .3s ease; } .block_hoverer:nth-child(1) { background: red; top:-90%; } .block_hoverer:nth-child(2) { background: lime; top:90%; } .block_hoverer:nth-child(3) { background: orange; left:-90%; } .block_hoverer:nth-child(4) { background: blue; left:90%; } .block_hoverer:hover { opacity:1; top:0; left:0; } .block_content { position: absolute; top: 0; left: 0; width: 100%; height: 100%; text-align: center; line-height: 10em; background: #333; color: #FFF; } </style>
<p class="text">從不一樣方向使鼠標指針移過下面的內容</p>
<p>↓</p>
<span>→ </span>
<div class="block">
<div class="block_hoverer">1</div>
<div class="block_hoverer">2</div>
<div class="block_hoverer">3</div>
<div class="block_hoverer">4</div>
<div class="block_content">
Hover me!
</div>
</div>
<span> ←</span>
<p>↑</p>
複製代碼
這是用純CSS實現的一個評級功能,主要是利用了 label
標籤跟 input
標籤的聯動性,以及 僞類:hover
跟 :focus
的操做性實現的。
代碼以下:
<style> html, body, div { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; } .container1, .container2 { font-size: 60px; display: flex; flex-direction: row-reverse; justify-content: center; } .container1 input { opacity: 0; position: absolute; } .container1 label { color: #aaa; text-decoration: none; -webkit-transition: color .4s; -moz-transition: color .4s; -o-transition: color .4s; transition: color .4s; } .container1 label:hover ~ label, .container1 input:focus ~ label, .container1 label:hover { color: #cc163a; cursor: pointer; } .container2 label { cursor: pointer; font-size: 60px; } .container2 input { opacity: 0; position: absolute; } .container2 label:hover ~ label, .container2 label:hover, .container2 input:focus ~ label, .container2 input:checked ~ label { color: #cc163a; } </style>
<section class="container1">
<input name="star1" id="s1" type="radio" /><label for="s1">☆</label>
<input name="star1" id="s2" type="radio" /><label for="s2">☆</label>
<input name="star1" id="s3" type="radio" /><label for="s3">☆</label>
<input name="star1" id="s4" type="radio" /><label for="s4">☆</label>
<input name="star1" id="s5" type="radio" /><label for="s5">☆</label>
</section>
<section class="container2">
<input type="radio" name="star2" id="s6">
<label for="s6">☆</label>
<input type="radio" name="star2" id="s7">
<label for="s7">☆</label>
<input type="radio" name="star2" id="s8">
<label for="s8">☆</label>
<input type="radio" name="star2" id="s9">
<label for="s9">☆</label>
<input type="radio" name="star2" id="s10">
<label for="s10">☆</label>
</section>
複製代碼
這是一隻兔子的路徑動畫,實現原理就是利用 animation
來操做 SVG path的 stroke-dashoffset
,從而實現路徑動畫。
代碼以下:
<style> path { stroke-dasharray: 6600; stroke-dashoffset: 6600; animation: dash 4s linear alternate infinite; fill: transparent; } @keyframes dash { to { stroke-dashoffset: 0; fill: #d81e06; } } </style>
<svg width="240" height="240" viewBox="0 0 1165 1024" version="1.1">
<path fill="transparent" stroke="#1296db" stroke-width="30" d="M0.000556 865.83469a66.118285 66.118285 0 0 0 65.93308 65.93308 69.08157 69.08157 0 0 0 39.63393-12.593959 222.246337 222.246337 0 0 0 111.123169 49.44981l26.113945 4.444927a232.247423 232.247423 0 0 0-5.370953 47.968168v2.222463h383.189726v-31.299693a123.717128 123.717128 0 0 0-62.043769-50.746247h-98.158799l-21.669018-15.927654 200.762525-50.931452 11.297522 17.594501 30.373666 79.823477 17.224092 52.227889H907.506434v-32.596129a144.83053 144.83053 0 0 0-38.893109-27.780793l-24.076687-11.667932-40.745161-62.969796v-112.790016a1069.375294 1069.375294 0 0 0 126.495207-140.015193l8.334237-0.926026 188.724182-49.635016h0.926026l36.11503-55.561584v-34.448182l-88.528124-97.417978a257.620546 257.620546 0 0 0-84.824019-61.117743l-13.519986-49.820221L944.54749 157.980105l-29.632845-67.414722L825.460495 10.556701A45.745704 45.745704 0 0 0 777.862737 3.889311a44.819678 44.819678 0 0 0-17.409296 13.33478l-7.408211-6.66739a46.30132 46.30132 0 0 0-74.082113 43.708446l60.376922 190.76144 72.785675 64.821849 12.96437 34.448182a371.706999 371.706999 0 0 0-58.710074 68.711159l-7.778622 11.482728-560.245976 107.048652a222.246337 222.246337 0 0 0-166.684753 267.066016c0 3.14849 1.666848 6.29698 2.592874 9.445469A65.377464 65.377464 0 0 0 0.000556 865.83469z" class="path"></path>
</svg>
複製代碼
這個動效主要是利用了animation
來控制不一樣關鍵幀下的水滴狀態,這裏的滴水動畫要注意的就是水滴下落的形變,以及到地上時引發的漣漪,主要是要儘可能貼合物理現象。
代碼以下:
<style> .water-damage { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200px; height: 200px; perspective: 600px; transform-style: preserve-3d; } .water-drop { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; width: 0; height: 0; border: 10px solid #30DFF3; border-radius: 1000px; margin-top: -10px; margin-left: -10px; opacity: 0; transform-style: preserve-3d; transform-origin: 50% 50%; transform: translate(0, -100px) scale(1, 1); animation: water-drop 3000ms cubic-bezier(.56, .18, .92, .69) infinite; } .water-drop::after { content: ""; width: 0; height: 0; border-style: solid; border-width: 0 7.5px 13.0px 7.5px; border-color: transparent transparent #30DFF3 transparent; position: absolute; left: 50%; top: -20px; transform: translate(-50%, 0); } @keyframes water-drop { 0% { opacity: 0; z-index: 10; transform: translate(0, -100px) scale(1, 1); } 50% { opacity: 1; z-index: 10; transform: translate(0, 0) scale(0.8, 1.2); } 51% { opacity: 1; z-index: 10; margin-top: -10px; margin-left: -10px; border-width: 10px; transform: rotateX(70deg); animation-timing-function: cubic-bezier(.12, .41, .63, .99); } 100% { opacity: 0; z-index: 1; margin-top: -200px; margin-left: -200px; border-width: 200px; transform: rotateX(70deg); animation-timing-function: cubic-bezier(.12, .41, .63, .99); } } </style>
<div class="water-damage">
<div class="water-drop"></div>
</div>
複製代碼
這是由於抖音而走紅的故障風效果,實現原理就是經過animation
來用 clip-path: inset
對元素進行不一樣位置的切割,從而實現故障風動畫。
代碼以下:
<style> .glitch-effect { margin: auto; display: flex; justify-content: center; align-items: center; flex-direction: column; position: absolute; top: 10px; left: 0; right: 0; color: #FFF; text-align: center; font-size: 50px; letter-spacing: 10px; } .ge-text { position: relative; color: #fff; font-size: 72px; line-height: 1; letter-spacing: 0.01em; transform: scale3d(1, 1, 1); padding: 10px 50px; background-image: linear-gradient( 135deg, #72EDF2 10%, #5151E5 100%); overflow: hidden; } .ge-text::before, .ge-text::after { content: attr(aria-title); position: absolute; left: 0; top: 0; width: 100%; height: 100%; color: #fff; background-image: linear-gradient( 135deg, #72EDF2 10%, #5151E5 100%); clip-path: inset(79px 50px 43px 0px); overflow: hidden; } .ge-text::before { left: 7px; text-shadow: 1px 0 #a1ffce; animation: glitch-effect 3s infinite linear alternate-reverse; } .ge-text::after { left: 3px; text-shadow: -1px 0 #faffd1; animation: glitch-effect 2s infinite linear alternate-reverse; } @keyframes glitch-effect { 0% { clip-path: inset(4px 50px 61px 0px); } 5% { clip-path: inset(99px 50px 30px 0px); } 10% { clip-path: inset(100px 50px 90px 0px); } 15% { clip-path: inset(69px 50px 98px 0px); } 20% { clip-path: inset(51px 50px 18px 0px); } 25% { clip-path: inset(43px 50px 38px 0px); } 30% { clip-path: inset(67px 50px 71px 0px); } 35% { clip-path: inset(32px 50px 44px 0px); } 40% { clip-path: inset(98px 50px 96px 0px); } 45% { clip-path: inset(92px 50px 93px 0px); } 50% { clip-path: inset(23px 50px 84px 0px); } 55% { clip-path: inset(15px 50px 46px 0px); } 60% { clip-path: inset(53px 50px 9px 0px); } 65% { clip-path: inset(89px 50px 21px 0px); } 70% { clip-path: inset(47px 50px 1px 0px); } 75% { clip-path: inset(98px 50px 55px 0px); } 80% { clip-path: inset(86px 50px 81px 0px); } 85% { clip-path: inset(25px 50px 47px 0px); } 90% { clip-path: inset(49px 50px 87px 0px); } 95% { clip-path: inset(7px 50px 59px 0px); } 100% { clip-path: inset(79px 50px 43px 0px); } } </style>
<div class="glitch-effect">
<h1 class="ge-text" aria-title="有趣的CSS">AWESOME</h1>
</div>
複製代碼
這是用 display: grid
完成的心型佈局,grid
真的是一個很是有用佈局屬性,建議還不熟的親能夠花時間去學習學習,這個心型佈局實現的核心就是利用grid
的二維性來建立一個 columns 爲11,rows 爲10的盒子,而後按照心型的形狀去定義子元素的 grid-area
,動畫就是常規的顯隱動畫。
順便安利下,這是一個在線生成GRID佈局的神器:cssgrid-generator.netlify.com/,經過這個網站就能夠自動生成你想要的佈局。
代碼以下:
<style> html, body, div { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; background: linear-gradient(to right, #141e30, #243b55); } .text { text-align: center; line-height: 3; -webkit-text-fill-color: transparent; background: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%); -webkit-background-clip: text; font-size: 30px; } .parent { width: 700px; height: 700px; display: grid; grid-template-columns: repeat(11, 1fr); grid-template-rows: repeat(10, 1fr); grid-column-gap: 10px; grid-row-gap: 10px; margin: auto; position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .parent > div { background: none; border-radius: 10px; animation-name: love; animation-duration: 0.2s; animation-timing-function: ease; animation-iteration-count: 1; animation-direction: normal; animation-fill-mode: both; animation-play-state: running; } .div1 { grid-area: 3 / 6 / 4 / 7; } .div2 { grid-area: 2 / 7 / 3 / 8; } .div3 { grid-area: 1 / 8 / 2 / 9; } .div4 { grid-area: 1 / 9 / 2 / 10; } .div5 { grid-area: 2 / 10 / 3 / 11; } .div6 { grid-area: 3 / 11 / 4 / 12; } .div7 { grid-area: 4 / 11 / 5 / 12; } .div8 { grid-area: 5 / 11 / 6 / 12; } .div9 { grid-area: 6 / 10 / 7 / 11; } .div10 { grid-area: 7 / 9 / 8 / 10; } .div11 { grid-area: 8 / 8 / 9 / 9; } .div12 { grid-area: 9 / 7 / 10 / 8; } .div13 { grid-area: 10 / 6 / 11 / 7; } .div14 { grid-area: 9 / 5 / 10 / 6; } .div15 { grid-area: 8 / 4 / 9 / 5; } .div16 { grid-area: 7 / 3 / 8 / 4; } .div17 { grid-area: 6 / 2 / 7 / 3; } .div18 { grid-area: 5 / 1 / 6 / 2; } .div19 { grid-area: 4 / 1 / 5 / 2; } .div20 { grid-area: 3 / 1 / 4 / 2; } .div21 { grid-area: 2 / 2 / 3 / 3; } .div22 { grid-area: 1 / 3 / 2 / 4; } .div23 { grid-area: 1 / 4 / 2 / 5; } .div24 { grid-area: 2 / 5 / 3 / 6; } @keyframes love { from { background: none; } to { background: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%); } } </style>
<div class="text">願我如星君如月,夜夜流光相皎潔。</div><div class="parent"><div class="div1"></div><div class="div2"></div><div class="div3"></div><div class="div4"></div><div class="div5"></div><div class="div6"></div><div class="div7"></div><div class="div8"></div><div class="div9"></div><div class="div10"></div><div class="div11"></div><div class="div12"></div><div class="div13"></div><div class="div14"></div><div class="div15"></div><div class="div16"></div><div class="div17"></div><div class="div18"></div><div class="div19"></div><div class="div20"></div><div class="div21"></div><div class="div22"></div><div class="div23"></div><div class="div24"></div></div>
<script> 'use strict' const div = [...document.querySelectorAll('.parent > div')] div.forEach((d, i) => { d.style = `animation-delay: ${(i + 1) * 0.2}s` }) </script>
複製代碼
這是利用 transform
跟 transition
實現的一個3D輪播圖,就是利用雪碧圖思路將要輪播的背景切割給各個子盒子,而後子盒子進行Z軸變換。
代碼以下:
<style> html, body, div { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; } :root { --base-color: #03A9F4; --bg-color: #3cba92; } .center { position: absolute; margin: auto; top: 50px; right: 0; left: 0; } .box { width: calc(var(--base-size) * 4); height: var(--base-size); } .slider { width: var(--base-size); height: var(--base-size); color: var(--base-color); perspective: 0px; transform-style: preserve-3d; position: absolute; top: 0; transform: rotateX(0deg); } .slider-1 { left: calc(var(--base-size) * 0); transition: all 1s linear 0s; } .slider-2 { left: calc(var(--base-size) * 1); transition: all 1s linear 0.5s; } .slider-3 { left: calc(var(--base-size) * 2); transition: all 1s linear 1s; } .slider-4 { left: calc(var(--base-size) * 3); transition: all 1s linear 1.5s; } .slider-page { transform-style: preserve-3d; width: var(--base-size); height: var(--base-size); position: relative; } .slider-main { width: var(--base-size); height: var(--base-size); position:absolute; box-sizing: border-box; border: 1px solid currentcolor; } .slider-front { transform: translateZ(calc(var(--base-size) / 2)); background-image: url(http://www.33lc.com/article/UploadPic/2012-8/2012891154949207.jpg); border: none; } .slider-bottom { transform: rotateX(-90deg) translateZ(calc(var(--base-size) / 2)); background-image: url(http://pic1.win4000.com/wallpaper/3/5858a0ab1ceb6.jpg); border: none; } .slider-back { transform: rotateZ(180deg) translateZ(calc(calc(-1 * var(--base-size)) / 2)); background-image: url(http://pic1.win4000.com/wallpaper/2/53cf2c1e5056b.jpg); border: none; } .slider-top { transform: rotateX(90deg) translateZ(calc(var(--base-size) / 2)); background-image: url(http://img.zcool.cn/community/03886cf575a66110000018c1b51ca27.jpg); border: none; } .slider-right { visibility: hidden; transform: rotateY(90deg) translateZ(calc(var(--base-size) / 2)); } .slider-left { visibility: hidden; transform: rotateY(-90deg) translateZ(calc(var(--base-size) / 2)); } </style>
<div class="box center">
<div class="slider slider-1">
<div class="slider-page">
<div class="slider-main slider-front"></div>
<div class="slider-main slider-bottom"></div>
<div class="slider-main slider-back"></div>
<div class="slider-main slider-top"></div>
<div class="slider-main slider-right"></div>
<div class="slider-main slider-left"></div>
</div>
</div>
<div class="slider slider-2">
<div class="slider-page">
<div class="slider-main slider-front"></div>
<div class="slider-main slider-bottom"></div>
<div class="slider-main slider-back"></div>
<div class="slider-main slider-top"></div>
<div class="slider-main slider-right"></div>
<div class="slider-main slider-left"></div>
</div>
</div>
<div class="slider slider-3">
<div class="slider-page">
<div class="slider-main slider-front"></div>
<div class="slider-main slider-bottom"></div>
<div class="slider-main slider-back"></div>
<div class="slider-main slider-top"></div>
<div class="slider-main slider-right"></div>
<div class="slider-main slider-left"></div>
</div>
</div>
<div class="slider slider-4">
<div class="slider-page">
<div class="slider-main slider-front"></div>
<div class="slider-main slider-bottom"></div>
<div class="slider-main slider-back"></div>
<div class="slider-main slider-top"></div>
<div class="slider-main slider-right"></div>
<div class="slider-main slider-left"></div>
</div>
</div>
</div>
<script> 'use strict' const baseSize = 200 document.documentElement.style.setProperty('--base-size', baseSize + 'px') const sliders = [...document.querySelectorAll('.slider')] const len = sliders - 1 sliders.forEach((slider, idx) => { const xPos = (idx * baseSize) const front = slider.querySelector('.slider-front') const bottom = slider.querySelector('.slider-bottom') const back = slider.querySelector('.slider-back') const top = slider.querySelector('.slider-top') front.style = `background-position: -${xPos}px -100px;` bottom.style = `background-position: -${xPos}px -100px;` back.style = `background-position: ${xPos}px 0px;` top.style = `background-position: -${xPos}px -100px;` }) const setPos = () => { let index = 0 const setRotateX = () => { index++ if (index > 3) { index = 0 } sliders.forEach(slider => { slider.style.transform = `rotateX(${index * 90}deg)` }) setTimeout(() => { setRotateX() }, 3000) } setRotateX() } setPos() </script>
複製代碼
這是利用了 cubic-bezier
貝塞爾曲線的特性實現的動畫,彩虹條的顏色是利用了filter: hue-rotate
去將色調轉換。
代碼以下:
<style> html, body, div { margin: 0; padding: 0; } html, body { background: linear-gradient(to right, #0f2027, #203a43, #2c5364); width: 100%; height: 100%; } h1 { text-align: center; line-height: 3; font-weight: 700; -webkit-text-fill-color: transparent; background-color: hsla(0, 100%, 60%, .8); -webkit-background-clip: text; animation: textColorRotate 5s linear infinite; letter-spacing:2px } .rainbow-box { position: absolute; top: 100px; right: 0; left: 0; margin: auto; width: 200px; height: 200px; } .rainbow-arc { position: absolute; left: 0; top: 0; width: 200px; height: 100px; box-sizing: border-box; overflow: hidden; transform-origin: 50% 100%; animation: rainbowMove 3s cubic-bezier(.58,-0.57,.5,1.66) infinite; } .rainbow-arc-main { border: 4px solid transparent; border-radius: 100%; box-sizing: border-box; height: 150px; left: 0; margin: 0 auto; position: absolute; right: 0; top: 0; width: 150px; } .rainbow-arc:nth-child(1) { animation-delay: -50ms; } .rainbow-arc:nth-child(2) { animation-delay: -100ms; } .rainbow-arc:nth-child(3) { animation-delay: -150ms; } .rainbow-arc:nth-child(4) { animation-delay: -200ms; } .rainbow-arc:nth-child(5) { animation-delay: -250ms; } .rainbow-arc:nth-child(6) { animation-delay: -300ms; } .rainbow-arc:nth-child(7) { animation-delay: -350ms; } .rainbow-arc:nth-child(1) .rainbow-arc-main { border-color: hsla(0, 100%, 60%, .8); height: 200px; width: 200px; top: 10px; } .rainbow-arc:nth-child(2) .rainbow-arc-main { border-color: hsla(30, 100%, 60%, .8); height: 180px; width: 180px; top: 20px; } .rainbow-arc:nth-child(3) .rainbow-arc-main { border-color: hsla(60, 100%, 60%, .8); height: 160px; width: 160px; top: 30px; } .rainbow-arc:nth-child(4) .rainbow-arc-main { border-color: hsla(90, 100%, 60%, .8); height: 140px; width: 140px; top: 40px; } .rainbow-arc:nth-child(5) .rainbow-arc-main { border-color: hsla(120, 100%, 60%, .8); height: 120px; width: 120px; top: 50px; } .rainbow-arc:nth-child(6) .rainbow-arc-main { border-color: hsla(150, 100%, 60%, .8); height: 100px; width: 100px; top: 60px; } .rainbow-arc:nth-child(7) .rainbow-arc-main { border-color: hsla(180, 100%, 60%, .8); height: 80px; width: 80px; top: 70px; } @keyframes textColorRotate { from { filter: hue-rotate(0deg); } to { filter: hue-rotate(360deg); } } @keyframes rainbowMove { 0%, 15% { transform: rotate(0); } 100% { transform: rotate(360deg); } } </style>
<h1><i>斯人若彩虹,趕上方知有</i></h1>
<div class="rainbow-box">
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
<div class="rainbow-arc">
<div class="rainbow-arc-main"></div>
</div>
</div>
複製代碼
這是在線生成貝塞爾曲線的網站,經過這個網站,你不須要手寫,只須要在線調試就能夠生成需用的值:cubic-bezier.com
這個效果是爲了慶祝祖國母親70週年生日而畫的,這裏的五星紅旗是經過SVG畫的,早前在本身的文章裏有提過五星紅旗的具體屬性。
國旗是五星紅旗,旗面爲紅色,長寬比例爲3:2。左上方綴黃色五角星五顆,四顆小星(其外接圓直徑爲旗高1/10)環拱在一顆大星(其外接圓直徑爲旗高3/10)的右面,並各有一個角尖正對大星的中心點。
通用尺寸有如下五種:
因此咱們有如下的墨線圖:
因此按照這個比例咱們能畫出這樣的SVG:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 30 20">
<defs>
<path id="s" d="M0,-1 0.587785,0.809017 -0.951057,-0.309017H0.951057L-0.587785,0.809017z" fill="#ffde00"/>
</defs>
<rect width="30" height="20" fill="#de2910"/>
<use xlink:href="#s" transform="translate(5,5) scale(3)"/>
<use xlink:href="#s" transform="translate(10,2) rotate(23.036243)"/>
<use xlink:href="#s" transform="translate(12,4) rotate(45.869898)"/>
<use xlink:href="#s" transform="translate(12,7) rotate(69.945396)"/>
<use xlink:href="#s" transform="translate(10,9) rotate(20.659808)"/>
</svg>
複製代碼
至於飄揚的動畫部分,一樣是利用了雪碧圖的原理,將圖片的每一塊區域賦值給dom節點,而後利用transform
進行Y軸的移動。
完整代碼以下:
<style> * { margin: 0; padding: 0; } html, body { height: 100%; width: 100%; } li { list-style: none; } .flag { position: absolute; left: 50%; top: 50%; animation: wave ease-in-out infinite; } .flag > li { height: 100%; float: left; background-image: url("https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/others/chinese/flag.jpg"); background-size: auto 100%; animation: flag ease-in-out infinite; } </style>
<ul id="flag" class="flag"></ul>
<script> const flag = document.querySelector('#flag') const image = new Image() image.src = 'https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/others/chinese/flag.jpg' const flagWidth = 800 const flagHeight = 640 let imgWidth = '' let imgHeight = '' const imgRender = ({ sliceCount = 70, amplitude = 20, period = 1.5, duration = 2, }) => { const style = document.createElement('style') const styleSplinter = [] const sliceCountPerPeriod = Math.floor(sliceCount / period) const sliceWidth = imgWidth / sliceCount const formula = sliceCountPerPeriod + 'n+' const delay = (duration * period / sliceCount) for (let i = 0; i < sliceCount; ++i) { if (i < sliceCountPerPeriod) { styleSplinter.push(` .flag > li:nth-child(${formula + i}) { animation-delay: -${delay * (sliceCountPerPeriod - i)}s; } `) } styleSplinter.push(` .flag > li:nth-child(${i}) { background-position: -${i * sliceWidth}px 0; } `) } styleSplinter.push(` @keyframes flag { 0% { transform: translate3d(0, ${amplitude}px, 0); } 50% { transform: translate3d(0, ${-amplitude}px, 0); } 100% { transform: translate3d(0, ${amplitude}px, 0); } } @keyframes wave { 0% { transform: translate3d(0, ${-amplitude}px, 0); } 50% { transform: translate3d(0, ${amplitude}px, 0); } 100% { transform: translate3d(0, ${-amplitude}px, 0); } } .flag { animation-duration: ${duration}s; animation-delay: -${delay * sliceCountPerPeriod}s; } .flag > li { animation-duration: ${duration}s; width: ${imgWidth / sliceCount}px; } `) style.innerHTML = styleSplinter.join('') flag.innerHTML = new Array(sliceCount + 1).join('<li></li>') document.documentElement.appendChild(style) } image.onload = () => { imgWidth = image.width imgHeight = image.height const ratio = image.width / image.height if (imgWidth > flagWidth) { imgWidth = flagWidth imgHeight = imgWidth / ratio } if (imgHeight > flagHeight) { imgWidth = imgHeight * ratio imgHeight = flagHeight } flag.style.width = imgWidth + 'px' flag.style.height = imgHeight + 'px' flag.style.marginLeft = -imgWidth / 2 + 'px' flag.style.marginTop = -imgHeight / 2 + 'px' imgRender({ sliceCount: 70, amplitude: 20, period: 1.5, duration: 2, }) } </script>
複製代碼
其實CSS仍是頗有趣的,各位有興趣也能夠多多發掘,多多開腦洞來創做一些有趣的特效。
魚頭我時不時就會上codepen.io/去看別人的創意,從中獲取寫CSS的靈感,各位對CSS感興趣,或者但願能夠加強CSS水平的均可以進去看看,固然裏面不止有CSS,還有各種DEMO,算是可視化版的github了~
若是你、喜歡探討技術,或者對本文有任何的意見或建議,你能夠掃描下方二維碼,關注微信公衆號「 魚頭的Web海洋 」,隨時與魚頭互動。歡迎!衷心但願能夠碰見你。