CSS: 在计时器上暂停动画

CSS: Pause animation on timer

我正在实现一个时间计数器。

objective是用户可以启动定时器,当他想的时候,他可以暂停或继续定时器。

我遇到的困难是暂停 SVG 动画。

我遵循了这个 article,但是它不起作用。

有什么建议吗?

代码

(function() {
    const start = document.querySelector( '.start' ),
      togglePause = document.querySelector( '.pause' ),
        seconds = 60;

    function format( seconds ) {
        var sec = Math.floor( seconds % 60 ),
            min = Math.floor( seconds / 60 );

            secdisp = sec;
            mindisp = min;

            if( min === 0 && sec === 0 ) {
                clearInterval( countdown );
            } else if ( secdisp === 0 ) {
                min--;
                sec = 0;
            }
    
          return mindisp + ':' + ( secdisp < 10 ? '0' + secdisp : secdisp );
    }

    function tickdown( seconds ) {
        var mod = Math.floor( seconds % 60 ),
            min = Math.floor( seconds / 60 ) - ( mod === 0 ? 1 : 0 ),
            sec = ( mod ? 60 - mod : 0 );

        var tick = () => {
            seconds--;
    
            document.getElementById('time').innerHTML = format( seconds );
        };
        tick();
        countdown = setInterval( tick, 1000 );
    }

    document.getElementById('time').innerHTML = format( seconds );

    start.addEventListener('click', () => {
        var gauge = document.querySelector( '.timer-gauge' ),
            frame = document.querySelector( 'html' );


        tickdown( seconds );
        gauge.style.transitionDuration = seconds + 's';
        gauge.classList.add('ticking');
    });
  
  togglePause.addEventListener( 'click', () => {
    var gauge = document.querySelector( '.timer-gauge' );
    const running = gauge.style.animationPlayState === 'running';
     gauge.style.animationPlayState = running ? 'paused' : 'running';  
    
  });
}());
* {
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
html {
    background: linear-gradient(125deg, #5967c3 0%,#76b8d6 100%);
    height: 100vh;
    width: 100vw;
    max-height: 100vh;
    max-width: 100vw;

}

html:after {
    content: " ";
    position: absolute;
    height: 100%;
    left: 0;
    top: 0;
    opacity: 0;
    transition: opacity .1s linear;
    width: 100%;
    z-index: 1;
    pointer-events: none;

}
html.started:after {
    background: linear-gradient(125deg, #52b670 0%,#84c86d 100%);
    opacity: 1;
}
body {
    margin: 0;
}
svg {
    position: absolute;
    width: 100%;
    height: 100%;
    padding: 2%;
    pointer-events: none;
    z-index: 2;
}
.main {
    max-width: 100%;

}
.chart-gauge {
    font-size: 1.5rem;
    text-anchor: middle;
    dominant-baseline: central;
    alignment-baseline: middle;
    stroke-linecap: round;
}
.timer-time {
    fill: rgba(255,255,255,.6);
}
.timer-backdrop {
    transform: rotate(-90deg);
    transform-origin: center;
    fill: none;
    stroke: rgba(255,255,255,.2);
    stroke-width: 5;
}
.timer-gauge {
    transform: rotate(-270deg) scaleX(-1);
    transform-origin: center;
    fill: none;
    stroke: rgba(255,255,255,.75);
    stroke-width: 5;
    animation: fill 1s;
    animation-iteration-count: 1;
    stroke-dashoffset: 0;
}
.ticking {
    stroke-dashoffset: 360;
    transition-timing-function: linear;
}

@keyframes fill {
  0%   { stroke-dashoffset: 360; }
  100% { stroke-dashoffset: 0; }
}
<div class="main">  
  <svg viewBox="0 0 120 120" class="chart-gauge" fill="none" stroke-width="2">
    <circle class="timer-backdrop" stroke-dasharray="360" r="57.32" cx="60" cy="60"></circle>
    <circle class="timer-gauge" stroke-dasharray="360" r="57.32" cx="60" cy="60"></circle>
    <text y="50%" x="50%" id="time" class="timer-time">1:00</text>
  </svg>

  <button class="start">Start</button>
</div>
<button class="pause">Toggle Pause</button>

代码

根据此 的建议更改代码。

现在的问题是动画在中间变快,在开始和结束时变慢,所以它不会到达“时钟”的正确位置

(function() {
    const start = document.querySelector( '.start' ),
      togglePause = document.querySelector( '.pause' ),
        seconds = 60;

    function format( seconds ) {
        var sec = Math.floor( seconds % 60 ),
            min = Math.floor( seconds / 60 );

            secdisp = sec;
            mindisp = min;

            if( min === 0 && sec === 0 ) {
                clearInterval( countdown );
            } else if ( secdisp === 0 ) {
                min--;
                sec = 0;
            }
    
          return mindisp + ':' + ( secdisp < 10 ? '0' + secdisp : secdisp );
    }

    function tickdown( seconds ) {
        var mod = Math.floor( seconds % 60 ),
            min = Math.floor( seconds / 60 ) - ( mod === 0 ? 1 : 0 ),
            sec = ( mod ? 60 - mod : 0 );

        var tick = () => {
            seconds--;
    
            document.getElementById('time').innerHTML = format( seconds );
        };
        tick();
        countdown = setInterval( tick, 1000 );
    }

    document.getElementById('time').innerHTML = format( seconds );

    start.addEventListener('click', () => {
        var gauge = document.querySelector( '.timer-gauge' ),
            frame = document.querySelector( 'html' );


        tickdown( seconds );
        gauge.style.animationDuration = seconds + 's';
        gauge.classList.add('ticking');
    });
  
  togglePause.addEventListener( 'click', () => {
    var gauge = document.querySelector( '.timer-gauge' );
    const running = gauge.style.animationPlayState === 'running';
     gauge.style.animationPlayState = running ? 'paused' : 'running';  
    
  });
}());
* {
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
html {
    background: linear-gradient(125deg, #5967c3 0%,#76b8d6 100%);
    height: 100vh;
    width: 100vw;
    max-height: 100vh;
    max-width: 100vw;

}

html:after {
    content: " ";
    position: absolute;
    height: 100%;
    left: 0;
    top: 0;
    opacity: 0;
    transition: opacity .1s linear;
    width: 100%;
    z-index: 1;
    pointer-events: none;

}
html.started:after {
    background: linear-gradient(125deg, #52b670 0%,#84c86d 100%);
    opacity: 1;
}
body {
    margin: 0;
}
svg {
    position: absolute;
    width: 100%;
    height: 100%;
    padding: 2%;
    pointer-events: none;
    z-index: 2;
}
.main {
    max-width: 100%;

}
.chart-gauge {
    font-size: 1.5rem;
    text-anchor: middle;
    dominant-baseline: central;
    alignment-baseline: middle;
    stroke-linecap: round;
}
.timer-time {
    fill: rgba(255,255,255,.6);
}
.timer-backdrop {
    transform: rotate(-90deg);
    transform-origin: center;
    fill: none;
    stroke: rgba(255,255,255,.2);
    stroke-width: 5;
}
.timer-gauge {
    transform: rotate(-270deg) scaleX(-1);
    transform-origin: center;
    fill: none;
    stroke: rgba(255,255,255,.75);
    stroke-width: 5;
    animation-name: initial-fill;
    animation-duration: 1s;
    animation-iteration-count: 1;
    stroke-dashoffset: 0;
}
.ticking {
animation-name: fill;
    stroke-dashoffset: 360;
    transition-timing-function: linear;
}

@keyframes initial-fill {
  0%   { stroke-dashoffset: 360; }
  100% { stroke-dashoffset: 0; }
}

@keyframes fill {
  0%   { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: 360; }
}
<div class="main">  
<svg viewBox="0 0 120 120" class="chart-gauge" fill="none" stroke-width="2">
            <circle class="timer-backdrop" stroke-dasharray="360" r="57.32" cx="60" cy="60"></circle>
            <circle class="timer-gauge" stroke-dasharray="360" r="57.32" cx="60" cy="60"></circle>
            <text y="50%" x="50%" id="time" class="timer-time">1:00</text>
        </svg>

        <button class="start">Start</button>
</div>

        <button class="pause">Toggle Pause</button>
</div>

我还没有测试过;只是挖掘旧知识。

animation: fill 1s;shorthand表示法
你也在搞乱 animation-play-state 设置。

尝试使用所有单独的属性:https://developer.mozilla.org/en-US/docs/Web/CSS/animation

animation-play-state: running(或暂停)以

开始

更新

如果我将你的 CSS 更改为:

    xanimation: fill 1s;
    animation-name: fill;
    animation-duration:60s;
    animation-play-state:paused;

你的开关做了一些事情

所以播放状态切换有效

现在你必须让你的 CSS 和 SVG 做你想做的事