function
- Click the page turn buttons on both sides to turn the page
- Move the mouse to pause the automatic play, move the mouse to continue the automatic play
- Click on the bordeaux green dot below to switch
structure
- Carousel: Carousel
- Pre and Next: Turn button
- Dot: Dot indicator at the bottom
- Card: indicates the card to be switched
- Play-ground: Wraps the card and moves it as a whole
- Screen: a display area where you can see only one card
<div id="carousel">
<div id="pre" class="page-btn">The previous page</div>
<div id="wrapper">
<div id="screen">
<div id="play-ground" class="play-ground">
<div class="card" style="background-color:goldenrod;">1</div>
<div class="card" style="background-color: rgb(252, 84, 84);">2</div>
<div class="card" style="background-color:skyblue;">3</div>
<div class="card" style="background-color:pink;">4</div>
<div class="card" style="background-color: rgb(117, 209, 99);">5</div>
</div>
</div>
<div id="pagenation">
<span data-id="1" class="dot checked"></span>
<span data-id="2" class="dot"></span>
<span data-id="3" class="dot"></span>
<span data-id="4" class="dot"></span>
<span data-id="5" class="dot"></span>
</div>
</div>
<div id="next" class="page-btn">The next page</div>
</div>
Copy the code
Train of thought
Let’s get the wheel map moving
- Play-ground, I’m going to box each card, and then I’m going to move this play-ground right or left, so I’m going to move the card
- Create a global variable index that represents the offset coefficient of the current play-ground. The initial value is 1
index = 1;
// The play function changes the offset of play-ground
function play() {
// card.item (0).offsetwidth represents the width of a Card
PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px";
}
play();
Copy the code
Let the wheel map be moved by you
- If play-ground is shifted to the left by the width of the card, the offset will be increased by one. You know,
- When you click on the pre and Next buttons, the index will change and the offset of the play-ground will change. Of course, clicking dot should also be able to switch
Pre.addEventListener('click', () => {
index--;
play();
})
Next.addEventListener('click', () => {
index++;
play();
})
Dot.forEach(dot => {
dot.addEventListener('click', (e) => {
index = e.target.dataset.id;
play();
});
Copy the code
Let the wheel – cast graph can be played in a loop
- For example, play-ground now has five cards, and if you cut to the fifth one and you switch, there are no cards left, so you want to loop it
- If the index is greater than 5, it goes back to 1, if the index is less than 1, it goes back to 5. This completes the loop
if (index == 6) { index = 1; };
if (index == 0) { index = 5; };
PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px";
// Update the dot style: The dot that is clicked will have a nice green background, and the rest will remain white
Dot.forEach(item= > (item.classList.remove('checked')));
Dot[index - 1].classList.add('checked');
Copy the code
Let the wheel – cast chart move by itself
- Create a global variable timer that periodically changes the index value. By default, it automatically switches to the next index, index++
- The timer stops when the mouse moves into the screen, so you have time to see the card, and continues automatically when the mouse moves out of the screen
// The function autoPlay is used to implement autoPlay
function autoPlay() {
index++;
play();
}
timer = setInterval(autoPlay, 3000);
Screen.onmouseenter = () = > {
clearInterval(timer);
}
Screen.onmouseleave = () = > {
timer = setInterval(autoPlay, 3000);
};
Copy the code
To this point, the rotation map can be arbitrarily switched, loop play, automatic play
Of course, it is more fragrant to add animation to the round cast chart! Seamless switching 😎Copy the code
Combined with animation
// CSS transitions are simple and work well
PlayGround.style.transition = "All 0.8 s ease - in-out";
PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px";
Copy the code
Seamless switching
It means that when you get to the last card, when you go down, it’s going to display the first card
- Copy card5 and insert it in front of card d1, so when you click on the last one you’ll see that card5 and card d1 are spliced together, and similarly copy card d1 and insert it after card5, you know…
// Copy the node using cloneNode()
const nextclone = Card[0].cloneNode(true);
const preclone = Card[Card.length - 1].cloneNode(true);
PlayGround.insertBefore(preclone, PlayGround.firstChild);
PlayGround.appendChild(nextclone);
Copy the code
Implement a true loop
- When the index exceeds the end point, index will be assigned a value of 1, that is, back to the starting point, but the animation effect is suddenly back to the starting point from the end point, it looks like this sub-child, which makes me difficult to 😯
- The solution:
- After index > 5, remove play-ground animation immediately after the animation of the card1 is finished, and make the offset of play-gorund go through javascript DOM processing and i7 8th generation processor speed calculation. Teleport to the real card1, at which point index is assigned a value of 1 (resuming animation incidentally) — completing a seamless loop
function play() {
PlayGround.style.transition = "All 0.8 s ease - in-out";
PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px";
// Add the transitionEnd event listener
PlayGround.addEventListener('transitionend'.() = > {
if (index == 6) { index = 1; };
if (index == 0) { index = 5; };
PlayGround.style.transition = "all ease-in-out";// Remove the animation
PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px";
Dot.forEach(item= > (item.classList.remove('checked')));
Dot[index - 1].classList.add('checked');
});
}
Copy the code
At this point, the rotation chart is complete! 😎
Put a source code:
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> < span style> < span style> body {display: flex; justify-content: center; align-items: center; } #carousel { width: 800px; height: 500px; border: grey 2px solid; display: flex; } .page-btn { width: 100px; height: 500px; text-align: center; font-weight: bold; line-height: 500px; } #wrapper { width: 600px; height: 500px; } #screen { width: 600px; height: 400px; display: flex; overflow: hidden; } .play-ground { position: relative; display: flex; } #pagenation { width: 100%; height: 100px; text-align: center; } .card { min-width: 600px; height: 400px; text-align: center; line-height: 400px; font-size: 5rem; } .dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: teal 1px solid; } .checked { background-color: teal; } </style> <div id="carousel"> <div id="pre" class="page-btn"> </div> <div id="wrapper"> <div id="screen"> <div id="play-ground" class="play-ground"> <div class="card" style="background-color:goldenrod;" >1</div> <div class="card" style="background-color: rgb(252, 84, 84);" >2</div> <div class="card" style="background-color:skyblue;" >3</div> <div class="card" style="background-color:pink;" >4</div> <div class="card" style="background-color: rgb(117, 209, 99);" >5</div> </div> </div> <div id="pagenation"> <span data-id="1" class="dot checked"></span> <span data-id="2" class="dot"></span> <span data-id="3" class="dot"></span> <span data-id="4" class="dot"></span> <span data-id="5" Class ="dot"></span> </div> <div >< div id="next" class=" page-bTN "> next page </div> </div> <script> const PlayGround = document.getElementById('play-ground'); const Card = document.querySelectorAll('.card'); const Next = document.getElementById('next'); const Pre = document.getElementById('pre'); const Dot = document.querySelectorAll('.dot'); const Screen = document.getElementById('screen'); const nextclone = Card[0].cloneNode(true); const preclone = Card[Card.length - 1].cloneNode(true); PlayGround.insertBefore(preclone, PlayGround.firstChild); PlayGround.appendChild(nextclone); index = 1; play(); timer = setInterval(autoPlay, 2000); Screen.onmouseenter = () => { clearInterval(timer) } Screen.onmouseleave = () => { timer = setInterval(autoPlay, 2000); }; Pre.addEventListener('click', () => { index--; play(); }) Next.addEventListener('click', () => { index++; play(); }) Dot.forEach(dot => { dot.addEventListener('click', (e) => { index = e.target.dataset.id; play(); }); (1) {}) function play PlayGround. Style. The transition = "all 0.8 s ease - in-out"; PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px"; PlayGround.addEventListener('transitionend', () => { if (index == 6) { index = 1; }; if (index == 0) { index = 5; }; PlayGround.style.transition = "all ease-in-out"; PlayGround.style.left = (index) * -Card.item(0).offsetWidth + "px"; Dot.forEach(item => (item.classList.remove('checked'))); Dot[index - 1].classList.add('checked'); }); } function autoPlay() { index++; play(); } </script> </body> </html>Copy the code