Carousel effect of picture slices

Preface

When I visited a certain website unintentionally, I was deeply attracted by the carousel effect on its homepage. Through the browser debugging, I finally understood the implementation principle, and finally wrote a copy by myself Demo. The final effect is as follows:( (The source code is at the end)

Plane effect:

Insert picture description here

3D effect:

Insert picture description here

This carousel cuts the picture into several pieces, then plays the cut pieces with animation effects in turn, and finally stitches them into a new picture.

In the process of recalling the front-end technology stack, it seems that there is no technology that can directly crop the image and divide it into several pieces. The image cropping effect we usually apply is only used canvasto simulate the generation.

Through my own debugging, it turns out that this carousel picture uses a canvassimpler way to achieve the same cropping effect.

Next, proceed from the shallower to the deeper, step by step to reveal the implementation principle.

Plane effect

Let's start with the plane effect, first write a general htmlcarousel diagram, the structure is as follows:

 <div class="main" id="el">
       <div class="item">
         <img src="./img/1.jpg" />
       </div>
       <div class="item">
         <img src="./img/2.jpg" />
       </div>
       <div class="item">
         <img src="./img/3.jpg" />
       </div>
 </div>

elIt is the outer container, which contains three carousel pictures.

If we want to make an animation effect, we have to follow a step.

  • Generate or get the domelements to be animated
  • domAdd animation effects to the element

Now slow down the animation of the plane effect and carefully observe its characteristics, as shown in the following figure:

Insert picture description here

htmlThis picture slice is not found in the original code, which means that the elements to be animated need to be generated by us and added to the page document for rendering.

If the setting picture will be cut into 5parts, then we generate a slice image structure is as follows:

   <div class="main" id="el">
         <div class="item">
           <img src="./img/1.jpg" />
         </div>
         <div class="item">
           <img src="./img/2.jpg" />
         </div>
         <div class="item">
           <img src="./img/3.jpg" />
         </div>
         <!--做动画的dom元素-->
         <div class="hook">
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
              <div><img src="./img/2.jpg" /></div>
         </div>
   </div>

In the original page by jsgenerating a class called a period hookof html片段, as a positioning mode absolute.

hookThere are five div, respectively, show 2.jpgthe corresponding picture cut problem now facing is how to let this 5one divwere to scale this picture a part of it?

If setting hookthe outer container has a total width of 1000pxthe sub-element 5number divaverage of 200pxmay be provided by a second let divonly show imgthe second cuts.

  <div style="position:absolute;width:200px;left:200px;overflow:hidden">
     <img src="./img/2.jpg" style="position:absolute;width:500%;left:-200px"/>
  </div>

Since the total width of the outer layer 1000px, cut into 5parts each divrepresenting 200px(in actual coding 200through jscalculated), and then moved to the right 200pxoccupying the second slice position.

imgThe assignment of the widthsum leftis the key point, and its specific value is also calculated by the total width and the number of slices.

widthSet to 500%, which means that the width of the picture is equal to 1000pxthe outermost container, and then move to the left 200px. Because the parent is divset overflow:hidden, imagine the effect and it will come out.

These processes mentioned above should be jsspliced ​​and calculated in a string html字符串, similar to the following:

  for(i=0;i<n;i++){ //循环i次,n(总共将图片切成n份),unit_width对应每一个切块的宽度
           html += `
               <div 
               style="position:absolute;
               width:${unit_width}px;
               top:-100%;
               left:${ i * unit_width};
               overflow:hidden">
                   <img src="${src}" 
                       style="position:absolute;
                       width:${n*100}%;
                       left:${-i * unit_width}px"/>
              </div>
     `     
  }

5After the divstitching is completed, put it into <div class="hook"></div>it and add it to the page document rendering. The final generated domelement is the element to be animated next.

Since 5a divset of absolute positioning and topvalue is set -100%, so they once rendered is in the top position on the page.

The next animation effect is very easy to achieve, we only need to divadd one to each in the above loop transition:top linear 0.25s.

Once that 5a divrendering is complete, we can jsdynamically set in each divof the topvalue of 0animation is triggered, each page divslowly sliding down from the top.

Wait until all the animation process is completed, we will hookthis use jsgenerated domremoved off, and that should be displayed item(containing static pictures of the original dom) is set to display hidden from this point the entire animation process is complete.

3D effect

The planar effect is relatively simple to implement, and the 3Dflipping effect requires an understanding of cssthe 3dattributes first.

3d property review

rotateX: Around the Xaxis of rotation, Lenovo 单杠运动.
rotateY: Around the Yaxis of rotation, Lenovo 钢管舞.
rotateZ: Around the Zaxis of rotation, Lenovo 老式钟表盘.

The above three attributes are usually contacted a lot, so I won't repeat them. The following will focus on the 3dattributes.

    .container{
       perspective: 1200px;
       perspective-origin: right center;
      .wrapper {
        transform-style: preserve-3d;
        transform:translateZ(-100px);
      }
    }

The outer container containercontains a child wrapper. The child is the specific 3delement to be animated, so it must set a property transform-style: preserve-3d.

Only when it is set can the preserve-3delement show its 3deffect.

translateZAnd translateX, translateYthese two attributes are not the same. translateXIs about to move in the plane, translateYis moved in the vertical plane.

translateZIt is an 3dattribute.It does not make up, down, left, and right displacements on the plane, but makes displacements in or out of the direction perpendicular to the plane.

translateZ(-100px)It means that the element has moved to the inside of the screen 100px. According to the rule of near, big, far, small, the final visual effect of the element is 100pxreduced overall. If it is positive , it will move to the outside of the screen 100px, and the visual effect of the element is enlarged.

translateZOnly preserve-3dapply on the element with the attribute set will have an effect, so that preserve-3dall 3dattributes can take effect.

blockIt is 3dthe domelement to be transformed , so it needs to be set preserve-3dand transformtransformed. The parent element is containerequivalent to a stage and blockcan be regarded as an actor of stage performance.

perspectiveIt represents the distance between the audience and the stage.It is conceivable perspectivethat the smaller the value, the closer the audience is to the stage, and the scene on the stage will be seen more clearly.

Corresponding to the real scene, perspectivecorresponding to domthe distance of the elements in the user's eyes, the larger the distance, the farther away, the wrappersmaller the interior and the less clear. On the contrary, the perspectivelarger the wrapperdisplay, the larger the appearance and the clearer the internal details. .

perspective-originIt can be understood as whether the user is sitting in the left position, the middle position or the right position of the auditorium to watch the performance on the stage, and the effect of the visual field is different.

Now back to the topic, continue to study 3dthe carousel diagram of the flip effect. By slowing down the animation time, observe its details, as shown in the following figure:

Insert picture description here

By observing the above picture, I quickly realized that the elements to be animated are not available on the current page and need to be jsdynamically generated by us.

The animation element is a cube, which contains two motion effects. One is to move to the left and the other is to flip forward. Moving to the left is easy to do, set it to an absolute positioning dynamic change leftvalue. And flipping can RotateX(-90deg)be done by setting Arrived (equivalent to Xflip 90degree along the axis ).

The animation effect of the cube is not difficult to achieve, the difficulty lies in how to generate such a cube.

Draw cube

In the current scene, the cube only needs to draw four faces: top, front, left and right. The top is stored for the next picture to be carousel, the front is stored for the currently displayed picture, and the left and right are black. The background is filled to make the picture more three-dimensional, the htmlstructure is as follows:


   <div class="wrapper">
            <div class="left"></div>
            <div class="right"></div>
            <div class="front"><img src="1.jpg"></div>
            <div class="up"><img src="2.jpg"></div>
   </div>

The left, right, frontand upare set to absolute positioning, width and height are filled with the parent element, leftand topsetting 0.

frontIt is the face directly in front, it is originally displayed on the plane, and there is no need to do any processing.

leftTo position the center point in the upper left corner, the yrendering 90degree along the axis will form the side.

.left {
  transform-origin: 0% 0%;
  transform: rotateY(90deg);
  background-color: #333;
}

rightYou need to move the entire width to the right and then rotate along the y axis 90to form the right side.

html += `
    ... //js中dom字符串拼接
   <div class="right" style="transform: translateX(${unit_width}px) rotateY(90deg);">
      ...
   </div>
   ...
`

upThe surface first sets the center point at the lower left corner, rotates around the Xaxis 90and then moves up the entire height to form the top.

.up{
    transform-origin: 0% 100%;
}
html += `
    ... //js中dom字符串拼接
   <div class="up" style="transform: rotateX(90deg) translateZ(${container_height}px);">
     ...
   </div>
   ...
`

The domstructure of these four faces jsis spliced ​​inside and put into the wrappercorresponding parent div. As mentioned above , the attributes wrapperneed to be set inside preserve-3d, and the wrapperelements are the elements that are really animated dom.

wrapperAfter the element is encapsulated, it is thrown into the stage element container, and the attributes and containerare set .3dperspectiveperspective-origin

One containercorresponds to a cube slice, and the htmlstring formed by all the cut cubes is put into the page document and rendered. In this way, the animated domelements are generated.

Add flip animation

The domelements that perform the animation have been generated and rendered on the page. According to the previous analysis, adding an attribute to each cube ( wrappercorresponding div) rotateX(-90deg)can make the cube flip. The results are as follows:

Insert picture description here
wrapperIn addition, the rotateX(-90deg)attribute is indeed flipped forward, but the final position is not close to the ground.

The cause of the accident was because it wrapperwas a cube, not a simple plane, it also contained four planes. Now when the cube is rotated, the position of its center point is very important.

wrapperThe height of is 100%full of the entire parent. Through testing, it is found that the attribute transformation of the cube is actually based on the front ( frontface). The center point of the cube is located in frontthe middle of the frontheight of the face . If the height of the face is 600px, then When 300pxdrawing an Xaxis, rotate the entire cube along this axis. If the frontheight of the surface is 800px, then the cube will 400pxrotate along the axis.

Now go back to the above case, frontthe height of the face is set to 100%fill the parent element, then the cube will draw an axis in the middle and flip forward 90, so there will be a hollow below. We can't let the cube turn and stop in mid-air , To find a way to put it back on the ground.

According to what I said before, the cube uses the frontsurface as the reference surface. After flipping the 90degree, the frontsurface comes to the bottom. Then you want the cube to move down, because it is frontfacing the bottom at this time , and you only need to set it translateZ(contrainer_height/2)to move the cube down. Half the height is attached to the bottom.

Although this setting can ensure that the flipped cube is attached to the bottom, the picture inside it is deformed.

Because when the cube is set rotateX(-90deg)to flip forward, it is actually moved forward. According to the rules of near large and far small, the visual effect of the picture is enlarged. In order to solve this problem, first use the cube translateZ(-contrainer_height/2)to push half of the height inside and then let the cube Flip forward, so that the problem of image stretching is solved, the code is as follows:


while ((el = eles.shift())) {
    //el对应着每个立方体的dom
    //立方体先沿Z轴往后推一半高度,再朝前做翻转,翻转完后向下移动一半高度贴底 
    el.style.transform = `translateZ(${  
      -this.container_height / 2
    }px) rotateX(-90deg) translateZ(${this.container_height / 2}px)`;
    ...
  }

After the flip effect is finished, we will find that the cube is facing us and flipping, we can't see the right side of the cube with a black background right, so it will appear very non-dimensional.

I introduced an attribute earlier perspective-origin:right center. This is like the audience sitting on the right side of the auditorium, and the stage is as wide as the auditorium, and there is an iron cage on the stage facing the front of the audience. At this time, the audience's field of vision can only see On the front of the iron cage, if the cage is pushed to the left side of the stage, then the customer sitting on the right side of the audience can not only see the front of the iron cage, but he can also see the right side of the iron cage.

In the same way, in order to make the cube appear more three-dimensional when it is flipped, the black background on the right can be displayed during the animation. In order to achieve this purpose, you need to move the cube to the left, plus perspective-originthe support of attributes, the cube The flipped three-dimensional effect comes out.

If you want the cube to move to the left, you only need to get the domelements of the cube and leftassign them dynamically.

Source code

Complete code

Guess you like

Origin blog.csdn.net/brokenkay/article/details/115034048