如何使用 JS 更改@keyframes?

Fel*_*ete 5 javascript css keyframe css-animations progress-bar

我在用着

#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;
} 
Run Code Online (Sandbox Code Playgroud)

@keyframes progressBar {
 0% { width: 0; }
100% { width: 280px; }
}
Run Code Online (Sandbox Code Playgroud)

我想改变@keyframe使用JS变量的宽度数。我怎样才能做到这一点(没有 jQuery)?

ale*_*een 13

对于这种情况,您可以使用css 变量。

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

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

...

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

Run Code Online (Sandbox Code Playgroud)

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

//set property: 

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

//get property

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

Run Code Online (Sandbox Code Playgroud)


小智 5

我想我们正处于 CSS+JS = CJSSS 的领域,这需要大量的 Ss 来处理。JS 处理 Document 对象模型,CSS 处理 CSS 对象模型。浏览器对象模型处理这两个问题。

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

考虑到上述情况,当我们使用 JS 更改样式值(例如 element.style.height=100%)时,它会在众所周知的计算值之后发生。

通过计算,它指的是屏幕上绘制的内容,因此 element.height 将返回以像素为单位的高度,而不是绘制它的 CSS 规则(百分比)。

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

BOM 仅提供通过样式函数操作的一组 CSS 样式属性,例如高度颜色等,它不包括该集合中的 @keyframe。

所以我们必须做一些事后处理它。

root = document.documentElement;

 
 setTimeout(function(){ root.style.setProperty('--change', 30 + "px"); }, 5000);
Run Code Online (Sandbox Code Playgroud)
: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); }
}
Run Code Online (Sandbox Code Playgroud)
<div id="progressBar"></div>
Run Code Online (Sandbox Code Playgroud)

所以这是我的解决方案允许我引入 CSS 变量

我在 CSSOM 全局范围内创建了一个 CSS 变量

:root {
      --change: 280px;
    }
Run Code Online (Sandbox Code Playgroud)

然后在 CSS 中访问相同的内容。好处是,当变量的值在根中更改时,它将自动表示在调用该变量的位置。

 @keyframes progressBar {
     0% { width: 0; }
    100% { width: var(--change); }
    }
Run Code Online (Sandbox Code Playgroud)

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

root.style.setProperty('--change', 30 + "px");
Run Code Online (Sandbox Code Playgroud)

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

最后一个例子,像以前一样使用它。

:root {
      --change: 280px;
    }
Run Code Online (Sandbox Code Playgroud)
 @keyframes progressBar {
     0% { width: 0; }
    100% { width: var(--change); }
    }
Run Code Online (Sandbox Code Playgroud)
root.style.setProperty('--change', 30 + "px");
Run Code Online (Sandbox Code Playgroud)
我刚刚设置了超时功能来展示它是如何工作的。显然这次没有设置超时。

关键带走。事后操作 CSS 块不会再次重新运行动画,如第一个示例所示,除非您运行另一组函数来反转所有内容然后重做它。取决于您的具体情况。

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

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

root = document.documentElement;

 
 root.style.setProperty('--change', 30 + "px"); 
Run Code Online (Sandbox Code Playgroud)
: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); }
}
Run Code Online (Sandbox Code Playgroud)
<div id="progressBar"></div>
Run Code Online (Sandbox Code Playgroud)

希望答案能给你足够的思路来前进。