3D flip box picture display special effects (solve the mouse enters different sides, automatically determine what direction it enters)

3D flip box picture display special effects

First, show the finished effect. The most difficult part of this demo is that the mouse enters different sides, and the direction must be automatically judged. This problem will be solved in detail later!
Insert picture description here

The main programming idea: the separation of style and behavior

Step 1: Build the html structure

In a container, six small boxes are generated. Here I use the ul li method. In each li, there is a pic-area to wrap pictures and text. Here I use the flexible box layout method to achieve the demonstration Layout, other methods are okay, and then by positioning the text area and overlapping the picture area, prepare for the subsequent construction of the cube. In order to see clearly, I added a little transparency, which will be deleted later.
Insert picture description here

Part of the html code is as follows:

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

The following is the css code, for reference only:

*{
    
    
    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);
}

Step 2: How to implement the cube

First thing to note: Although it looks is a six-sided cube, but I only had two faces, I define the class name of the four directions, move the mouse in different directions, I added the corresponding class name to
us to flip the text portion of the back of the picture, pay attention to the text of the flip 90 degrees, he flipped the center is in the center position, as shown below, even after the flip-up, inside translation
Insert picture description here
but I used a A simple method, first pan, then change the flip source point, and finally flip the
Insert picture description here
css code directly as follows:

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

It is worth noting that do not forget the following code, one is the depth of field property, the other is to turn on the 3D mode
Insert picture description here

There should be an effect like this now
Insert picture description here

The same is true: four faces and four class names

.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);
}

Set it on a different li and look at the current effect as shown in the figure:
Insert picture description here
Next, this is the rotation effect. Here, the animate effect of css3 is mainly used to
change the rotation source of the picture area first, otherwise there will be a prominent effect, 150px It is half the width and height of the box, so that the axis of rotation of the box is fixed at the center of the box

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

Next, define four key frames, and then add animation animations to different directions except that name is a public attribute, so it is proposed to set them together in pic-area, and the following is to set the animation name separately

.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)}
}

This is the effect after the rotation. Here I also added a transparency to the text area.
Insert picture description here
Above is the animation that enters, and the animation that is written next
is actually very simple. Just change the order.

@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)}
}

Animation name added

.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;
}

The animation effect added, here I will write it together with the animation effect entered, so that the amount of code can be reduced

.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);
}

The principles of setting the styles in the four directions are the same, as long as you know how to set the styles in one direction.
Each direction has a set of corresponding animations, which are controlled by the class name, namely in- direction and out- direction

The third step: and the most important step: how to judge from which direction you entered?

First: Get the li object and turn the li class array into an array

    var oLi = Array.prototype.slice.call(document.getElementsByTagName('li'));

Bind events to each li

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

Define a function to increase the class name


    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);  //角度值与弧度值的转换
    }

This is when the mouse enters a box, a radian value will be generated. Here I set offsetWidth/2 to move the center of the coordinate circle to the middle, so that you can get the angle of one week, and then use a mathematical formula to convert it into an angle. This is The mouse enters at different angles,
Insert picture description here
but the range of angles in this way will be chaotic, there are positive and negative, so I added 180 degrees to all the angles, so all the angles become a positive number, and it is from 0 degrees To 360 degrees,
Insert picture description here
let’s take a look at the range of angles in all directions at this time

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

But now this number of degrees still seems inconvenient for us to operate, so continue to simplify and divide each one by 90°.
Then the current angle range is:

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

Continue to simplify and round up

  • top :1
  • right:2
  • bottom:3
  • left: 0 & 4
    But now there are two numbers in left that represent a direction, so we need to continue processing, each of which is +3, and then becomes 4, 5, 6, 3&7, and then %4 takes the remainder of 4.
  • top:0
  • right:1
  • bottom :2
  • left: 3
    is now converted to code:
        var deg = (Math.round((Math.atan2(y,x) * (180/Math.PI)+180) / 90)+3) % 4;

Insert picture description here
Now the four directions can be represented by a number. The
complete js code is as follows:

    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; // 这里采用了类名拼接的方式
    }

Finally this project is completed.

Guess you like

Origin blog.csdn.net/qq_43377853/article/details/108267606