如何使用标准JavaScript结束CSS过渡后立即重新启动? [英] How can I restart a CSS transition as soon as it ends using standard JavaScript?

查看:120
本文介绍了如何使用标准JavaScript结束CSS过渡后立即重新启动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立了一种密码生成器,该密码生成器应在倒计时结束时显示一个新密码。不幸的是,我只设法弄清楚了如何运行我的代码一次。倒计时由一个简单的CSS过渡组成,我想保留它,因为它比其他尝试(我尝试使用JavaScript反复更新宽度)平滑得多。

I have built a kind of password generator that should display a new password whenever the countdown expires. Unfortunately, I have only managed to figure out how to run my code once. The countdown consists of a simple CSS transition, which I would like to keep, because it is much smoother than my other attempts, wherein i tried to repeatedly update the width using JavaScript.

var dictionary = {
	"adverbs": [
  	"always",
  	"usually",
    "probably"
  ],
  "adjectives": [
  	"useful",
  	"popular",
   	"accurate"
  ],
  "nouns": [
  	"computer",
    "software",
    "terminal"
  ]
};

function capitalizeFirst(string) {
	return string.charAt(0).toUpperCase() + string.slice(1);
}

function randomIndex(object) {
	return object[Math.floor(Math.random() * object.length)];
}

function generatePassword() {
	var category = ["adverbs", "adjectives", "nouns"];
	var password = [];
  
  for (i = 0; i < category.length; i++) {
  	password.push(capitalizeFirst(randomIndex(dictionary[category[i]])));
  }
  
  password.push(Math.floor(Math.random() * 8999) + 1000);
  return password.join("");
}

function updatePassword() {
	document.getElementById("countdown-fill").style.width = 100 + '%';
	document.getElementById("text-field").value = generatePassword();
	document.getElementById("countdown-fill").style.width = 0 + '%';
}

setInterval(updatePassword, 5000);

@import url('https://fonts.googleapis.com/css?family=Nunito&display=swap');

body {
  margin: 0;
  width: 100%;
  height: 100%;
  background-color: #f8f8f8;
}

.container {
  max-width: 400px;
  margin: 0 auto;
}

#text-field {
  font-size: 15px;
  font-weight: 400;
  font-family: 'Nunito', sans-serif;
  margin-top: 100px;
  margin-bottom: 10px;
  width: 100%;
  height: 30px;
  padding: 10px;
  box-sizing: border-box;
  border: 1px solid  #e5e5e5;
  background-color: #ffffff;
}

#countdown-background {
  width: 100%;
  height: 10px;
  box-sizing: border-box;
  border: 1px solid  #e5e5e5;
  background-color: #ffffff;
}
#countdown-fill {
  width: 100%;
  height: 100%;
  transition: width 5s;
  transition-timing-function: linear;
  background-color: #1e87f0;
}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Password Generator</title>
  </head>
  <body>
    <div class="container">
      <input id="text-field" type="text" spellcheck="false">
      <div id="countdown-background">
        <div id="countdown-fill"></div>
      </div>
    </div>
  </body>
</html>

当前,我我的代码有两个明显的问题:

Currently, I have two apparent issues with my code:


  1. 由于 setInterval ,转换被延迟了。如果我只简单地自己调用 updatePassword ,则不是这种情况。

  2. CSS过渡仅动画一次。我想每次调用 updatePassword 时重置动画。

  1. The transition becomes delayed due to setInterval. This is not the case if I simply call updatePassword on its own.
  2. The CSS transition only animates once. I would like to reset the animation every time i call updatePassword.

I遇到了一些针对我的问题的jQuery解决方案,但是我对此不太感兴趣,因为我想尽可能地依赖标准JavaScript。但是,我对其他CSS工具(例如关键帧)也没问题,这些工具似乎效果很好:

I came across a few jQuery solutions for my problem, but I am not very interested in those, as I want to rely on standard JavaScript as much as possible. However, I am okay with alternative CSS tools like keyframes, which seem to work well:

#countdown-fill {
  width: 100%;
  height: 100%;
  animation: refresh 5s infinite;
  background-color: #1e87f0;
}

@keyframes refresh {
    from {
        width: 100%;
    }
    to {
        width: 0;
    }
}

尽管如此,我还是担心动画中的同步问题不会以任何方式与 updatePassword 耦合。

Although, I do worry about synchronization issues as the animation is not coupled with updatePassword in any way.

问题:有没有办法在每次调用函数时让 updatePassword 重置动画并消除初始延迟?

Question: Is there a way to have updatePassword reset the animation each time I call the function, and remove the initial delay?

JSFiddle: https://jsfiddle.net/MajesticPixel/fxkng013/

推荐答案

我修改了您的 JSFiddle ,这是解释。

I've modified your JSFiddle, here's the explanation.

#countdown-fill {
  width: 100%;
  height: 100%;
  transform-origin: left;
  background-color: #1e87f0;
}
.reset {
  transition: transform 5s linear;
  transform: scaleX(0);
}

诀窍是将过渡绑定到类上,以及何时需要重置它只需删除类(将过渡重置为初始状态)并再次添加(重新启动它)即可。

The trick is to bind the transition to a class, and when you want to reset it you just remove the class (reset the transition to the initial status) and add it again (restart it).

但是有一些陷阱:最重要的是是立即删除和添加类将由浏览器进行优化,浏览器将合并动作,而根本不会发生过渡。技巧是将调用包装在嵌套的rAF调用中,这将迫使浏览器执行,呈现然后再次执行。

But there are a few gotchas: the most important is that instantly removing and adding the class will be optimized by the browser, which will just merge the actions and no transition at all will happen. The trick is to wrap the calls in a nested rAF call, which will force the browser to execute, render, and then execute again.

window.requestAnimationFrame(function() {
  document.getElementById("countdown-fill").classList.remove('reset');   
  window.requestAnimationFrame(function() {
    document.getElementById("countdown-fill").classList.add('reset');
  });
});

第二个与转换有关:优化浏览器渲染,避免转换宽度或高度之类的属性,以及尝试限制转换和不透明度。我已将您的宽度过渡更改为变换过渡:效果相同,性能更高。

The second is related to transitions: to optimize browser rendering, avoid transitioning properties like width or height, and try to limit to transforms and opacity. I've changed your width transition into a transform transition: same effect, more performance.

这篇关于如何使用标准JavaScript结束CSS过渡后立即重新启动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆