- 做者:陳大魚頭
- github: KRISACHAN
「我和個人祖國一刻也不能分割,不管我走到哪裏都流出一首讚歌。」javascript
相信你們最近已經被 《我和個人祖國》 這首歌給刷屏了,魚頭每次在聽到這首歌的時候,總會感慨萬千,咱們偉大的新中國,這70年真的經歷了太多太多了。css
可是就是在一代又一代的人不懈的努力下,現在的中國,已經成爲了各個國家,乃至西方列強所沒法忽視的強大存在。html
中國是世界上文明發達最先的國家之一,有將近5000年的有文字可考的歷史。前端
曾經,西漢開闢了絲綢之路,經過絲綢鏈接了從古都長安到羅馬帝國這條路上的各個國家;java
曾經,成吉思汗和他的後代,從公元1205年起,前後滅掉了西夏和金朝,而後又征服了中亞、西亞和亞洲西部的許多國家,一直打到歐洲的多瑙河畔。git
可是,從1840年 第一次鴉片戰爭 開始,中國受了將近100年的屈辱。github
從1840年鴉片戰爭到1919年五四運動前夕的舊民主主義革命階段,微信
從1919年五四運動到1949年中華人民共和國成立前夕的新民主主義革命階段,dom
咱們經歷了太多太多。svg
曾經在1936年柏林奧運會69人的表明團因全軍覆沒,途經新加坡時,被當地報刊諷刺爲 「東亞病夫」 。就如同下面的GIF同樣,殘缺,破損。
上面GIF的風格被稱之爲是「故障風(Glitch Effect)」,是近期比較流行的一種設計風格。因此是怎麼實現的呢?
<style> .ge-text { position: relative; color: #fff; font-size: 72px; line-height: 1; letter-spacing: 0.01em; transform: scale3d(1, 1, 1); padding: 10px 20px; background: linear-gradient(to right, #232526, #414345); 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: linear-gradient(to right, #232526, #414345); clip-path: inset(79px 50px 43px 0px); overflow: hidden; } .ge-text::before { left: 7px; animation: glitch-effect 3s infinite linear alternate-reverse; } .ge-text::after { left: 3px; 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); } ...(省略了不一樣百分比下的的值) 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="東亞病夫">東亞病夫</h1>
</div>
複製代碼
(重複代碼太多,就不所有放出來了,具體實現能夠看個人codepen)
咱們看上面的GIF,不難發現所謂的故障風就是相同圖形不一樣的位置跳動。只是都是浮在正常圖形之上的跳動,因此看起來有物體故障的感受,抖音的LOGO GIF就是這麼個操做。
既然知道這一點,咱們第一步就是作三個如出一轍,可是位置不一樣的圖形了。
上述DEMO我是用了::before
跟::after
,固然,重複的圖形,你能夠只用一個,或者多個均可以,隨你喜歡,就看你喜歡怎樣的故障了。
以後的核心就是clip-path: inset
跟@keyframes
的配合。
clip-path
能夠引入或者建立一個指定裁剪區域的強大屬性,它在代替了已經棄用的clip
屬性的同時還多了須要有趣的功能。
本文不打算詳細講解這個屬性,有興趣的能夠經過MDN 或者 CSS clip-path 生成器 來深刻了解。
clip-path主要由如下4個可選函數:
函數 | 做用 |
---|---|
clip-path: inset( <shape-arg>{1,4} [round <border-radius>]? ) |
用於定義裁剪的矩形區域 |
clip-path: circle( [<shape-radius>]? [at <position>]? ) |
用於定義裁剪的圓形區域 |
clip-path: ellipse( [<shape-radius>{2}]? [at <position>]? ) |
用於定義裁剪的橢圓區域 |
clip-path: polygon( [<fill-rule>,]? [<shape-arg> <shape-arg>]# ) |
用於定義裁剪的多邊形區域 |
下面圖示即是用 clip-path: polygon
所畫出來的。
那麼咱們的故障風該如何畫呢?
首先咱們來看看clip-path: inset
不一樣值的狀態。
上面隨手輸入了幾組值,咱們不難發現,不一樣的值所裁剪的區域是不同的,這個時候只要咱們用::before
跟::after
去作這個變更的處理,而後給它們各自加上不一樣的left
值,則會有最上面的效果。
從東亞病夫,到金磚四國,再到國家GDP排名全世界前三;
從開國大典紅旗冉冉升起,到第一科原子彈爆炸成功,到97香港迴歸,再到08年奧運會,再到現在,中國經歷了太多太多。
因此時常在聽到國歌,看到國旗的時候,內心總會百感交集。
提及國旗,咱們不來嘗試下用代碼來畫個五星紅旗嗎?
首先咱們要知道,國旗是五星紅旗,旗面爲紅色,長寬比例爲3:2。左上方綴黃色五角星五顆,四顆小星(其外接圓直徑爲旗高1/10)環拱在一顆大星(其外接圓直徑爲旗高3/10)的右面,並各有一個角尖正對大星的中心點。
通用尺寸有如下五種:
國旗墨線圖以下:
知道這個以後咱們就能夠按照上述的比例去作一畫一個五星紅旗出來,效果以下:
此效果DEMO核心實現靈感來自此文:前端實現旗幟飄動效果系列 (Ⅰ):dom+css實現,有興趣的能夠去看看原文。
因此該如何實現上述紅旗飄飄的功能呢?
首先咱們來看僞代碼
<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("flag.jpg"); background-size: auto 100%; animation: flag ease-in-out infinite; } </style>
<ul id="flag" class="flag"></ul>
<script> 'use strict' const flag = document.querySelector('#flag') const image = new Image() image.src = 'flag.jpg' const flagWidth = 800 const flagHeight = 640 let imgWidth = '' let imgHeight = '' /** * @func * @name 分割圖片 * @param sliceCount 切片數量 * @param amplitude 振幅 * @param period 固定週期個數 * @param duration 一個週期的時長 */ const imgRender = ({ sliceCount = 70, amplitude = 20, period = 1.5, duration = 2, }) => {/* 具體生成紅旗DOM片斷的邏輯 */} 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>
複製代碼
所添加的 imgRender
究竟作了什麼?
若是大家知道什麼是 雪碧圖(CSS Sprite) ,這個應該就好理解了,在 HTTP1 的時代裏, 雪碧圖(CSS Sprite) 是一個很常見的技術概念,因爲譯名的緣由,也有人叫它CSS精靈,是一種CSS圖像合併技術,該方法是將小圖標和背景圖像合併到一張圖片上,而後利用css的背景定位來顯示須要顯示的圖片部分。
CSS雪碧的基本原理是把你的網站上用到的一些圖片整合到一張單獨的圖片中,而後使用CSS background
和 background-position
屬性渲染。
因此 imgRender
就是作了這麼一件事,將紅旗圖片按等分切割出來,而後進行循環,生成 sliceCount
量的DOM節點,而後添加background-position
,這時候的background-position
值是跟循環到的下標有關的,具體邏輯其實能夠按需去改,以後就是動畫屬性的配置了。
具體實現能夠看魚頭的CODEPEN。
Mmmm,本文標題是CSS,其實這裏也不算用了JS,畢竟它在這裏只是做爲一個腳本生成重複的代碼,主要核心仍是雪碧圖 + animation
咱們實現了CSS版的五星紅旗,那麼如今就讓咱們來實現一次SVG版本的。
用SVG去處理一些複雜的圖案是很是輕鬆的,咱們只須要知道路徑,就能夠對它進行操做。
固然咱們該怎麼知道路徑?這可讓咱們的UI設計師從AI中導出SVG,或者去www.iconfont.cn找也能夠,以後咱們就能夠作咱們想作的操做了。
若是咱們要畫上面的紅旗,也很是簡單。
這裏直接上代碼:
<?xml version="1.0" encoding="UTF-8"?>
<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>
複製代碼
從上面咱們不難看出,這個五星紅旗只須要定義一個紅色畫布,一個星星的輪廓,而後use進去以後給定不一樣的位置就能夠了。
效果以下:
「五星紅旗,你是個人驕傲;五星紅旗,我爲你自豪;爲你歡呼,我爲你祝福;你的名字,比我生命更重要;」
寫到這裏的時候,腦子自動響起了紅旗飄飄的旋律。祝願祖國愈來愈強盛,也祝你們國慶節快樂。
若是你、喜歡探討技術,或者對本文有任何的意見或建議,你能夠掃描下方二維碼,關注微信公衆號「 魚頭的Web海洋 」,隨時與魚頭互動。歡迎!衷心但願能夠碰見你。