一步一步來製作CSS3 3D旋轉相冊

  • body 內添加如下代碼,結構:舞臺,容器,圖片內容
<div class="stage-area">
    <div class="container">
        <a href="#"><img src="1.jpeg" /></a>
        <a href="#"><img src="2.jpeg" /></a>
        <a href="#"><img src="3.jpeg" /></a>
        <a href="#"><img src="4.jpeg" /></a>
        <a href="#"><img src="5.jpeg" /></a>
        <a href="#"><img src="6.jpeg" /></a>
        <a href="#"><img src="7.jpeg" /></a>
        <a href="#"><img src="8.jpeg" /></a>
        <a href="#"><img src="9.jpeg" /></a>
    </div>
</div>
  • 設置舞臺透視距離。設置容器3D透視和內容寬度。設置圖片最大伸縮到自身寬度,這裏說下 max-width:100% 與 width:100% 的區別,前者圖片最大伸展到圖片實際的寬度,後者伸展最大伸展到父級元素的寬度,也就是說如果父級的寬度超過圖片的寬度後者會拉伸超過圖片實際寬度導致模糊失真,這是響應式或做自適應時默認要設置的屬性。
.stage-area {
    perspective: 800px;
}
.container {
    transform-style: preserve-3d;
    width: 160px;
}
img {
    max-width: 100%;
}
  • 設置容器相對於窗口水平垂直居中,圖片疊加在一起的效果。利用定位和負的margin來水平垂直居中確定寬度的塊級元素。設置圖片絕對定位使得圖片相互疊加,避免後續導致的DNA螺旋效果,也方便查看垂直居中效果。
.container {
    ...
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -80px;
    margin-left: -80px;
}
img {
    ...
    position: absolute;
}
  • 查看並未達到預期的垂直居中效果,圖片也被裁剪。查看頁面元素髮現body高度爲0,這是由於內容設置了絕對定位脫離了普通流而且塊級元素的默認性質是寬度儘量寬撐滿,高度儘量窄由內容高度決定。設置如下:
html, body {
    height: 100%;
}
.stage-area {
    ...
    min-height: 100%;
}
  • 設置圖片旋轉角度,此時發現有種翻書效果。
.container a:nth-child(1) img {
    transform: rotateY(0deg);
}
.container a:nth-child(2) img {
    transform: rotateY(40deg);
}
.container a:nth-child(3) img {
    transform: rotateY(80deg);
}
.container a:nth-child(4) img {
    transform: rotateY(120deg);
}
.container a:nth-child(5) img {
    transform: rotateY(160deg);
}
.container a:nth-child(6) img {
    transform: rotateY(200deg);
}
.container a:nth-child(7) img {
    transform: rotateY(240deg);
}
.container a:nth-child(8) img {
    transform: rotateY(280deg);
}
.container a:nth-child(9) img {
    transform: rotateY(320deg);
}

這裏寫圖片描述
- 設置圖片3D Z軸距離


.container a:nth-child(1) img {
    transform: rotateY(0deg) translateZ(250px);
}
.container a:nth-child(2) img {
    transform: rotateY(40deg) translateZ(250px);
}
...

這裏寫圖片描述
- 好了,一個3D立體的旋轉相冊出現了,如果感覺圖片有點太高,有種仰視的感覺,可以設置perspective-origin,讓透視點高一點,產生俯瞰的效果。

這裏寫圖片描述

.stage-area {
    ...
    perspective-origin: center 30%;
}
  • 去掉圖片定位,可以看下DNA螺旋效果,後面動態旋轉的時候可以倒騰看看。
    這裏寫圖片描述

  • 接下來,讓圖片動起來,也就是繞着3D視圖的Y軸旋轉,這就得靠 @keyframes 設置關鍵幀和 animation 了。

屬性 描述
@keyframes 定義關鍵幀
animation 所有動畫屬性的簡寫屬性,除了 animation-play-state 屬性。
animation-name @keyframes 定義的動畫名稱。
animation-duration 設置完成動畫所花費的時間。默認值是 0,意味着沒有動畫效果。
animation-timing-function 使用名爲三次貝塞爾(Cubic Bezier)函數的數學函數,來生成速度曲線。能夠在該函數中使用自己的值。
animation-delay 設置動畫開始前等待的時間,以秒或毫秒計。默認值是 0。
animation-iteration-count 設置動畫被播放的次數。
animation-direction 設置動畫是否在下一週期逆向地播放,單數次正向,偶數次逆向。
animation-fill-mode 設置動畫在播放之前或之後,其動畫效果是否可見。
animation-play-state 設置動畫正在運行或暫停。
@keyframes rotating {
    0% {
        transform: rotateY(0deg);
    }
    100% {
        transform: rotateY(360deg);
    }
}
.container {
    ...
    /*animation: rotating 10s linear 3s infinite alternate forwards;*/
    animation-name: rotating;
    animation-duration: 10s;
    animation-timing-function: linear;
    /*animation-delay: 3s;*/
    animation-iteration-count: infinite;
    /*animation-direction: alternate;*/
    /*animation-fill-mode: forwards;*/
}

這裏寫圖片描述

  • DNA螺旋效果
    這裏寫圖片描述

  • 如果我們想鼠標移動到圖片上,就暫停動畫該怎麼辦呢,設置 animation-play-state ,同時爲了美觀,給圖片加個半透明小邊框。

.container:hover {
    animation-play-state: paused;
}
.container img {
    border: 3px solid rgba(255, 255, 255, .5);
}
  • 還想更進一步,實現點擊圖片大圖顯示效果,這時可以利用 position + z-index + :target 僞類來實現。修改頁面元素:
<img id="t2" src="2.jpeg" />
<img id="t3" src="3.jpeg" />
<img id="t4" src="4.jpeg" />
<img id="t5" src="5.jpeg" />
<img id="t6" src="6.jpeg" />
<img id="t7" src="7.jpeg" />
<img id="t8" src="8.jpeg" />
<img id="t9" src="9.jpeg" />
<img id="t1" src="1.jpeg" />
<div class="stage-area">
    <div class="container">
        <a href="#t1"><img src="1.jpeg" /></a>
        <a href="#t2"><img src="2.jpeg" /></a>
        <a href="#t3"><img src="3.jpeg" /></a>
        <a href="#t4"><img src="4.jpeg" /></a>
        <a href="#t5"><img src="5.jpeg" /></a>
        <a href="#t6"><img src="6.jpeg" /></a>
        <a href="#t7"><img src="7.jpeg" /></a>
        <a href="#t8"><img src="8.jpeg" /></a>
        <a href="#t9"><img src="9.jpeg" /></a>
    </div>
</div>
  • 此時發現一個有意思的現象,圖片外沿出現縫隙,我們知道谷歌瀏覽器默認給 body 加了 margin ,img 設置了絕對定位但沒設置top,left屬性,給 body 添加 border 和 padding 發現圖片定位於 body 的 content 區域邊界,如果設置圖片top: 0; left: 0;發現此時圖片與瀏覽器窗口邊界對齊。可以設置 body margin: 0 或 圖片定位top: 0; left: 0;來消除縫隙。
    這裏寫圖片描述
  • 我們要如何實現點擊圖片切換後面的大圖呢?原理:相冊圖片有 a 元素包裹,href 屬性對應大圖的 id,此時點擊相冊圖片可以觸發大圖 :target 的僞類樣式,由於圖片都設置了 position 定位,可以設置圖片的 z-index 來實現層級升降。之前定位圖片是按順序疊加的,有個小技巧,可以把首次要展示的圖片放下面的位置。如下:降低非 :target 的圖片的層級。
body > img:not(:target) {
    z-index: -1;
}

這裏寫圖片描述

  • 至此大功告成,但也在過程中發現了不少問題,比如剛開始是嘗試在 提高 .container 層級降低圖片層級,但失敗了。查詢資料,可能是在 .stage-area 設置了 perspective 屬性產生了新的層級層疊上下文,導致 .container 和大圖不在一個層級層疊上下文中,導致 z-index 失敗,去掉 perspective 相關屬性測試發現正常。
.container {
    ...
    z-index: 3;
}
body > img:not(:target) {
    z-index: 1;
}
body > img:target {
    z-index: 2;
}
  • 完整代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>旋轉相冊</title>
    <style>
        @keyframes rotating {
            0% {
                transform: rotateY(0deg);
            }
            100% {
                transform: rotateY(360deg);
            }
        }
        html, body {
            height: 100%;
            margin: 0;
        }
        .stage-area {
            perspective: 800px;
            min-height: 100%;
            perspective-origin: center 30%;
        }
        .container {
            transform-style: preserve-3d;
            width: 160px;
            position: absolute;
            /*z-index: 3;*/
            top: 50%;
            left: 50%;
            margin-top: -80px;
            margin-left: -80px;
            /*animation: rotating 10s linear 3s infinite alternate forwards;*/
            animation-name: rotating;
            animation-duration: 10s;
            animation-timing-function: linear;
            /*animation-delay: 3s;*/
            animation-iteration-count: infinite;
            /*animation-direction: alternate;*/
            /*animation-fill-mode: forwards;*/
        }
        .container:hover {
            animation-play-state: paused;
        }
        .container img {
            border: 3px solid rgba(255, 255, 255, .5);
        }
        img {
            max-width: 100%;
            position: absolute;
        }
        .container a:nth-child(1) img {
            transform: rotateY(0deg) translateZ(250px);
        }
        .container a:nth-child(2) img {
            transform: rotateY(40deg) translateZ(250px);
        }
        .container a:nth-child(3) img {
            transform: rotateY(80deg) translateZ(250px);
        }
        .container a:nth-child(4) img {
            transform: rotateY(120deg) translateZ(250px);
        }
        .container a:nth-child(5) img {
            transform: rotateY(160deg) translateZ(250px);
        }
        .container a:nth-child(6) img {
            transform: rotateY(200deg) translateZ(250px);
        }
        .container a:nth-child(7) img {
            transform: rotateY(240deg) translateZ(250px);
        }
        .container a:nth-child(8) img {
            transform: rotateY(280deg) translateZ(250px);
        }
        .container a:nth-child(9) img {
            transform: rotateY(320deg) translateZ(250px);
        }
        body > img:not(:target) {
            z-index: -1;
        }
        /*body > img:not(:target) {
             z-index: 1;
         }
        body > img:target {
            z-index: 2;
        }*/
    </style>
</head>
<body>
<img id="t2" src="2.jpeg" />
<img id="t3" src="3.jpeg" />
<img id="t4" src="4.jpeg" />
<img id="t5" src="5.jpeg" />
<img id="t6" src="6.jpeg" />
<img id="t7" src="7.jpeg" />
<img id="t8" src="8.jpeg" />
<img id="t9" src="9.jpeg" />
<img id="t1" src="1.jpeg" />
<div class="stage-area">
    <div class="container">
        <a href="#t1"><img src="1.jpeg" /></a>
        <a href="#t2"><img src="2.jpeg" /></a>
        <a href="#t3"><img src="3.jpeg" /></a>
        <a href="#t4"><img src="4.jpeg" /></a>
        <a href="#t5"><img src="5.jpeg" /></a>
        <a href="#t6"><img src="6.jpeg" /></a>
        <a href="#t7"><img src="7.jpeg" /></a>
        <a href="#t8"><img src="8.jpeg" /></a>
        <a href="#t9"><img src="9.jpeg" /></a>
    </div>
</div>
</body>
</html>

參考資料:
1、十天精通CSS3
https://www.imooc.com/code/1882
2、深入理解CSS中的層疊上下文和層疊順序
https://www.zhangxinxu.com/wordpress/2012/09/css3-3d-transform-perspective-animate-transition/
3、理解 CSS z-index
https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
4、CSS3 動畫屬性(Animation)
http://www.w3school.com.cn/cssref/index.asp#animation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章