Teach people to analyze native JS by fishing and write rotation map

Keywords: Javascript JSON REST github

Demand and analysis

Demand:
Cyclic seamless automatic rotation of five pictures, press the left and right arrows to manually switch pictures, the mouse click on the button 123 445 under the rotation map will jump to the corresponding 123 445 pictures. When the mouse is placed on the picture of the rotation map, the left and right arrows are no longer automatically rotated and displayed. When the mouse moves away, the left and right arrows are hidden and rotated automatically.

Design sketch:


Analysis:

Layout: Prepare seven pictures for so-called seamless rotation, fix the width and height of seven pictures, assume 600 px*400 PX below. Suppose html is divided into three areas: picture area, button area and arrow area. Then encapsulate the three areas with a div and fix the width of the div to 600*400.



Style: Centralized left and right, 100 PX from the top of the page. The five buttons are circular, and the color of the button changes when it rotates to which picture or clicks to which button. The rest of the small styles are added to the Buddhist system when they are specifically coding.



JS script: I'll show you where to put a little graph, and the rest when I write that part of the code.

Two of the seven pictures are the same as the first and fifth of the five different pictures. The seventh of the seven pictures is the same as the first of the five different pictures, and the first of the seven pictures is the same as the fifth of the five different pictures. The reason will be explained when you write that part of the code.

Implementation steps

  1. Let's start with an html framework
<body>
    <div class="container">
        <div class="wrap">
            <img src="./imgs/5.jpg" alt="5">
            <img src="./imgs/1.jpg" alt="1">
            <img src="./imgs/2.jpg" alt="2">
            <img src="./imgs/3.jpg" alt="3">
            <img src="./imgs/4.jpg" alt="4">
            <img src="./imgs/5.jpg" alt="5">
            <img src="./imgs/1.jpg" alt="1">
        </div>
        <div class="button">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
        </div>
        <a href="javascript:void(0);" class="jt jt_left">&lt;</a>
        <a href="javascript:void(0);" class="jt jt_right">&gt;</a>
    </div>

Add javascript:void (0) to a tag to prevent a tag from jumping.

  1. define styles

The main purpose is to define the width and height of the total div, the button area div, the picture, the button and the left and right arrows. Seven pictures are displayed side by side. Five buttons are displayed in the middle at the bottom of the picture, and two arrows are displayed in the right and left positions respectively.

/* Clear the default style */
*{
    margin: 0;
    padding: 0;
    text-decoration: none;
}
/* Total div */
div.container{
    position: relative;
    width: 600px;
    height: 400px;
    margin: 100px auto 0 auto;
    box-shadow: 0 0 5px aqua;
    overflow: hidden;
}
/* Picture area */
div.container div.wrap{
    position: absolute;
    width: 4200px;
    height: 400px;
    z-index: 1;
}

div.container div.wrap img{
    width: 600px;
    height: 400px;
    float: left;
}
/* Button area */
div.container div.button{
    position: absolute;
    right: 225px;
    bottom: 15px;
    width: 150px;
    height: 20px;
    z-index: 2;
    text-align: center;
}

div.container div.button span{
    margin-left: 5px;
    display: inline-block;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: greenyellow;
    text-align: center;
    color: white;
    cursor: pointer;
    opacity: 0.6;
}
/* It's different from other buttons in which picture and which button have this effect. */
div.container div.button span.on{
    opacity: 1;
}
/* Arrow area */
div.container .jt{
    position: absolute;
    top: 40%;
    color:greenyellow;
    padding: 0px 14px;
    font-size: 55px;
    text-align: center;
    z-index: 2;
    display: none;
}

div.container .jt_left{
    left: 10px;
}

div.container .jt_right{
    right: 10px;
}

div.container:hover .jt{
    display: block;
    opacity: 0.4;
}

div.container .jt:hover{
    opacity: 1;
}

In order to let the first picture of the page just entered show 1.jpg, add an in-line style in the picture area map, and let the default open page show this graph:

<div class="wrap" style="left:-600px">...</div>
The effect is that when the mouse moves to the picture, there are some styles at the arrow:

  1. javascript

Step 1: Automatically switching pictures

It encapsulates two functions: next() and prev(), which correspond to the right and left rotation respectively. If you call which function, you can switch between a picture and a picture in which direction.

var wrap = document.getElementsByClassName('wrap')[0];

var newLeft = -600;

function next() {
    setInterval(function(){
        if(newLeft == -2400){
            newLeft = 0;
        }else{
            newLeft = parseInt(wrap.style.left) - 600;
        }
        wrap.style.left = newLeft + 'PX';
    },1000)
}

function prev() {
    setInterval(function(){
        if(newLeft == -600){
            newLeft = -3000;
        }else{
            newLeft = parseInt(wrap.style.left) + 600;
        }
        wrap.style.left = newLeft + 'PX';
    },1000)
}

Step 2: Let the pictures change from one picture to another in a moving trajectory during the rotation, instead of rigidly changing from one picture to another.

Here, I need to use a motion function startMove() encapsulated in my package to make a tool to use:

function getStyle(obj, attr){
    if(obj.currentStyle){
        return obj.currentStyle[attr];
    }else{
        return getComputedStyle(obj, false)[attr];
    }
}

//startMove function of motion frame    
function startMove(obj,json,fn){       
    clearInterval(obj.timer);      
    //Turn on the timer        
    obj.timer = setInterval(function(){  
        var flag = true;                 
        //Traversing json               
        for (var attr in json) {                                
            //Take the current value iCur   
            var iCur = 0;                
            if (attr == 'opacity') {                       
                iCur = Math.round(parseFloat(getStyle(obj, attr))*100);                  
            }else{                     
                iCur = parseInt(getStyle(obj, attr));                
            }                  
            //Calculating speed: iSpeed
            //Target value: json[attr]                   
            var iSpeed = (json[attr]-iCur)/8;
            iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);                       
            //Detection stop                 
            if (iCur != json[attr]) {                      
                flag = false                 
            }                  
            if (attr == 'opacity') {                       
                obj.style.filter = 'alpha(opacity:'+iCur+iSpeed+')';                      
                obj.style.opacity = (iCur+iSpeed)/100;                
            }else{                     
                obj.style[attr] = iCur + iSpeed + 'px';                   
            }   
        }        
        if (flag) {                  
            clearInterval(obj.timer);                  
            if (fn) {fn();}               
        }                     
    },30)      
}

This encapsulated motion function here, coupled with my comments can not read the code, you can see this video, the lecturer said very clearly: JS animation effect

Then use this principle: when the picture is rotated to the right to the sixth, the first picture is presented immediately, and then the encapsulated motion function is called to switch the motion from the first picture to the second picture. The same is true when you rotate to the left. When you rotate to the first page, you will show the sixth page immediately, and then move from the sixth page to the fifth page. So visually, it's five pictures that have been rotated seamlessly all the time.

That's why seven pictures are used, and the first one is the same as the sixth one, the seventh one is the same as the second one.
The code is as follows:

var wrap = document.getElementsByClassName('wrap')[0];

var newLeft = -600;

function next() {
    setInterval(function () {
        if (newLeft == -3000) {
            newLeft = 0;
            wrap.style.left = newLeft + 'px';
        }
        newLeft -= 600;
        startMove(wrap, {
            "left": newLeft
        })
        // wrap.style.left = newLeft + 'PX';
    }, 3000)
}

function prev() {
    setInterval(function () {
        if (newLeft == 0) {
            newLeft = -3000;
            wrap.style.left = newLeft + 'px';
        }
        newLeft += 600;
        startMove(wrap, {
            "left": newLeft
        });
    }, 3000)
}

Step 3: When the mouse moves to the picture, stop the automatic rotation and let the left and right arrows be clicked several times to control the rotation of several pieces to the left and right one by one.

Core Principles: Clear the timer, bind click, onmouseenter, onmouseleave events, and reconstruct the code to encapsulate the right-to-left rotation function and automatic rotation function.

Right-to-right rotation function:

function next() {
    if (newLeft == -3000) {
        newLeft = 0;
        wrap.style.left = newLeft + 'px';
    }
    newLeft -= 600;
    startMove(wrap, {
        "left": newLeft
    });
}

Left-to-left rotation function:

function prev() {
    if (newLeft == 0) {
        newLeft = -3000;
        wrap.style.left = newLeft + 'px';
    }
    newLeft += 600;
    startMove(wrap, {
        "left": newLeft
    });
}

Autoplay function:

var timer = null;

function autoPlay() {
    timer = setInterval(function () {
        next();
    }, 2000)
} /* Autoplay */

Bind events:

container.addEventListener('mouseenter', function () {
    clearInterval(timer);
}, false)

container.addEventListener('mouseleave', function () {
    autoPlay();
}, false)

left.addEventListener('click', function () {
    prev();
})

right.addEventListener('click', function () {
    next();
})

Step 4:

  • Processing buttons so that when you first enter the page, the first button has the effect of'on'in the span element.
  • Next, to achieve the visual rotation of which picture, it corresponds to which button has a kind of'on'effect.
  • Finally, when you click on which button, the button has the effect of'on', and jumps to the visual pictures.

Encapsulating a function to process buttons, the function is to set the class name of each button to empty, and then let the type of button A at this time be'on'when moving visually to picture A.

So you need to set up a Sentinel index to listen for the visual pictures, and then add the'on'class for the buttons corresponding to this picture:

//Processing button
var index = 0;
var len = dot.length;
function setCurrentDot(){
    for (var m = 0; m < len; m++){
        dot[m].className = ''; 
    }
    dot[index].className = 'on';
}
setCurrentDot();

Call this function at this time, it is equal to the first image displayed by default when entering the page is also the default so that the first button has the effect of the'on'class.


How do you make the type of button A'on'when you move visually to picture A?

You can add the value of the modified index sentry to the function once-in-a-round and call the setCurrentDot() function. In next():

    index++;
    if(index === 5){
        index = 0;
    }
    setCurrentDot();

In prev():

    index--;
    if(index === -1){
        index = 4;
    }
    setCurrentDot();

Finally, when implementing which button to click on, the button has the effect of'on'and jumps to the visual pictures.

Core idea: When clicking on the button, such as clicking on the third button, the picture should be displayed at this time should be the visual third picture, that is, the fourth of the seven pictures. The fourth corresponding wrap's left is -1800px, and then find out the corresponding rule. At this time, the new Left should be: -600* (x + 1). So no matter where you've rotated before clicking the button, just use the motion function startMove() to move to this new Left location after clicking. For example, the Sentinel index at this time equals 3, because clicking on the number of buttons is bound to have the'on'class on the number of buttons.


Write the code according to the core idea as follows (here we need to pay attention to the closure problem when Binding events):

// When the button is clicked, it has the effect of'on'and jumps to the visual pictures.
for (var s = 0; s < len; s++){
    (function(s){
        dot[s].addEventListener('click',function(){
            newLeft = -600 * (s + 1);
            startMove(wrap,{"left":newLeft});
            index = s;
            setCurrentDot();
        },false)
    }(s))
}

That's it, so the demand is done.

Last

This is the way of thinking. What matters is not the code, but the analytical logic.
Source code has been passed to github I think it's helpful to you. Please order a star. Thank you.~

Posted by ensanity on Sun, 03 Feb 2019 03:21:16 -0800