如何使用 JS 更改@keyframes?

How do I change @keyframes using JS?

我正在使用

#progressBar{
   background-color: #247BA0;
   width: 150px;
   padding: 10px;
   border-radius: 5px;
   animation: progressBar 3s ease;
   animation-fill-mode:both; 
   text-align: center;
   box-sizing: content-box;
} 

@keyframes progressBar {
 0% { width: 0; }
100% { width: 280px; }
}

我想使用 JS 变量更改 @keyframe 的宽度数字。我怎么能这样做(没有 jQuery)?

对于这种情况,您可以使用 css variables

在页面的根目录中定义两个变量并在关键帧中使用它们:

:root {
    --my-start-width: 0;
    --my-end-width: 280px;
}

...

@keyframes progressBar {
    0% { width: var(--my-start-width); }
    100% { width: var(--my-end-width); }
}

现在您可以使用这些函数在 js 中获取和设置此 属性 :

//set property: 

document.documentElement.style
    .setProperty('--my-variable-name', '100px');

//get property

getComputedStyle(document.documentElement)
    .getPropertyValue('--my-variable-name'); // returns value

我想我们在 CSS+JS = CJSSS 的领土上,那是很多 Ss 需要处理的事情。 JS 处理 Document 对象模型,CSS 处理 CSS 对象模型。浏览器对象模型处理这两者。

据说 JS 与 CSSOM 没有交互。我们在屏幕上看到的是 BOM 将这两者绘制在屏幕上。当它的画又名 DOM 代表 Js 能够访问和操作对象时。

当我们使用 JS 更改样式值时,请牢记以上内容,例如element.style.height=100% 它发生在广为人知的计算值之后。

通过计算,它指的是在屏幕上绘制的内容,因此 element.height 会 return 以像素为单位,而不是根据绘制它的 CSS 规则,即百分比。

因此,当我们打算更改@keyframe 时,我们打算在事前而不是事后操纵 CSS 规则。那是问题 1.

BOM 仅提供设置数量的 CSS 样式属性,可通过样式函数进行操作,例如高度颜色等在那个集合中不包括@keyframe。

所以我们必须在事后做一些腿部工作来处理它。

root = document.documentElement;

 
 setTimeout(function(){ root.style.setProperty('--change', 30 + "px"); }, 5000);
:root {
  --change: 280px;
}
#progressBar{
   background-color: #247BA0;
   width: 150px;
   padding: 10px;
   border-radius: 5px;
   animation: progressBar 3s ease;
   animation-fill-mode:both; 
   text-align: center;
   box-sizing: content-box;
} 


@keyframes progressBar {
 0% { width: 0; }
100% { width: var(--change); }
}
<div id="progressBar"></div>

所以这是我的解决方案,请允许我介绍一下 CSS Variables

我在 CSSOM 全局作用域中创建了一个 CSS 变量

:root {
      --change: 280px;
    }

然后在 CSS 中访问了相同的内容。好处是每当变量的值在 root 中更改时,它将自动在调用变量的地方表示。

 @keyframes progressBar {
     0% { width: 0; }
    100% { width: var(--change); }
    }

不,我们需要事后访问它。我使用 document.documentElement 将整个文档抓取为一个元素,包括其中的所有 css。 然后我使用 style.setProperty 修改 CSS 声明块中现有的 CSS 属性 。关键字声明块不是计算绘制块。

root.style.setProperty('--change', 30 + "px");

上面正在更改 CSSOM 全局范围内设置的文档的 属性,它没有子属性等。我们仍然无法访问规则,例如root.style.setProperty('@keyframes progressBar', 30 + "px") 根本行不通。

最终示例,如实使用它。

root = document.documentElement;

 
 root.style.setProperty('--change', 30 + "px"); 
:root {
  --change: 280px;
}
#progressBar{
   background-color: #247BA0;
   width: 150px;
   padding: 10px;
   border-radius: 5px;
   animation: progressBar 3s ease;
   animation-fill-mode:both; 
   text-align: center;
   box-sizing: content-box;
} 


@keyframes progressBar {
 0% { width: 0; }
100% { width: var(--change); }
}
<div id="progressBar"></div>
我刚刚设置了超时功能来展示它是如何工作的。显然这次没有设置超时。

关键点。 在事实发生后操纵 CSS 块不会像第一个示例中那样再次重新 运行 动画,除非你 运行 另一组函数反转所有事情然后重做它。取决于您的上下文。

在事实之前操作 CSS 块将把 JS 操作视为被考虑的值,如第二个示例所示。

根据上下文,我的意思是你真正打算做的事情如下面的例子所示,使用设置超时,我们在 3 秒后更改 css 变量,显然动画是 运行 两次,但在第二次运行 条形图更长。所以 CJSSS alo 需要你的上下文。

root = document.documentElement;

 
 setTimeout(function(){ root.style.setProperty('--change', 500 + "px"); }, 3000);
:root {
  --change: 280px;
}
#progressBar{
   background-color: #247BA0;
   width: 150px;
   padding: 10px;
   border-radius: 5px;
   animation: progressBar 3s ease;
   animation-fill-mode:both; 
   text-align: center;
   box-sizing: content-box;
animation-iteration-count: 2;
} 


@keyframes progressBar {
 0% { width: 0; }
50% { width: var(--change); }
100% { width: 0; }
}
<div id="progressBar"></div>

希望答案能为您提供足够的前进方向。