前已經(jīng)說(shuō)過(guò),本人是即將畢業(yè)的學(xué)生。前幾天的HTML5實(shí)訓(xùn)學(xué)到了很多有趣的東西,其中CSS3做的東西很棒。由于時(shí)間關(guān)系,老師并沒(méi)有講解多少,只是做了幾個(gè)簡(jiǎn)單的案例。其中有利用transform實(shí)現(xiàn)文字或圖像的旋轉(zhuǎn),縮放,傾斜,移動(dòng)這四種類(lèi)型的變形處理;有使用transition功能通過(guò)將元素的某個(gè)屬性從一個(gè)屬性在指定的時(shí)間內(nèi)平滑過(guò)渡到另一個(gè)屬性值來(lái)實(shí)現(xiàn)動(dòng)畫(huà);還有animations通過(guò)定義多個(gè)關(guān)鍵幀以及定義每個(gè)關(guān)鍵幀中元素的屬性值來(lái)實(shí)現(xiàn)更為復(fù)雜的動(dòng)畫(huà)效果。
我自己還沒(méi)有系統(tǒng)的學(xué)習(xí)CSS3,只是稍有了解。CSS3新增了很多美觀的樣式,不斷豐富頁(yè)面內(nèi)容。我選擇主攻前端正是因?yàn)橄矚g將用戶(hù)體驗(yàn)盡可能做到最佳,當(dāng)然也少不了CSS3。今天先來(lái)分享一下兩個(gè)使用CSS3做出的炫酷小動(dòng)畫(huà)吧,都是從老師那里學(xué)到的。
第一個(gè)先來(lái)大風(fēng)車(chē)吧,說(shuō)到大風(fēng)車(chē)我第一時(shí)間想到了“大風(fēng)車(chē)吱呀吱扭扭地轉(zhuǎn)”這句詞,嘿嘿。進(jìn)入正題,首先將靜態(tài)頁(yè)面搭建起來(lái),這個(gè)就比較簡(jiǎn)單啦。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>大風(fēng)車(chē)</title>
<style type="text/css">
.wrap{
width: 400px;
height: 400px;
position: relative;
}
.wrap div{
width: 200px;
height: 200px;
position: absolute;
}
.box1{
background: linear-gradient(to top,#dc143c 50%,rgba(0,0,0,0) 50%);
top:100px;
border-radius: 0 0 100px 100px;
}
.box2{
background: linear-gradient(to bottom,#ff4500 50%,rgba(0,0,0,0) 50%);
top:100px;
right: 0;
border-radius: 100px 100px 0 0;
}
.box3{
background: linear-gradient(to right,#00ced1 50%,rgba(0,0,0,0) 50%);
left:100px;
border-radius:100px 0 0 100px;
}
.box4{
background: linear-gradient(to left,pink 50%,rgba(0,0,0,0) 50%);
left:100px;
bottom: 0;
border-radius:0 100px 100px 0;
}
.gunzi{
width: 10px;
height: 300px;
position: absolute;
top:208px;
left:204px;
background:black;
z-index: -1;
}
</style>
</head>
<body>
<div class="wrap">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
</div>
<div class="gunzi"></div>
</body>
</html>
先來(lái)看下效果,如下:
接下來(lái)在<style></style>標(biāo)簽中加入:
@keyframes rotate{
from{transform: rotate(0deg);}
to{transform: rotate(360deg);}
}
.wrap{
animation:rotate 2s linear infinite;
}
使用@keyframes規(guī)則定義關(guān)鍵幀創(chuàng)建動(dòng)畫(huà)。效果如下:
大風(fēng)車(chē)到這里就結(jié)束啦,最后再來(lái)一個(gè)3D立方體。
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
body{-webkit-perspective:1500px;
}
.div{
-webkit-transform-style:preserve-3d;
width:200px;height:200px;
margin:100px auto;
position:relative;
-webkit-transition:-webkit-transform 2s ease 0s;
}
p{margin:0;
padding:0;width:200px;
height:200px;position:absolute;
opacity:0.5;}
p:nth-of-type(1){background-color:#00b38b;
-webkit-transform:translateZ(100px); opacity:1;
}
p:nth-of-type(2){background-color:#ff4500;
-webkit-transform:rotateX(90deg) translateZ(100px);
}
p:nth-of-type(3){background-color:honeydew;-webkit-transform:rotateX(90deg) translateZ(-100px)}
p:nth-of-type(4){background-color:red;-webkit-transform:rotateY(90deg) translateZ(100px)}
p:nth-of-type(5){background-color:#00bfff;-webkit-transform:rotateY(90deg) translateZ(-100px)}
p:nth-of-type(6){background-color:#ff1493;-webkit-transform:rotateY(90deg) translateZ(-100px)}
.div:hover{
-webkit-transform:rotateX(45deg) rotateY(45deg);
}
</style>
</head>
<body>
<div class="div">
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
</div>
</body>
</html>
上面使用了perspective 屬性定義 3D元素距視圖的距離。完成之后的效果如下:
以上就是今天的CSS3小動(dòng)畫(huà)全部源代碼以及效果,剛剛接觸,純屬娛樂(lè),不喜勿噴,歡迎大家提出意見(jiàn)~
言:
這次項(xiàng)目用到了一些自定義的數(shù)據(jù)可視化組件,我把我做的部分抽出來(lái)幾個(gè)典型做個(gè)匯總。
分為如下:
星球環(huán)繞旋轉(zhuǎn)圖
效果展示:
有些圖片(例如上面這個(gè) jpg 動(dòng)圖)太大,進(jìn)行了一定程度的壓縮,有點(diǎn)模糊(^_^)。
我的碎碎念(*^3^): 之所以出現(xiàn)兩個(gè)版本的原因:本來(lái)用 svg 實(shí)現(xiàn)了一版,結(jié)果后來(lái)我這個(gè)星球的 svg 和同事的其他動(dòng)畫(huà) svg 沖突了(?????????),發(fā)生了巨大改變,本身 svg 又臭又長(zhǎng),改的太累,干脆用 css3d 重新畫(huà)一個(gè)了( ′▽?zhuān)?。
步驟:
//舉例一個(gè)星球的動(dòng)畫(huà) <animateMotion dur="6s" begin="0" repeatCount="indefinite"> <mpath xlinkHref="#Path-12" /> //軌跡動(dòng)畫(huà) </animateMotion> <animateTransform //自身動(dòng)畫(huà),靠近我的時(shí)候星球變大,遠(yuǎn)離我時(shí)變小 id="first" attributeType="XML" attributeName="transform" type="scale" begin="0;second.end " from="1" to="0.512" dur="3s" fill="freeze" /> <animateTransform id="second" attributeType="XML" attributeName="transform" type="scale" begin="first.end" from="0.512" to="1" dur="3s" fill="freeze" /> 作者:溯朝 鏈接:https://juejin.im/post/5b690a66f265da0f820254bd 來(lái)源:掘金 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
參考鏈接:https://www.jianshu.com/p/2b85973ad1ed
<!-- 軌道 --> <div class="orbit"> <!-- 行星 --> <div class="planet planet1"> <!-- <span class="name"></span> --> </div> <div class="planet planet2"> <!-- <span class="name"></span> --> </div> </div>
.orbit { //軌道旋轉(zhuǎn),公轉(zhuǎn) border: 5px solid red; transform-style: preserve-3d; padding: 65px; width: 500px; height: 500px; border-radius: 50%; animation: orbit-rotate 10s linear infinite; } .planet { //星球自轉(zhuǎn) width: 50px; height: 50px; background: url('../../img/ball1.png') no-repeat; background-size: 100% 100%; border-radius: 50%; animation: self-rotate 10s linear infinite; } // (1)rotateX 是為了讓整個(gè)面傾斜,translateZ是為了防止橢圓(border)因?yàn)閮A斜發(fā)生鋸齒, // (2)停頓效果的產(chǎn)生,其實(shí)我是走了野路子的。五個(gè)球,根據(jù)360/5=72,寫(xiě)了五個(gè)不同的關(guān)于orbit的class, // 0 + 72,....360依次增加72,直到360,利用setimeout每隔4秒,按順序切換一個(gè)class @keyframes orbit-rotate { 0% { transform: rotateX(70deg) rotateZ(0deg) translateZ(0); } 100% { transform: rotateX(70deg) rotateZ(-360deg) translateZ(0); } } @keyframes self-rotate { 0% { transform: rotateX(-90deg) rotateY(360deg) rotateZ(0deg); } 100% { transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg); } } .planet1 { //確定星球開(kāi)始位置 position: absolute; top: 65px; right: 65px; } .planet2 { //確定星球開(kāi)始位置 position: absolute; bottom: 65px; right: 65px; }
?───O(≧?≦)O────?可愛(ài)的分割線(xiàn)?───O(≧?≦)O────?
地圖
我的碎碎念(*^3^): 奇葩的需求(?o?;;, 因?yàn)榧追秸J(rèn)為百度地圖等位置不準(zhǔn)確,不準(zhǔn)使用百度地圖和高德地圖的api,又不滿(mǎn)意天地圖的樣式,所以我們采用的方案是ui畫(huà)地圖,導(dǎo)出svg,再讓前端根據(jù)svg做各種效果展示。
步驟:
地圖文件如下:index.js主文件包含懸浮事件,index.less樣式文件,mapStyle.js存放背景地圖,pathStyle.js數(shù)組格式存放代表地圖上小塊的路徑
代碼如下:
根據(jù)接口給的數(shù)據(jù),按照五個(gè)色系分別給不同的path填充(fill)不同的顏色
const colorMap=[ 'rgba(89, 126, 247, 0.8)', 'rgba(0, 121, 254, 0.8)', 'rgba(0, 121, 254, 0.8)', 'rgba(38, 168, 254, 0.8)', 'rgba(192, 228, 253, 0.8)', ];
render 代碼如下:
?───O(≧?≦)O────?可愛(ài)的分割線(xiàn)?───O(≧?≦)O────?
二維餅圖(風(fēng)車(chē)圖)
效果展示:
我的碎碎念(*^3^):因?yàn)?echarts 的餅圖都是一個(gè)參數(shù)緯度的餅圖,而這次ui要求兩個(gè)參數(shù)緯度的餅圖,只能自己畫(huà)了(′;ω;`)。因?yàn)橹坝?canvas 畫(huà)過(guò)餅圖,本來(lái)以為還是簡(jiǎn)單的,結(jié)果甲方爸爸看了成果,說(shuō)要加自定義懸浮事件(剛開(kāi)始 prd 沒(méi)有的),廢了3天畫(huà)了一個(gè)夠用版的。
步驟:
option.push=[{ color: color[i], //餅圖塊顏色 radius: item.revenueTaxAvg, //餅圖塊半徑 name: item.domainName, // 餅圖塊名稱(chēng) angle: item.companyCnt, //餅圖塊角度 }];
進(jìn)行碰撞檢測(cè),判斷鼠標(biāo)懸浮是落在哪個(gè)弧度的餅圖塊之間,如果不再餅圖塊里面懸浮樣式消失。
數(shù)學(xué)里主要判斷邏輯如下:
//使用勾股定理計(jì)算這個(gè)點(diǎn)與圓心之間的距離 distanceFromCenter=Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)) //α(弧度)=L (弧長(zhǎng))/ r(半徑),但是弧長(zhǎng),我求不出來(lái)。 (點(diǎn)到圓心的直線(xiàn)的角度)的范圍我主要使用sin(x),如下方法。 判斷不同區(qū)間的sin(x)值大小,推斷出懸浮區(qū)域所在的值是什么。
?───O(≧?≦)O────?可愛(ài)的分割線(xiàn)?───O(≧?≦)O────?
三棱錐
效果展示:
步驟:
主要原理:兩個(gè)三角形 + 一個(gè)園=三棱錐
canvas.width=canvas.offsetWidth; //防止圖片變形 canvas.height=canvas.offsetHeight; ctx.clearRect(0, 0, canvas.width, canvas.height); 清除畫(huà)布 const { height }=canvas; // 計(jì)算等邊三角形的高 //如下圖,第一個(gè)三角形 A-B-C ctx.moveTo(100, 0); // 從A(100,0)開(kāi)始 ctx.lineTo(0, height); // 從A(100,0)開(kāi)始,畫(huà)到B (0,height)結(jié)束 ctx.lineTo(144, height); // B(0,height)-C(144, height) //第二個(gè)三角形 A-C-D ctx.moveTo(100, 0); // 從A(100,0)開(kāi)始 ctx.lineTo(143, height); // A-C ctx.lineTo(210, height); // C-D //第三個(gè)畫(huà)圓 ctx.arc(100, 23 , 23, 0, Math.PI * 2, false); // 畫(huà)圓 <canvas id={`pyramid${id}`} height={itemHeight} /> //計(jì)算itemHeight
對(duì)數(shù)增長(zhǎng)--三棱錐高度(itemHeight)計(jì)算:
假設(shè)輸入 data=[0, 1, 2, 3, 4, 5],x為其中任意值; maxHeight 為最大高度; 輸出 itemHeight(0 <=itemHeight< maxHeight),成對(duì)數(shù)增長(zhǎng) //求最大值 const max=MAX(data) //排除 x===0 的情況 因?yàn)閘ogmax(max)=1,且x > 0 由上圖可得 0 < logmax(x)< 1 所以 0 < logmax(x) * maxHeight < maxHeight 可知 logmax(x) * maxHeight 成對(duì)數(shù)變化 又因?yàn)閘ogmax(x)=loge(x) / loge(max) //寫(xiě)成代碼為 const max=data.reduce((a, b)=> { return a > b ? a : b; }, 0); itemHeight=x===0 ? 0 : Math.log(x) / Math.log(max) * maxHeight
==/* 注意 */==
y 軸計(jì)算采用指數(shù)增長(zhǎng),因?yàn)槿我?max 的 0 次方=1, 所以單獨(dú)判斷 i <=0的情況
i > 0 ? Math.round(max ** (i * 0.25)) : 0
長(zhǎng)方體
效果展示:
步驟:
html
<div id="cube"> <figure class="front">1</figure> <figure class="back">2</figure> <figure class="right">3</figure> <figure class="left">4</figure> <figure class="top">5</figure> <figure class="bottom">6</figure> </div>
css
#box.show-front { transform: translateZ( -50px ) rotateY( 0deg ); } #box.show-back { transform: translateZ( -50px ) rotateX( -180deg ); } #box.show-right { transform: translateZ( -150px ) rotateY( -90deg ); } #box.show-left { transform: translateZ( -150px ) rotateY( 90deg ); } #box.show-top { transform: translateZ( -100px ) rotateX( -90deg ); } #box.show-bottom { transform: translateZ( -100px ) rotateX( 90deg ); }
增量增長(zhǎng)--長(zhǎng)方形高度(itemHeight)計(jì)算:
//求數(shù)據(jù)的和 const sum=data.reduce((a, b)=> { return a + b; }, 0); itemHeight=x <=min ? min : min + (max-min) * x /sum;
?───O(≧?≦)O────?可愛(ài)的分割線(xiàn)?───O(≧?≦)O────?
總結(jié)
我第一次寫(xiě)這么多字的總結(jié)技術(shù)的文章,排版有點(diǎn)亂,(╯°□°)╯︵ ┻━┻。大部分的內(nèi)容其實(shí)很簡(jiǎn)單,用到的基本上是初中、高中里面最基礎(chǔ)的數(shù)學(xué)(其實(shí)難了,我也不會(huì)了φ(??)。
厚著臉皮說(shuō),我可能文字功底不咋地,但是每個(gè)例子的中心思想應(yīng)該都表達(dá)了。
最后的最后,看在我第一次寫(xiě)了這么多字的份上,給個(gè)贊唄(///▽///)。
者:lulu_up
轉(zhuǎn)發(fā)鏈接:https://segmentfault.com/u/lulu_up
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。