如何停止关键帧动画1秒后不使用setTimeout? - 队列上的问题事件 [英] How stop keyframe Animation exactly after 1 second without to use setTimeout ? - Problem events on queue

查看:55
本文介绍了如何停止关键帧动画1秒后不使用setTimeout? - 队列上的问题事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这将是一个很难解决的问题...

I think this will be a problem really difficult to solve...

我创建了一个速度表,显示我所在城市发生的地震次数。
我想以两种方式为这个速度表设置动画:
background-color (没有地震时为绿色,有时为红色) 3000 地震)和这个彩色div的宽度(我为背景颜色设置动画的div)。
因此,当没有地震时,宽度将 0 ,当有3000次地震时,宽度将为100%。

I created a speedometer that shows number of earthquakes occured in my city. I want to animate this speedometer in two way: background-color (green when there aren't quakes and red when there are 3000 quakes) and width of this colored div (the div where i animate background-color). So the width will be 0 when there aren't quakes and will be 100% when there are 3000 quakes.

动画是2秒,所以例如,如果我有 1500 地震:
为动画速度计添加类

The animation is 2 seconds, so for example if i have 1500 quakes: Add the class for animate speedometer

  $('#first').addClass('first-start');

使用 setTimeout 我添加一个类1秒后停止动画

And using setTimeout i add a class to stop the animation after 1 second

 setTimeout(function() {
   $('#first').addClass('first-pause');
 }, 1000);

此代码几乎总是很好用。

This code almost always works great.

现在我添加一个片段:

$('#first').addClass('first-start');

setTimeout(function() {
  $('#first').addClass('first-pause');
}, 1000);

#page {
  margin-top: 50px;
  width: 300px;
  height: 300px;
  background-color: #000;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  z-index: 4;
  overflow: hidden;
}

#box-first{
  width: 200px;
  height: 100px;
  background-color: #fff;
  border-radius: 200px 200px 0 0;
  margin-top: 10px;
  margin-bottom: 10px;
  position: relative;
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  z-index: 3;
  overflow: hidden;
}

#first{
  border-radius: 200px 200px 0 0;
  margin: 0;
  background: red;
  width: 200px;
  height: 100px;
  transform: rotate(180deg);
  transform-origin: 50% 100%;
  position: absolute;
  top: 0px;
  right: 0px;
  border: 0;
  z-index: 1;
}

#n1{
  font-size: 20px;
  color: #fff;
  font-weight: bold;
  position: absolute;
  left: 50px;
  right: 0;
  text-align: center;
  top: 50px;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 100px;
  height: 50px;
  background: #000;
  border-radius: 100px 100px 0 0;
  z-Index: 1;
  overflow: hidden;
}

@keyframes first {
  0% {
    background-color: green;
    transform: rotate(180deg);
  }
  33% {
    background-color: yellow;
    transform: rotate(240deg);
  }
  66% {
    background-color: orange;
    transform: rotate(300deg);
  }
  100% {
    background-color: red;
    transform: rotate(360deg);
  }
}



.first-start {
  animation: first 2s linear;
}

.first-pause {
  animation-play-state: paused;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
  <div id="box-first">
    <div id="first">

    </div>
    <div id="n1">
      1500
    </div>
  </div> 
</div>

https://jsfiddle.net/hoymds97/

问题在于我使用这个代码在一个大文件(4000行)中有很多事件,在同一个函数中有8个速度表。
我注意到有时(当有更多事件时) setTimeout 在为动画速度表添加类后不会立即启动。

The problem is that i use this code in a big file (4000 lines) with a lot of events and in the same function there are 8 speedometers. I noticed that sometimes (when there are more events) setTimeout not start immediately after added class for animate speedometer.

结果,动画将在...之后停止。
在我们的例子中,它就好像在1700毫秒而不是1000秒后被阻止。有时它会在2秒后停止。

As a result, the animation will stop after ... In our case, for example, it is as if it blocked after 1700 milliseconds and not 1000 seconds. Sometimes it stops even after 2 seconds.

我认为问题是队列中的许多事件

那么我该如何解决这个问题?

So how can i solve this problem ?

可以使用 setTimeout <来解决/ code>或没有它?

Is possible to solve using always setTimeout or without it?

我希望你能帮助我,对不起我的英语。

I hope you can help me and sorry for my english.

推荐答案

这是一个完全新的想法,它依赖于转换而不是动画,你可以在没有同步问题的情况下轻松调整状态。

Here is a complete new idea that relies on transition instead of animation and where you can easily adjust the state without synchronization issue.

主要技巧是使用渐变用于背景着色并调整其位置以获得所需的颜色。

The main trick is to use a gradient for the background coloration and adjust its position in order to have the needed color.

这是一个简单的代码来说明颜色:

Here is a simple code to illustrate the coloration:

.box {
  background: linear-gradient(to right, green, yellow, orange, red);
  background-size: 2000% 100%;
  transition:1s;
  background-repeat: no-repeat;
  background-position: 0 0;
  height: 200px;
}

.box:hover {
  background-position: 100% 0;
}

<div class="box">

</div>

正如您所看到的,我定义了一种带有4种颜色的渐变,我们只需调整背景尺寸即可获得着色(绿色 0%,红色 100%)。这在视觉上并不完全相同,因为我们不会像动画那样拥有纯色,因此我将背景大小大到足以创造出幻觉纯色。

As you can see, I defined a gradient with the 4 colors and we simply need to adjust the background-size in order to have the coloration (0% for green and 100% for red). This won't be exactly the same visually because we will not have a solid color like with animation and for this reason I made the background-size big enough to create the illusion of a solid color.

现在,我们只需找到背景位置和<$的值c $ c>度这很简单。 backround-position 0% 100%和度数是 180deg 360deg 之间的值。对于州 50%,我们将在逻辑上使用 50%作为背景位置, 270deg 用于转换和 x%状态我们将分别使用 x% x%*(360deg - 180deg)+ 180deg = x%* 180deg + 180deg = 180deg(x%+ 1)

Now, we simply need to find the values of the background-position and the degree which is pretty easy. The backround-position is a value between 0% and 100% and the degree is a value between 180deg and 360deg. For the state 50% we will logically use 50% for the background-position and 270deg for the transformation and for an x% state we will use respectively x% and x%*(360deg - 180deg) + 180deg = x%*180deg + 180deg = 180deg(x% + 1)

以下是 50%的示例(悬停看)

Here is an example with 50% (hover to see)

#page {
  margin-top: 50px;
  width: 300px;
  height: 300px;
  background-color: #000;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  z-index: 4;
  overflow: hidden;
}

#box-first{
  width: 200px;
  height: 100px;
  background-color: #fff;
  border-radius: 200px 200px 0 0;
  margin-top: 10px;
  margin-bottom: 10px;
  position: relative;
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  z-index: 3;
  overflow: hidden;
}

#first{
  border-radius: 200px 200px 0 0;
  margin: 0;
  background: linear-gradient(to right, green, yellow, orange, red);
  background-size: 2000% 100%;
  background-repeat:no-repeat;
  background-position:0% 0%;
  transition:1s;
  width: 200px;
  height: 100px;
  transform: rotate(180deg);
  transform-origin: 50% 100%;
  position: absolute;
  top: 0px;
  right: 0px;
  border: 0;
  z-index: 1;
}
#box-first:hover #first{
  transform: rotate(270deg);
  background-position:50% 0%;
}

#n1{
  font-size: 20px;
  color: #fff;
  font-weight: bold;
  position: absolute;
  left: 50px;
  right: 0;
  text-align: center;
  top: 50px;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 100px;
  height: 50px;
  background: #000;
  border-radius: 100px 100px 0 0;
  z-Index: 1;
  overflow: hidden;
}

<div id="page">
  <div id="box-first">
    <div id="first">

    </div>
    <div id="n1">
      1500
    </div>
  </div> 
</div>

为了使这个动态,我们需要使用JS调整值,转换将完成工作。为此,我们可以为我们转换为所需值的州定义数据属性

In order to make this dynamic, we need to adjust the values using JS and the transition will do the job. For this we can define a data-attribute for the state that we convert to the needed value.

这是我还简化了html并使用了伪元素和CSS变量的例子

Here is an example where I also simplified the html and used pseudo element and CSS variables

setTimeout(function() {
  $('.box').each(function() {
    var d = $(this).data('state');
    $(this).attr("style", "--s:" + d);
  });
}, 1000);

body {
  margin: 0;
  background: #000;
}

.box {
  width: 200px;
  height: 100px;
  background-color: #fff;
  border-radius: 200px 200px 0 0;
  margin: 10px;
  position: relative;
  display: inline-flex;
  z-index: 0;
  overflow: hidden;
}

.box:before {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 200px 200px 0 0;
  background: linear-gradient(to right, green, yellow, orange, red);
  background-size: 2000% 100%;
  background-repeat: no-repeat;
  background-position: calc(var(--s, 0) * 1%) 0%;
  transition:2s linear;
  width: 200px;
  height: 100px;
  transform: rotate(calc((var(--s, 0)/100 + 1)*180deg));
  transform-origin: 50% 100%;
  top: 0px;
  right: 0px;
}

.box:after {
  content: attr(data-number);
  font-size: 20px;
  color: #fff;
  font-weight: bold;
  text-align: center;
  margin: auto auto 0;
  width: 100px;
  height: 50px;
  line-height: 50px;
  background: #000;
  border-radius: 100px 100px 0 0;
  z-Index: 1;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box" data-number="1500" data-state="50"></div>

<div class="box" data-number="1000" data-state="20"></div>

<div class="box" data-number="3000" data-state="80"></div>

<div class="box" data-number="6000" data-state="100"></div>

您可能会注意到自转换以来所有的持续时间都相同对所有人来说都是一样的。如果你想要一个不同的持续时间并保持相同的速度,也只需在转换中使用CSS变量。

You may notice that all will have the same duration since the transition is the same for all. In case you want a different duration and keep the same speed, simply use the CSS variable within the transition also.

setTimeout(function() {
  $('.box').each(function() {
    var d = $(this).data('state');
    $(this).attr("style", "--s:" + d);
  });
}, 1000);

body {
  margin: 0;
  background: #000;
}

.box {
  width: 200px;
  height: 100px;
  background-color: #fff;
  border-radius: 200px 200px 0 0;
  margin: 10px;
  position: relative;
  display: inline-flex;
  z-index: 0;
  overflow: hidden;
}

.box:before {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 200px 200px 0 0;
  background: linear-gradient(to right, green, yellow, orange, red);
  background-size: 2000% 100%;
  background-repeat: no-repeat;
  background-position: calc(var(--s, 0) * 1%) 0%;
  transition: calc(2s * var(--s, 0)/100) linear;
  width: 200px;
  height: 100px;
  transform: rotate(calc((var(--s, 0)/100 + 1)*180deg));
  transform-origin: 50% 100%;
  top: 0px;
  right: 0px;
}

.box:after {
  content: attr(data-number);
  font-size: 20px;
  color: #fff;
  font-weight: bold;
  text-align: center;
  margin: auto auto 0;
  width: 100px;
  height: 50px;
  line-height: 50px;
  background: #000;
  border-radius: 100px 100px 0 0;
  z-Index: 1;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box" data-number="1500" data-state="50"></div>

<div class="box" data-number="1000" data-state="20"></div>

<div class="box" data-number="3000" data-state="80"></div>

<div class="box" data-number="6000" data-state="100"></div>

这篇关于如何停止关键帧动画1秒后不使用setTimeout? - 队列上的问题事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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