JavaScript implementation of seamless carousel chart

Keywords: Javascript

JavaScript realizes seamless carousel chart:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            position: relative;
            width: 500px;
            height: 400px;
            border: 1px solid #fff;
            margin: 20px auto;
            overflow: hidden;
            cursor: pointer;
        }

        .container .images img {
            display: block;
            float: left;
        }

        .container .dots {
            position: absolute;
            margin: 0 auto;
            left: 0;
            right: 0;
            bottom: 10px;
            background: rgba(255, 255, 255, .3);
            padding: 5px;
            border-radius: 20px;
        }

        .container .dots span {
            margin: 2px;
            width: 8px;
            height: 8px;
            display: block;
            border-radius: 50%;
            background: rgba(255, 255, 255, .5);
            float: left;
        }

        .container .dots span.active {
            background: #f40;
        }

        .container .arrow {
            display: none;
        }

        .container:hover .arrow {
            display: block;
        }

        .container .arrow .item {
            width: 40px;
            height: 40px;
            background: rgba(255, 255, 255, .5);
            color: #fff;
            position: absolute;
            top: 0;
            bottom: 0;
            margin: auto 0;
            text-align: center;
            line-height: 40px;
            font-size: 20px;
        }

        .container .arrow .leftArrow {
            left: 0;
            border-radius: 0 20px 20px 0;
        }

        .container .arrow .rightArrow {
            right: 0;
            border-radius: 20px 0 0 20px;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="images">
        </div>
        <div class="dots">
        </div>
        <div class="arrow">
            <div class="item leftArrow">&lt;</div>
            <div class="item rightArrow">&gt;</div>
        </div>
    </div>
    <script>
        var config = {
            imgWidth: 500, //image width
            dotWidth: 12, //Small dot width
            imageArray: ["./image/5.jpg", "./image/1.jpg", "./image/2.jpg", "./image/3.jpg", "./image/4.jpg",
                "./image/5.jpg", "./image/1.jpg"
            ], //Array to store picture paths
            doms: {
                images: document.querySelector(".images"), //Storing pictures dom
                dots: document.querySelector(".dots"), //Polka Dot dom
                leftArrow: document.querySelector(".item.leftArrow"), //On the left dom
                rightArrow: document.querySelector(".item.rightArrow") //On the right dom
            },
            currentIndex: 2, //Currently displayed picture subscript
            timer: { //Timer configuration
                id: null, //timer id
                duration: 16, //Every time you switch pictures, the interval between movements
                totalTime: 1000 //The total time of moving each time you switch pictures
            }
        };
        initImages();
        initDots();

        //Initialize picture elements
        function initImages() {
            //Create picture elements
            config.doms.images.style.width = config.imageArray.length * config.imgWidth + "px";
            for (var i = 0; i < config.imageArray.length; i++) {
                var img = document.createElement("img");
                img.src = config.imageArray[i];
                config.doms.images.appendChild(img);
            }

            //Show the first picture 1.jpg
            config.doms.images.style.marginLeft = -config.imgWidth * config.currentIndex + "px";
        }

        //Create a dot element
        function initDots() {
            config.doms.dots.style.width = (config.imageArray.length - 2) * config.dotWidth + "px";
            for (var i = 0; i < config.imageArray.length - 2; i++) {
                var dot = document.createElement("span");
                config.doms.dots.appendChild(dot);
            }

            config.doms.dots.children[config.currentIndex - 1].className = "active";
        }

        //Click the left arrow, right arrow, and dot
        config.doms.leftArrow.onclick = config.doms.rightArrow.onclick = config.doms.dots.onclick = function (e) {
            if (e.target.tagName === "DIV" && e.target.classList.contains("leftArrow")) { //Click the left arrow
                var index = config.currentIndex - 1;//Jump to the bottom of the picture to the left
                if(index === 0){//
                    index = 5;
                }
                jumpToImage(index, "left");
            } else if (e.target.tagName === "DIV" && e.target.classList.contains("rightArrow")) { //Click the right arrow
                var index = config.currentIndex + 1;//Jump right to the bottom of the picture
                if(index === 6){//
                    index = 1;
                }
                jumpToImage(index, "right");
            } else if (e.target.tagName === "SPAN" && e.target.parentElement && e.target.parentElement.classList
                .contains("dots")) { //Click on the dot
                var index = Array.from(config.doms.dots.children).indexOf(e.target) + 1;
                jumpToImage(index, (index > config.currentIndex) ? "right" : "left");
            }
        }

        //Which picture to jump to
        function jumpToImage(index, direction) { //index:Subscript for next picture(1,25);direction direction(1.left:Left;2.right:right);
            if (index === config.currentIndex) { //If the image subscript to jump is the same as the current subscript, do not execute
                return;
            }
            if (!direction) { //Direction default: right
                direction = "right";
            }

            //Goal to move to marginLeft
            var newMarginLeft = -index * config.imgWidth;
            //Picture switching
            //config.doms.images.style.marginLeft = newMarginLeft + "px";
            autoPlay();
            //Dots also switch automatically
            for (var i = 0; i < config.doms.dots.children.length; i++) {
                config.doms.dots.children[i].classList.remove("active");
            }
            config.doms.dots.children[index - 1].className = "active";
            //After switching, change the current picture subscript
            config.currentIndex = index;

            //Picture gradient animation,Little by little changes marginLeft
            function autoPlay() {
                stopPlay(); //Stop the last animation before playing the carousel

                //Current marginLeft
                var currentMarginLeft = parseFloat(window.getComputedStyle(config.doms.images).marginLeft);
                //The total length of the picture can't be counted as the first and the last. These two pictures are additional duplicate ones
                var allImagesLength = (config.imageArray.length - 2) * config.imgWidth;
                //1.Calculate the total number of movements
                var frequency = Math.ceil(config.timer.totalTime / config.timer.duration);
                var currentNum = 0; //Number of current movements
                //2.Calculate the total distance of the motion
                var allDistance = 0;
                if (direction == "left") { //Left movement
                    if (newMarginLeft > currentMarginLeft) { //target marginLeft > current marginLeft
                        //Total distance = target marginLeft - current marginLeft
                        allDistance = newMarginLeft - currentMarginLeft;
                    } else {
                        //Total distance = Total picture length - |target marginLeft - current marginLeft|
                        allDistance = allImagesLength - Math.abs(newMarginLeft - currentMarginLeft);
                    }
                } else { //Right movement
                    if (newMarginLeft < currentMarginLeft) { //target marginLeft < current marginLeft
                        //Total distance = target marginLeft - current marginLeft
                        allDistance = newMarginLeft - currentMarginLeft;
                    } else { //target marginLeft > current marginLeft
                        //Total distance = -(Total picture length - |target marginLeft - current marginLeft|)
                        allDistance = -(allImagesLength - Math.abs(newMarginLeft - currentMarginLeft));
                    }
                }
                //3.Calculate the distance of each movement change
                var everyDistance = allDistance / frequency; //Distance per movement = Total distance of movement / Total number of exercises
                config.timer.id = setInterval(function () {

                    //Changing the picture marginLeft
                    currentMarginLeft += everyDistance;
                    //If the picture moves to the right to the extra first picture (i.e. the last picture in the array)
                    if (direction === "right" && Math.floor(Math.abs(currentMarginLeft)) > allImagesLength) {
                        
                        currentMarginLeft += allImagesLength; //The picture moves back to the corresponding position of the first picture in an instant
                    } else if (direction === "left" && Math.ceil(Math.abs(currentMarginLeft)) < config
                        .imgWidth) { //If the picture moves left to the last additional picture (i.e. the first picture in the array)
                        currentMarginLeft -= allImagesLength; //The picture moves back to the corresponding position of the last picture in an instant
                    }
                    config.doms.images.style.marginLeft = currentMarginLeft + "px";
                    currentNum++; //Current number of movements per execution++
                    if (currentNum === frequency) { //Reach the total number of movements, stop moving
                        stopPlay();
                    }
                }, config.timer.duration);
            }
            //stop playing
            function stopPlay() {
                clearInterval(config.timer.id);
                config.timer.id = null;
            }
        }
    </script>
</body>

</html>
index.html

Effect display:

Last picture toggles the effect of the first picture

 

The image array stores a total of seven images, but 1.jpg and 5.jpg are stored twice for connection. In this way, when switching from 5.jpg to 1.jpg, there will be no break. The width and height of the five pictures are 500 X 200

 

 

 

The difficulties of making seamless broadcast chart:

Calculate the total distance of the motion

Left movement, target margin left and current margin left

Target marginLeft > current marginLeft / / total distance = target marginLeft - current marginLeft

Target marginLeft < current marginLeft / / total distance = total picture length - | target marginLeft - current marginLeft|

Move right, target margin left and current margin left

Target marginLeft < current marginLeft / / total distance = target marginLeft - current marginLeft

Target marginLeft > current marginLeft / / total distance = - (total picture length - | target marginLeft - current marginLeft |)

Posted by B-truE on Fri, 01 May 2020 19:35:38 -0700