It's already 2023, and you still don't know how to tear up carousels?

jd.gif


I. Introduction

At present, there 移动端is 网页端an indispensable demand for carousels. We have many alternative frameworks or components to implement this function, but it is not as good as we start customizing one ourselves today and 原生js轮播图summarize and improve relevant knowledge points.

轮播图It currently appears on the homepages of major shopping websites for display 商品信息, and many plug-ins are now available to help us achieve a variety of functions more conveniently 轮播图.

Jingdong

jd.gif

Tmall

tm.webp

Taobao

tb.webp

纯手写轮播图It may be difficult for beginners, but some companies also use carousel charts to examine interviewees 基础能力. In fact, the carousel image is relatively simple 模块as long as it is subdivided into several smaller ones.逐步实现

Below, I will show you how to implement it simply 轮播图.

2. Animation Basics

We all know that carousel images have an animation process, so how to encapsulate and implement this animation function?

1. Timer

There are two types of timers on the front end, one is a one-time timersetTimeout and the other is a repetitive timer.setInterval

1-Timer.gif

As shown in the picture above, setTimeoutyou only have to click the button before the object will run forward after 15ms 10px. If setIntervalyou only need to click once, it will be executed every 15ms. The countdown effect on the page also does the same.

setIntervalTherefore, we must choose the second option for our carousel chart .

2. left与offsetLeft

leftIt is the distance to the left of the positioning object we have added. Here you can refer to some common positioning attributes.

offsetLeftIs a read-only property ( the value cannot be modifiedoffsetParent ), returning the offset pixel value of the current element relative to the left edge of the node. The current parent node is the entire page, so you only need to assign the offset offsetLeftto it.objectleft

3. Encapsulation function

After we have the timer, we need to consider encapsulating this code into an animation function and just call it when we want.

When encapsulating functions, we must pay attention to parameters. So what parameters should our timer pass in?

物体 目标点 回调函数

3.1 Object

The object is the element we want to move dom, which is the pink box above that moves on the screen.

3.2 Target point

The movement direction of the box above is there, but once it is executed, it keeps rushing forward, which is not good!

So, let's try to modify the above code. For example, when it arrives, 800pxit will clear the timer and let it stop, otherwise it will continue to move forward. At this time we only need to add a judgment
to the timer .if else

if(object.offsetLeft==500){
    clearInterval(timer);
}
else{
    object.style.left=object.offsetLeft+10+'px';
}

2-target.gif

The target point is met, but there are still two questions?

  • How to go back after reaching 800px?
  • How to change the motion curve of an object?

Both problems require only one solution, which is to add a stepvariable that represents the value of each move instead of a fixed one 10px.

This variable only needs to be changed to the following formula to calculate:

var step = (target - obj.offsetLeft) / 10;

Our initial motion curve is like this, in a constant speed state:

liner.png

This formula can not only ensure that the object can retreat, but also satisfy the requirement of first accelerating and then decelerating 曲线运动.

easeinout.png

If you check this formula carefully, cssthe distance will actually be biased and smaller than the actual target point. Due to 浮点数calculation problems, the formula must be used to make approximations.

step = step > 0 ? Math.ceil(step) : Math.floor(step);

3.3 Callback function

回调函数As the name suggests, when I call this timer function, the target point is reached, the timer is cleared, and the callback function I passed in can be executed.

Next, let the arriving 800pxobjects change color.

3-callback.gif

Of course, you can also achieve special effects later according to your own requirements.

4. Encapsulation

We unify the code written above into one animate.jsfile and import it when needed.

function animate(obj, target, callback) {
    
    
    //排他原理
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
    
    
        //步长
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
    
    
            clearInterval(obj.timer);
            //回调函数
            callback && callback();
        }
        else {
    
    
            obj.style.left = obj.offsetLeft + step + 'px';
        }
    }, 15);
}

In order to optimize the code and prevent users from excessive clicking, we need to clear the previous timer in advance at the beginning of the timer execution 排他原理, and then execute our own timer.

3. Basic structure

1.png

The structure of building htmla page is actually very simple. We mainly divide it into three parts, namely the middle, the 焦点图left and right sides 按钮, and the bottom 小圆点.

3.1 Focus map

2.png

<ul class="rotate-middle">
    <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
    <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
    <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
    <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
    <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
</ul>

The focus map first defines a 400*300box at the bottom, and puts pictures one by one in the box. At this time, it should be noted that with each floatli added , the size of the box also needs to be extended enough to accommodate the size of this row arrangement .ul图片

3.2 Button

<button class="btn-lt">&lt;</button>
<button class="btn-rt">&gt;</button>

I didn't use 字体图标, 伪元素or anything like that for the buttons < >. I just used ordinary ones and just changed the style appropriately.

Extra attention should be paid to adding z-indexa raised position to the button to prevent it from being suppressed by the picture.

3.3 Small dots

<ol class="rotate-bottom">
    <li class="current"></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ol>

The bottom is small. 圆点Now I htmlwrite it directly in it, but later in jsthe code it will be updated in real time according to the actual number of pictures.

3.4 Summary

These three basic structures use unified positionpositioning ( son and father ), and we ulalso need to add one position: absolute;because we need to animate the box later.

4. Button display

Our requirement for this part is that 图片the button will be displayed when the mouse moves to it, but not displayed when it leaves. Before we officially write the code, let’s clarify a question first?

  • mouseenterWhat is the difference between and mouseover?

Recommended article: Why are mouseenter and mouseover so entangled?

After reading it, choose mouseenterto avoid bubbling. After obtaining the time source, directly add program execution and use it directly to hide or show the button display.

focus.addEventListener('mouseenter', function () {
    
    
        lt.style.display = 'block';
        rt.style.display = 'block';
    });
    focus.addEventListener('mouseleave', function () {
    
    
        lt.style.display = 'none';
        rt.style.display = 'none';
    });

5. Dots

5.1 Generate

for (var i = 0; i < ul.children.length; i++) {
    
    
    //创建ol li
    var cloneli = this.document.createElement('li');
    ol.appendChild(cloneli);
}

3.png

At the beginning, we did htmlnot give the dots, and later jsgenerated them in the code based on the number of pictures li.

5.2 Properties

 //自定义属性
 ol.children[i].setAttribute('index', i);

In order to better move the carousel images later, we need to ol lidefine an attribute for each one index. Here we are 5a picture and indexthe range is 0~4.

5.3 Mobile

//绑定事件
ol.children[i].addEventListener('click', function () {
    
    
// 排他原理
    for (var j = 0; j < ol.children.length; j++) {
    
    
        ol.children[j].className = '';
    }
    this.className = 'current';

    index = this.getAttribute('index');
    num = index;
    circle = index;
    animate(ul, -fixWidth * index);
})

4-move.gif

At this time, every time we click on a dot, we get its current indexvalue, and then call the animation function to pass 目标值 ulin the distance - 盒子的大小 * inddexto move the picture.

6. Button

6.1 Preparation

The movement of the left and right buttons is essentially the same, let's do the right button first. The expected goal is that every time I click 右侧按钮, the picture will move backward one.

So do we still need to add each picture here 自定义属性?

In fact, you don’t need to, just customize a variable and adjust it numaccording to the number of clicks .++

6.2 Error

5-btn.gif

As in the picture above, there are several questions:

  • The picture moved, but the dots didn’t move?
  • When I reach the last picture, how do I go back?

Below, we solve them one by one.

6.2.1 Small dot following

The small dots are easy to follow, we also define a variable circle, when the button is clicked once, circle++and then fill the corresponding dot with color.

numNote that we have to improve the boundary problem here , and we ++cannot continue when we reach the last picture 归零.

if (circle == 4) {
    
    
    circle = 0;
}
else {
    
    
    circle++;
}

6.2.2 Image return

In fact, when we reach the last picture and click again, it is incoherent and loses the smooth transition effect. 克隆In fact, we can add the first picture after the last one .

When the picture moves backward, it will transition to the last picture ( that is, the cloned version of the first picture ). At this time, if we click again, we can quickly return to the first picture.

//节点操作,复制照片
var cloneimg = ul.children[0].cloneNode(true);
ul.appendChild(cloneimg);

6.3 bug

6-bug.gif

As shown in the picture above, we clicked on the dot to reach the third picture, and then clicked the button on the right. It did not return to the fourth picture, so why was it returned to the second picture. This is mainly due to the fact that our ol liand indexare num cirleout of sync.

How to improve it is very simple, just indexassign it in real time num cirle.

For the button on the left, just copy and paste and change a few values. I won’t go into details.

7. Timer

In order to make the carousel move on time, we need to add a timer effect at the end. It is actually very simple. Just call the code of the button on the right directly inside the timer.

var timer = this.setInterval(function () {
    
    
        rt.click();
    }, 1000);

7-rotate.gif

Each time there is an interval of one second, the picture moves one to the right. If the mouse is touched, the carousel of pictures will stop. If the mouse is moved away, the carousel of pictures will continue.

8. Summary

This article mainly implements a simple carousel effect. See you next time!

25.gif

Guess you like

Origin blog.csdn.net/qq_53673551/article/details/128486591