没有 JavaScript 计时器的自动播放轮播 - CSS 动画

先看效果:
在这里插入图片描述
再看代码(查看更多):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计时器</title>
    <style>
        * {
      
      
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        body {
      
      
            background: #98ede0;
            transition: background 500ms;
            font-family: ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT", "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif;
        }

        .content {
      
      
            margin: 0 auto;
            max-width: 500px;
            height: 100vh;
            height: 100svh;
            min-height: 400px;
            display: flex;
            flex-direction: column;
            padding: 40px 40px 80px;
            justify-content: center;
        }

        a {
      
      
            transition: color 200ms;
            color: rgba(0, 0, 0, 0.5);
            border-radius: 5px;
            text-decoration: none;
            margin: 40px auto 0;
        }
        a:hover {
      
      
            color: black;
            text-decoration: underline;
        }
        a:focus-visible {
      
      
            color: black;
            outline: 3px solid rgba(255, 255, 255, 0.3);
            outline-offset: 5px;
        }

        .pagination {
      
      
            display: flex;
            gap: 10px;
            height: 4px;
            min-height: 4px;
        }

        .pagination-item {
      
      
            border-radius: 100px;
            height: 100%;
            flex: auto;
            background: rgba(0, 0, 0, 0.08);
            overflow: hidden;
            border: 0;
            cursor: pointer;
        }

        @keyframes progress {
      
      
            from {
      
      
                width: 0;
            }
            to {
      
      
                width: 100%;
            }
        }
        .pagination-progress {
      
      
            flex: auto;
            background: #333;
            height: 100%;
            width: 0;
        }
        .pagination-item--running .pagination-progress {
      
      
            animation: progress 3s linear forwards;
        }
        .pagination-item--done .pagination-progress {
      
      
            width: 100%;
        }
        .pagination--paused .pagination-progress {
      
      
            animation-play-state: paused;
        }
        :-moz-window-inactive .pagination-progress {
      
      
            animation-play-state: paused;
        }

        .controls {
      
      
            display: flex;
            justify-content: center;
            gap: 12px;
        }

        .control {
      
      
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 100px;
            border: none;
            outline: none;
            height: 40px;
            flex: 40px 0 0;
            max-width: 100px;
            background: rgba(255, 255, 255, 0.3);
            transition: transform 200ms, background-color 200ms;
            will-change: transform, background-color;
            font-size: 20px;
        }
        .control:hover {
      
      
            cursor: pointer;
            transform: scale(1.15);
            background: rgba(255, 255, 255, 0.45);
        }
        .control:focus {
      
      
            background: rgba(255, 255, 255, 0.6);
        }

        .icon {
      
      
            width: 20px;
        }

        .icon--play {
      
      
            margin-right: -2px;
        }

        .pagination--paused ~ .controls .icon--pause,
        .pagination:not(.pagination--paused) ~ .controls .icon--play {
      
      
            display: none;
        }

        .state {
      
      
            font-size: 120px;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="content">

    <div class="pagination">
    </div>

    <div class="state">
        &nbsp;
    </div>

    <div class="controls">
        <button class="control control--prev" aria-label="Previous">
            <svg class="icon" viewBox="0 0 32 32">
                <path d="M20 28a1 1 0 0 1-.521-.146l-18-11a1.002 1.002 0 0 1 0-1.708l18-11A.999.999 0 0 1 21 5v6.11a1 1 0 0 1-.479.854L13.918 16l6.603 4.035c.297.182.479.506.479.854V27a1 1 0 0 1-1 1zM3.918 16 19 25.217V21.45l-7.521-4.596a1 1 0 0 1 0-1.707L19 10.55V6.783L3.918 16z" />
                <path d="M30 28a1 1 0 0 1-.521-.146l-18-11a1.002 1.002 0 0 1 0-1.708l18-11A.999.999 0 0 1 31 5v22a1 1 0 0 1-1 1zM13.918 16 29 25.217V6.783L13.918 16z" />
            </svg>
        </button>
        <button class="control control--play-pause" aria-label="Play/Pause">
            <svg class="icon icon--play" viewBox="0 0 32 32">
                <path d="M7 28a.999.999 0 0 1-1-1V5a1 1 0 0 1 1.521-.854l18 11a1.001 1.001 0 0 1 0 1.708l-18 11A1 1 0 0 1 7 28zM8 6.783v18.434L23.082 16 8 6.783z" />
            </svg>
            <svg class="icon icon--pause" viewBox="0 0 32 32">
                <path d="M13 28H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v22a1 1 0 0 1-1 1zm-5-2h4V6H8v20zM25 28h-6a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v22a1 1 0 0 1-1 1zm-5-2h4V6h-4v20z" />
            </svg>
        </button>
        <button class="control control--next" aria-label="Next">
            <svg class="icon" viewBox="0 0 32 32">
                <path d="M12 28a1 1 0 0 1-1-1v-6.111c0-.348.182-.672.479-.854L18.082 16l-6.603-4.035A1.001 1.001 0 0 1 11 11.11V5a1 1 0 0 1 1.521-.854l18 11a1.002 1.002 0 0 1 0 1.708l-18 11A1 1 0 0 1 12 28zm1-6.55v3.767L28.082 16 13 6.783v3.767l7.521 4.596a1.001 1.001 0 0 1 0 1.708L13 21.45z" />
                <path d="M2 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.521-.854l18 11a1.002 1.002 0 0 1 0 1.708l-18 11A1 1 0 0 1 2 28zM3 6.783v18.434L18.082 16 3 6.783z" />
            </svg>
        </button>
    </div>

    <a target="_blank" href="https://blog.csdn.net/qq_35241329?type=blog">博客文章</a>
</div>
</body>
<script>
    "use strict";
    function getItem(index) {
      
      
        const item = document.createElement('button');
        item.classList.add('pagination-item');
        item.addEventListener('animationend', next);
        item.addEventListener('click', () => update(index));
        const progress = document.createElement('div');
        progress.classList.add('pagination-progress');
        item.appendChild(progress);
        return item;
    }
    function createItems(itemsCount) {
      
      
        const items = [];
        for (let i = 0; i < itemsCount; i++) {
      
      
            items.push(getItem(i));
        }
        return items;
    }
    function jumpTo(item) {
      
      
        if (isPaused) {
      
      
            item.classList.remove(classNames.RUNNING);
            item.classList.add(classNames.DONE);
        }
        else {
      
      
            item.classList.add(classNames.RUNNING);
            item.classList.remove(classNames.DONE);
        }
        let sibling = item;
        while ((sibling = sibling.previousSibling)) {
      
      
            sibling.classList.remove(classNames.RUNNING);
            sibling.classList.add(classNames.DONE);
        }
        sibling = item;
        while ((sibling = sibling.nextSibling)) {
      
      
            sibling.classList.remove(classNames.RUNNING, classNames.DONE);
        }
    }
    function update(index) {
      
      
        activeIndex = index;
        jumpTo(items[activeIndex]);
        // 更新幻灯片和背景颜色
        $state.innerHTML = activeIndex + 1;
        document.body.style.backgroundColor = colors[activeIndex];
    }
    function prev() {
      
      
        if (activeIndex > 0) {
      
      
            update(activeIndex - 1);
        }
    }
    function next() {
      
      
        if (activeIndex < ITEMS_COUNT - 1) {
      
      
            update(activeIndex + 1);
        }
    }
    function playPause() {
      
      
        $pagination.classList.toggle(classNames.PAUSED);
        isPaused = !isPaused;
        ///如果当前幻灯片已完成,跳到下一张
        if (!isPaused && items[activeIndex].classList.contains(classNames.DONE)) {
      
      
            next();
        }
    }
    const colors = ['#98ede0', '#74b9ff', '#a29bfe', '#fd79a8', '#ffeaa7'];
    const classNames = {
      
      
        RUNNING: 'pagination-item--running',
        DONE: 'pagination-item--done',
        PAUSED: 'pagination--paused',
    };
    let activeIndex = 0;
    let isPaused = false;
    const ITEMS_COUNT = 5;
    const items = createItems(ITEMS_COUNT);
    const $pagination = document.querySelector('.pagination');
    const $state = document.querySelector('.state');
    const $prev = document.querySelector('.control--prev');
    const $next = document.querySelector('.control--next');
    const $playPause = document.querySelector('.control--play-pause');
    $pagination.replaceChildren(...items);
    $prev.addEventListener('click', prev);
    $next.addEventListener('click', next);
    $playPause.addEventListener('click', playPause);
    update(activeIndex);

</script>
</html>

Guess you like

Origin blog.csdn.net/qq_35241329/article/details/132569653