自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用CSS+JS幫你實(shí)現(xiàn)蘋(píng)果cover flow效果

開(kāi)發(fā) 前端
本文通過(guò)使用CSS+JS幫你實(shí)現(xiàn)蘋(píng)果cover flow效果,有具體代碼和詳細(xì)解釋。

 [[170771]] 

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <title>coverflow-demo</title> 
  6.     <style> 
  7.         div.innerWrapper{ 
  8.             perspective: 300px; 
  9.             width: 600px; 
  10.             height: 300px; 
  11.             margin: 100px auto; 
  12.             display: flex;  
  13.             align-items:flex-start; 
  14.             background-color: #000;  
  15.             overflow: hidden;  
  16.             padding-top: 5%; 
  17.         } 
  18.         div.cover{ 
  19.             height: 50%;  
  20.             flex-grow:1; 
  21.             transition: all .5s ease; 
  22.             background-size: 100% 100%;  
  23.             background-repeat:no-repeat; 
  24.             margin: 0;  
  25.             -webkit-box-reflect:below 5% linear-gradient(transparent, white); 
  26.             border: 1px solid #fff; 
  27.  
  28.         } 
  29.         div.cover:nth-child(1){ 
  30.             background-image: url('covers/computergraphics-album-covers-2014-15.jpg'); 
  31.         } 
  32.         div.cover:nth-child(2){ 
  33.             background-image: url('covers/Funkadelic-Maggot-Brain-album-covers-billboard-1000x1000.jpg'); 
  34.         } 
  35.         div.cover:nth-child(3){ 
  36.             background-image: url('covers/Green-Day-American-Idiot-album-covers-billboard-1000x1000.jpg'); 
  37.         } 
  38.         div.cover:nth-child(4){ 
  39.             background-image: url('covers/insurgency-digital-album-cover-design.jpg'); 
  40.         } 
  41.         div.cover:nth-child(5){ 
  42.             background-image: url('covers/Pink-Floyd-Dark-Side-of-the-Moon-album-covers-billboard-1000x1000.jpg'); 
  43.         } 
  44.         div.cover:nth-child(6){ 
  45.             background-image: url('covers/sonic-quiver-time-and-space1-1000x1000.jpg'); 
  46.         } 
  47.         div.cover:nth-child(7){ 
  48.             background-image: url('covers/tumblr_inline_nydppi1Mp91t7tdyh_500.jpg'); 
  49.         } 
  50.         button[required='required']{ 
  51.             background-color: #000;  
  52.         } 
  53.     </style> 
  54. </head> 
  55. <body> 
  56.     <div class='container'
  57.         <div class="innerWrapper"
  58.             <div></div> 
  59.             <div></div> 
  60.             <div></div> 
  61.             <div></div> 
  62.             <div></div> 
  63.             <div></div> 
  64.             <div></div> 
  65.         </div> 
  66.     </div> 
  67.     <button required='required'>222</button> 
  68.     <script> 
  69.     ;(function(parent){ 
  70.         var cards = parent.querySelectorAll('div'), coverCount = cards.length, middleIndex = (coverCount-1)/2, middleCover = cards[middleIndex], parentWidth = middleCover.parentNode.clientWidth, currentIndex = middleIndex;  
  71.         var maxRotate = 42, stepper = maxRotate/middleIndex, maxZIndex = middleIndex + 1;  
  72.         var rotateReg = /rotateY\((\-?\d{1,3}\.?\d*)deg\)/, translateReg = /translateX\((\-?\d{1,3}\.?\d*)px\)/;  
  73.         // debugger;  
  74.         for(var i = 0; i<coverCount; i++){ 
  75.             var elem = cards[i];  
  76.             elem.classList.add('cover');  
  77.             elem.style.transform = 'translateX(0px) rotateY(' + (maxRotate-(i*stepper).toFixed(0)) + 'deg)';  
  78.             elem.style.flexGrow = 1;  
  79.             if(i<middleIndex){ 
  80.                 elem.style.zIndex = i+1;  
  81.             }else if(i == middleIndex){ 
  82.                 elem.style.zIndex = i+1;  
  83.                 elem.style.flexGrow = 2;  
  84.             }else
  85.                 elem.style.zIndex = coverCount - i;  
  86.             } 
  87.         } 
  88.         function move(direction){ 
  89.             if(currentIndex==(direction=='right'?0:coverCount-1))return;  
  90.             direction=='right'?currentIndex--:currentIndex++;  
  91.             maxZIndex++;  
  92.             [].forEach.call(cards, function(element, index) { 
  93.                 var previousRotate = parseInt(element.style.transform.match(rotateReg)[1]);  
  94.                 var previousTranslate = parseInt(element.style.transform.match(translateReg)[1]); 
  95.                 // translateX + 80 px one right button is clicked 
  96.                 var currentRotate, currentTranslate;  
  97.                 if(direction=='right'){ 
  98.                     currentRotate = previousRotate-stepper;  
  99.                     currentTranslate = previousTranslate+(parentWidth/(coverCount+1));  
  100.                 }else
  101.                     currentRotate = previousRotate+stepper;  
  102.                     currentTranslate = previousTranslate-(parentWidth/(coverCount+1));  
  103.                 } 
  104.                 element.style.transform = 'translateX(' + currentTranslate + 'px) rotateY('+ currentRotate +'deg)' 
  105.                 // element.style.zIndex =  
  106.                 if(index == currentIndex){ 
  107.                     element.style.flexGrow = 2;  
  108.                     element.style.zIndex = maxZIndex;   
  109.                 }else
  110.                     element.style.flexGrow = 1;  
  111.                 } 
  112.             }); 
  113.         } 
  114.         document.addEventListener('keyup'function(e){ 
  115.             if(e.which == 37){ 
  116.                 move('right');  
  117.             }else if(e.which == 39){ 
  118.                 move('left');  
  119.             } 
  120.         }) 
  121.     })(document.querySelector('.innerWrapper'));  
  122.     </script> 
  123. </body> 
  124. </html> 

稍微解釋下這里用到的幾個(gè)知識(shí)點(diǎn):

1. flex-box.

什么是flex-box捏, 它是為了適應(yīng)當(dāng)前設(shè)備屏幕大小不一而提出的一種display方法. 當(dāng)一個(gè)父元素的顯示被設(shè)定為display:flex時(shí), 它內(nèi)部的子元素們會(huì)被平均分配占滿(mǎn)父元素的空間, 并且當(dāng)父元素的尺寸變化時(shí), 子元素的尺寸也會(huì)相應(yīng)變化! 是不是很神奇呢? 不僅如此, 你還可以任意分配子元素們的排列順序, 如果覺(jué)得某個(gè)子元素需要突出顯示, 就可以給這個(gè)子元素以特殊身份, 讓它相比其他子元素大一些, 或者小一些! 由于其的自適應(yīng)特性, flex是移動(dòng)開(kāi)發(fā)的一把利器, 我們先來(lái)看看一個(gè)小應(yīng)用:

設(shè)計(jì)一個(gè)對(duì)話框函數(shù), 當(dāng)傳入一個(gè)回調(diào)函數(shù)時(shí), 只顯示一個(gè)'確定'按鈕, 占100%寬度; 當(dāng)傳入兩個(gè)回調(diào)函數(shù)(確定和取消)時(shí), 分別顯示'確定'和'取消'按鈕, 各占50%寬度, 樣式分別如下:

 怎么實(shí)現(xiàn)呢? 我們當(dāng)然可以用JS來(lái)做, 但是(凡事就怕一個(gè)但是哈哈)! 我們作為有追求的前端, 戰(zhàn)斗在CSS探索的***線, 現(xiàn)在有了如此好用的flex屬性, 為毛不立馬用起來(lái)呢? 說(shuō)走咱就走, 按鈕容器和按鈕本身的CSS如下:

 

 

 


關(guān)鍵是按鈕的width:100%屬性. 有了它, 當(dāng)容器里只有一個(gè)按鈕時(shí), 它的寬度會(huì)拓展為容器的100%寬度; 而當(dāng)容器里有兩個(gè)按鈕時(shí), 按鈕的寬度都為100%, 怎么辦呢? 由于兩個(gè)按鈕勢(shì)均力敵, 它們只好平分秋色, 各占50%的空間了!

 

有的同學(xué)要問(wèn)了: 要是我不想按鈕把空間占滿(mǎn)怎么辦呢? 這時(shí)候, 可以設(shè)定按鈕的寬度各為45%, 然后在父元素上設(shè)置justify-content:center, 意思是兩個(gè)子元素只占了90%的橫向空間, 那怎么分配剩下的10%空間呢? 那就兩邊各分配5%吧! 除此之外, 該屬性的其它值, 可以讓子元素左右對(duì)齊, 更多flexbox的神奇應(yīng)用, 請(qǐng)參考這篇文章~

A Complete Guide to Flexbox

回到我們的例子. 在卡片們沒(méi)有被應(yīng)用transform屬性之前, 它們看起來(lái)是這個(gè)樣子的:

[[170774]]

 七個(gè)元素平均分布, 占據(jù)了父元素的全部橫向空間. 其中中間的元素應(yīng)用了flex-grow:2的屬性, 使得它比其他元素高人一等, 面積是其他元素的兩倍~~

2. transform

其實(shí)有了上一幅圖, 初始頁(yè)面的雛形就已經(jīng)差不多了~現(xiàn)在只需要給父元素設(shè)置視角(關(guān)于視角, 3D變換等內(nèi)容, 請(qǐng)見(jiàn)我的這一篇文章). 為了得到比較明顯3D效果, 設(shè)置了父元素的perspective為較小的值300px, 就相當(dāng)于從距離3D變換平面300px的距離看. perspective的值越大, 相當(dāng)于從越遠(yuǎn)的距離看, 3D效果越不明顯, 平面化效果越強(qiáng)烈~

設(shè)置好了視角, 接下來(lái)該給元素們?cè)O(shè)置3D效果了. ***步很簡(jiǎn)單: 假設(shè)有7個(gè)元素, 沿Y軸***旋轉(zhuǎn)角度為42度, 則0,1,2號(hào)元素分別旋轉(zhuǎn)42, 28, 14度, 3號(hào)元素旋轉(zhuǎn)0度同時(shí)變大2倍,4,5,6號(hào)元素分別旋轉(zhuǎn)-14, -28, -42度. 用一個(gè)簡(jiǎn)單的for循環(huán)就可以完成這項(xiàng)任務(wù), 代碼如下: 

  1. for(var i = 0; i<coverCount; i++){ 
  2.             var elem = cards[i];  
  3.             elem.classList.add('cover');  
  4.             // 設(shè)置元素的translateX為0px, 旋轉(zhuǎn)角度為***旋轉(zhuǎn)角度-目錄值*步進(jìn)值 
  5.             elem.style.transform = 'translateX(0px) rotateY(' + (maxRotate-(i*stepper).toFixed(0)) + 'deg)';  
  6.             elem.style.flexGrow = 1;  
  7.             // 設(shè)置元素的z-index以區(qū)分前后順序, 并將中間元素設(shè)置大一些 
  8.             if(i<middleIndex){ 
  9.                 elem.style.zIndex = i+1;  
  10.             }else if(i == middleIndex){ 
  11.                 elem.style.zIndex = i+1;  
  12.                 elem.style.flexGrow = 2;  
  13.             }else
  14.                 elem.style.zIndex = coverCount - i;  
  15.             } 
  16.         }  

初始化完成后效果圖如下:

 

[[170775]] 

此時(shí)每個(gè)卡片的translateX為0, 這個(gè)值要預(yù)先寫(xiě)好, 才能通過(guò)改變?cè)撝祦?lái)實(shí)現(xiàn)卡片的左右移動(dòng)效果; rotateY的值分別為42, 28, 14, 0, -14, -28, 42度; flex-grow(相對(duì)于其它子元素的大小)分別為1, 1, 1, 2, 1, 1, 1

3.-webkit-box-reflect

那么漂亮的倒影是怎么實(shí)現(xiàn)的呢? 哈哈其實(shí)一行CSS就能搞定, 那就是強(qiáng)大的-webkit-box-reflect, 值為below 5% linear-gradient(transparent, white). 相信聰明的小伙伴看到這里已經(jīng)明白了大概了, 為了避免誤解, 稍稍再解釋一下~below是倒影在盒子下方, 5%表示offset, 和盒子的距離是盒子寬度的5%, linear-gradient(transparent, white)指的是倒影的顏色, 從透明到完全不透明. 漸變語(yǔ)法的顏色在這里起作用的只有透明度, 白色的顏色是不會(huì)顯出來(lái)的~到這里, 我們用的大部分都是CSS, 效果圖如下:

[[170776]] 

然而靜態(tài)的展示是不夠的, 我們的目標(biāo)是! 要讓它動(dòng)起來(lái)! 來(lái)回左右動(dòng)! 到這里CSS已經(jīng)無(wú)能為力, 改JS閃亮登場(chǎng)的時(shí)候了!~

4.JS控制

控制左右移動(dòng)的函數(shù)如下, 接受一個(gè)參數(shù)left或者right表示要移動(dòng)的方向~

  1. // 定義提取旋轉(zhuǎn)角度和translateX值的正則, 例如 -> $0.style.transform.match(/rotateY\((\-?\d{1,3}\.?\d*)deg\)/) <- ["rotateY(14deg)""14"
  2.        var rotateReg = /rotateY\((\-?\d{1,3}\.?\d*)deg\)/, translateReg = /translateX\((\-?\d{1,3}\.?\d*)px\)/;  
  3.        function move(direction){ 
  4.            // 當(dāng)前值為0或者當(dāng)前值為卡片數(shù)目時(shí), 返回 
  5.            if(currentIndex==(direction=='right'?0:coverCount-1))return;  
  6.            // 當(dāng)前值自增或者自減 
  7.            direction=='right'?currentIndex--:currentIndex++;  
  8.            // ***Z-index自增 
  9.            maxZIndex++;  
  10.            [].forEach.call(cards, function(element, index) { 
  11.                // 提取變換之前的旋轉(zhuǎn)角度 
  12.                var previousRotate = parseInt(element.style.transform.match(rotateReg)[1]);  
  13.                // 提取變換之前的translateX 
  14.                var previousTranslate = parseInt(element.style.transform.match(translateReg)[1]); 
  15.                var currentRotate, currentTranslate;  
  16.                if(direction=='right'){ 
  17.                    // 計(jì)算rotatey的值 
  18.                    currentRotate = previousRotate-stepper;  
  19.                    // 計(jì)算平移的距離 
  20.                    currentTranslate = previousTranslate+(parentWidth/(coverCount+1));  
  21.                }else
  22.                    currentRotate = previousRotate+stepper;  
  23.                    currentTranslate = previousTranslate-(parentWidth/(coverCount+1));  
  24.                } 
  25.                // 寫(xiě)入元素屬性 
  26.                element.style.transform = 'translateX(' + currentTranslate + 'px) rotateY('+ currentRotate +'deg)' 
  27.                // element.style.zIndex =  
  28.                if(index == currentIndex){ 
  29.                    element.style.flexGrow = 2;  
  30.                    // 不斷寫(xiě)入maxZIndex, 確保翻過(guò)的元素始終在最前面 
  31.                    element.style.zIndex = maxZIndex;   
  32.                }else
  33.                    element.style.flexGrow = 1;  
  34.                } 
  35.            }); 
  36.        }  

再給按鈕或者鍵盤(pán)增加事件監(jiān)聽(tīng), 這樣就完成啦!

總結(jié)一下: 

  1. flex-box可以讓你的元素變得flex, 輕松實(shí)現(xiàn)根據(jù)元素?cái)?shù)目重載! 各種屬性讓你任意操作flex元素!
  2. transform實(shí)現(xiàn)漂亮的3D變換效果!
  3. -webkit-box-reflect實(shí)現(xiàn)更加酷炫的倒影效果!
  4. ***JS來(lái)補(bǔ)刀, 讓我們的卡片們動(dòng)起來(lái)!
責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2021-05-19 06:07:21

CSS 斜線效果技巧

2010-09-08 12:49:16

CSS斜線

2022-12-12 11:11:05

2010-09-14 12:58:41

DIV+CSS圓角

2010-09-07 14:53:45

Chroma屬性CSS

2021-12-27 07:45:30

CSS 技巧煙霧效果

2021-01-19 12:16:10

CSS前端UI

2010-09-09 11:16:06

CSS交互

2010-09-09 12:49:58

鼠標(biāo)懸停tip效果CSS

2010-09-14 09:18:28

DIVCSS

2014-04-25 11:02:25

虛擬化虛擬化技術(shù)

2012-01-10 14:59:42

jQuery

2022-07-07 08:43:05

HoudiniAPICSS

2022-03-17 19:29:04

CSS切角自適應(yīng)

2023-05-22 09:10:53

CSSloading 效

2010-09-13 14:09:35

CSS文字

2024-07-31 20:38:18

2021-09-28 08:26:06

CSS 技巧文字鏤空波浪

2022-06-15 22:15:47

CSS視覺(jué)還原

2023-07-18 15:49:22

HTMLCSS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)