javascript - CSS:在计时器上暂停动画

标签 javascript html css svg css-animations

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

目标是用户可以启动计时器,并且当他愿意时,他可以暂停或继续计时器。

我遇到的困难是暂停 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>

代码

根据此 answer 的建议更改代码.

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

(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>

最佳答案

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

使用动画:填充1s; 简写表示法
您还弄乱了 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 做你想做的事情

关于javascript - CSS:在计时器上暂停动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67125030/

相关文章:

javascript - 加载网络字体后如何收到通知

javascript - 单击带有 flash 的 iframe

javascript - Bootstrap 下拉菜单不会在外部单击时关闭

javascript - 将多个视频返回到海报照片

css - 在容器内居中图像

javascript - 如何在angularjs中有条件地应用css类

html - 两个 div(一个有绝对高度,另一个有滚动条)

javascript - 选择单词边界,但不包括标点符号

javascript - 为屏幕而不是打印媒体切换 CSS 显示

css - 在 R 中有什么方法可以将 RMarkdown v2 html 文件作为电子邮件的正文发送