天天看點

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

3D翻轉盒子圖檔展示特效

首先展示一下完成的效果,這個demo最難的部分在于滑鼠進入不同的邊,要自動判斷方向,這個問題在後面會有詳細的解決辦法!

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

主要程式設計思想:樣式與行為相分割

第一步:建構html結構

在一個容器中,生成六個小盒子,這裡我使用了 ul li 的方式 在每一個li中 有一個 pic-area 用來包裹圖檔和文字,我這裡使用了彈性盒子布局的方式,實作了示範的布局,其他方式也都可以,然後通過把文字區域定位,與圖檔區重疊,為後續建構立方體做準備,為了看得清楚,我增加了一點點透明度,後期會删掉

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

一部分html代碼如下:

<div class="wrapper">
        <ul>
            <li>
                <div class="pic-area">
                    <img src="./tq.jpg" alt="">
                    <p>Lorem, ipsum dolor.</p>
                </div>
            </li>
         <!--  此處是六個li 其他的省略不寫了 -->
        </ul>
    </div>
           

以下是css代碼,僅供參考:

*{
    margin: 0;
    padding: 0;
    list-style: none;
}
.wrapper{
    width: 1000px;
    height: 650px;
    border: 1px solid #424242;
    margin: 20px auto;
}
ul{
    width: 100%;
    height: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
ul>li{
    width: 300px;
    height: 300px;
    margin: 10px;
}
.pic-area{
    position: relative;
    transform-style: preserve-3d;
    
}
.pic-area img{
    opacity: 0.4;
}
.pic-area p{
    position: absolute;
    top: 0;
    left: 0;
    width: 300px;
    height: 300px;
    background-color: #424242;
    font-size: 30px;
    line-height: 300px;
    text-align: center;
    transform: translate3d(0 ,0 ,-1px);
}
           

第二步:如何實作立方體

首先要注意的是:雖然看起來是一個六面立方體,但是我隻用了兩個面,我定義了四個方向的類名,滑鼠在不同的方向移入,我添加對應的類名即可

我們要翻轉的是圖檔後面的文字部分,注意文字部分在翻轉90度的時候,他翻轉的中心是在中心的位置,如下圖所示,翻轉之後還要往上,往裡平移

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

但是我采用了一種簡單的方法,首先平移,然後改變翻轉源點,最後直接翻轉

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

css代碼如下:

.in-top .pic-area .hide{
    transform-origin: bottom;
    transform: translate3d(0,-100%,0) rotate3d(1,0,0,90deg);
}
           

值得注意的是 不要忘記如下代碼,一個是景深屬性 ,一個是開啟3D模式

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

現在應該有一個這樣的效果

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

同理:四個面四個類名

.in-top .pic-area .hide{
    transform-origin: bottom;
    transform: translate3d(0,-100%,0) rotate3d(1,0,0,90deg);
}
.in-bottom .pic-area .hide{
    transform-origin: top;
    transform: translate3d(0,100%,0) rotate3d(-1,0,0,90deg);
}
.in-left .pic-area .hide{
    transform-origin: right;
    transform: translate3d(-100%,0,0) rotate3d(0,1,0,-90deg);
}
.in-right .pic-area .hide{
    transform-origin: left;
    transform: translate3d(100%,0,0) rotate3d(0,1,0,90deg);
}
           

設定在不同的li上看一下現在的效果 如圖所示:

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

接下來這是轉動效果,這裡主要通過css3的animate效果來實作

首先改變圖檔區的轉動源,不然會有一個突出去的效果 ,150px是盒子寬高的一半,讓盒子的轉動軸固定在盒子中心

.pic-area{
    position: relative;
    transform-style: preserve-3d;
    transform-origin: 50% 50% -150px;
    animation: 0.3s ease-out forwards;
}
           

緊接着,定義四個關鍵幀 ,然後給不同的方向添加動畫 animation除了name是公有屬性,是以提出來在pic-area中一起設定了,下面是分别設定動畫名字

.wrapper .in-top .pic-area{
    animation-name: in-top;
}
.wrapper .in-bottom .pic-area{
    animation-name: in-bottom;
}
.wrapper .in-left .pic-area{
    animation-name: in-left;
}
.wrapper .in-right .pic-area{
    animation-name: in-right;
}
@keyframes in-top{
    0%{transform: rotate3d(0,0,0,0)}
    100%{transform: rotate3d(-1,0,0,90deg)}
}
@keyframes in-bottom{
    0%{transform: rotate3d(0,0,0,0)}
    100%{transform: rotate3d(1,0,0,90deg)}
}
@keyframes in-left{
    0%{transform: rotate3d(0,0,0,0)}
    100%{transform: rotate3d(0,1,0,90deg)}
}
@keyframes in-right{
    0%{transform: rotate3d(0,0,0,0)}
    100%{transform: rotate3d(0,-1,0,90deg)}
}
           

這是轉動之後的效果,這裡我也給文字區加了一個透明度

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

上面呢是進入的動畫,接下來寫出去的動畫

道理其實很簡單,就是把順序換一下就好了

@keyframes out-top{
    0%{transform: rotate3d(-1,0,0,90deg)}
    100%{transform: rotate3d(0,0,0,0)}
}
@keyframes out-bottom{
    0%{transform: rotate3d(1,0,0,90deg)}
    100%{transform: rotate3d(0,0,0,0)}
}
@keyframes out-left{
    0%{transform: rotate3d(0,1,0,90deg)}
    100%{transform: rotate3d(0,0,0,0)}
}
@keyframes out-right{
    0%{transform: rotate3d(0,-1,0,90deg)}
    100%{transform: rotate3d(0,0,0,0)}
}
           

添加出去的動畫名稱

.wrapper .out-top .pic-area{
    animation-name: out-top;
} 
.wrapper .out-bottom .pic-area{
    animation-name: out-bottom;
}
.wrapper .out-left .pic-area{
    animation-name: out-left;
}
.wrapper .out-right .pic-area{
    animation-name: out-right;
}
           

添加出去的動畫效果,這裡我就和進入的動畫效果放在了一起寫,這樣可以減少代碼量

.out-top .pic-area .hide,
.in-top .pic-area .hide{
    transform-origin: bottom;
    transform: translate3d(0,-100%,0) rotate3d(1,0,0,90deg);
}
.out-bottom .pic-area .hide,
.in-bottom .pic-area .hide{
    transform-origin: top;
    transform: translate3d(0,100%,0) rotate3d(-1,0,0,90deg);
}
.out-left .pic-area .hide,
.in-left .pic-area .hide{
    transform-origin: right;
    transform: translate3d(-100%,0,0) rotate3d(0,1,0,-90deg);
}
.out-right .pic-area .hide,
.in-right .pic-area .hide{
    transform-origin: left;
    transform: translate3d(100%,0,0) rotate3d(0,1,0,90deg);
}
           

四個方向樣式的設定原理相同,隻要清楚一個方向的樣式設定方法就可以。

每一個方向都有一組相應的動畫,通過類名來控制,分别是 in-方向 與 out-方向

第三步:也是最重要的一步:如何判斷從那個方向進入的呢?

首先:擷取li對象,并把li類數組變為數組

給每一個li綁定事件

oLi.forEach(function(ele ,index){
        ele.addEventListener('mouseenter',function(e){
            addClass(this,e);
        })
    })
           

定義一個增加類名的函數

function addClass(ele,e) {
        // 判斷從那個方向進入

        // 首先擷取滑鼠進入的位置 
        var x = e.offsetX - ele.offsetWidth / 2;
        var y = e.offsetY - ele.offsetHeight / 2;

        var deg = Math.atan2(y,x) * (180/Math.PI);  //角度值與弧度值的轉換
    }
           

這是滑鼠進入一個盒子的時候會産生一個弧度值,這裡我把offsetWidth/2是為了把坐标圓心移動到中間,這樣就會得到一周的角度,然後再通過一個數學公式,轉化成角度,這就是滑鼠進入時的不同角度

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

但是這個樣子角度的區間會亂,有正有負,是以我給所有的角度都加了180度,這樣是以的角度就都變成了一個正數,而且是從0度到360度

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

我們不妨來看一下此時各個方向的角度範圍

  • top :45~135
  • right:135~225
  • bottom:225~315
  • left:0~45 & 315~360

但是現在這個度數看起來還是不友善我們操作,是以繼續化簡,給每一個都除以90°

那麼現在的角度範圍是:

  • top :0.5~1.5
  • right :1.5~2.5
  • bottom :2.5~3.5
  • left :0~0.5 & 3.5~4

繼續化簡,進行四舍五入取整

  • top :1
  • right:2
  • bottom:3
  • left:0 & 4

    但是現在left中有兩個數字代表了一個方向,是以要繼續進行處理 ,每一個都+3,之後變為 4,5, 6,3&7 ,然後%4取餘4

  • top:0
  • right:1
  • bottom :2
  • left:3

    現在轉換為代碼:

3D翻轉盒子圖檔展示特效(解決滑鼠進入不同的邊,自動判斷進入的是什麼方向)

現在四個方向就可以用一個數字來代表

完整js代碼如下:

var oLi = Array.prototype.slice.call(document.getElementsByTagName('li'));
//擷取li對象,并把擷取到li類數組轉換為數組
    oLi.forEach(function(ele ,index){
        ele.addEventListener('mouseenter',function(e){
            addClass(this,e,'in');
        })
        ele.addEventListener('mouseleave',function(e){
            addClass(this,e,'out');
        })
    })

    function addClass(ele,e,state) {
        // 判斷從那個方向進入

        // 首先擷取滑鼠進入的位置 
        var x = e.offsetX - ele.offsetWidth / 2;
        var y = e.offsetY - ele.offsetHeight / 2;
        var deg = (Math.round((Math.atan2(y,x) * (180/Math.PI)+180) / 90)+3) % 4;
        
        var direction;
        switch(deg){
            case 0 :
                direction = 'top';
                break;
            case 1 :
                direction = 'right';
                break;
            case 2 :
                direction = 'bottom';
                break;
            case 3 :
                direction = 'left';
                break; 
        }
        ele.className = state + '-' + direction; // 這裡采用了類名拼接的方式
    }

           

最後這個項目就完成了。

繼續閱讀