为什么我的CSS变量不影响关键帧动画? [英] Why do my CSS variables not affect keyframes animation?

查看:92
本文介绍了为什么我的CSS变量不影响关键帧动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试使用javascript更改关键帧动画的开始和结束度值。

I'm trying to use javascript to change the start and end degree values for keyframes animations.

在CSS文件的:root中,我为每个变量创建了一个开始和结束变量六个div并分配初始值 0deg。然后在我的javascript文件中,我每3秒钟更新一次每个变量。从理论上讲,这应该意味着每个div都以90度为增量随机旋转。

In :root in my CSS file I create a start and end variable for each of six divs and assign an initial value of "0deg". Then in my javascript file I update each variable every 3 seconds. Theoretically this should mean that each div randomly turns in 90 degree increments.

但是,那不是正在发生的事情,我碰到了墙。有趣的是,当我使用getComputedStyle将CSS旋转变量的值打印到控制台时,它们可以正确反映javascript创建的值。您可以在此处看到控制台正在记录与我的 rotate0a公式匹配的各种数字。和 rotate0b-左上div的开始和结束值。但是该div会根据我在:root中设置的变量不断旋转。

But, that's not what's happening and I've hit a wall. Interestingly, when I print the values of my CSS rotation variables to the console using getComputedStyle, they are correctly reflecting the javascript-created values. You can see here the console is logging a variety of numbers that match my formula for "rotate0a" and "rotate0b"--the start and end values for the top-left div. Yet that div continuously rotates according to the variable I set in :root.

CSS转换不考虑新的变量值。任何帮助将不胜感激。谢谢!

The CSS transform isn't respecting the new variable values. Any help would be hugely appreciated. Thank you!

以下代码和此处的CodePen版本: https:/ /codepen.io/KylePalermo/pen/rNeENww

Code below and CodePen version here: https://codepen.io/KylePalermo/pen/rNeENwd

let min = 0;
let max = 4;

let x;

let rotVar;
let rotVarStarts = [0, 0, 0, 0, 0, 0];
let rotVarEnds = [];


function getRandomInt() {
  min = Math.ceil(min);
  max = Math.floor(max);
  x = Math.floor(Math.random() * (max - min) + min); 
}

function resetStarts() {
  for (let i = 0; i < 6; i++) {
    rotVarStarts[i] = rotVarEnds[i];
  }
}


function setEnds(){
  for (let i = 0; i < 6; i++) {
    getRandomInt();
    if (x == 0) { 
      rotVar = 0; } else if 
      (x == 1) {
      rotVar = 90; } else if 
      (x == 2) {
      rotVar = 180; } else if 
      (x == 3) { 
      rotVar = 270; } else if 
      (x == 4) {
      rotVar = 360; }
    rotVarEnds[i] = rotVar;   
  }


  document.documentElement.style.setProperty('--rotate0a', rotVarStarts[0] + "deg");
  document.documentElement.style.setProperty('--rotate0b', rotVarEnds[0] + "deg");
  
  document.documentElement.style.setProperty('--rotate1a', rotVarStarts[1] +"deg");
  document.documentElement.style.setProperty('--rotate1b', rotVarEnds[1] + "deg");

  document.documentElement.style.setProperty('--rotate2a', rotVarStarts[2] + "deg");
  document.documentElement.style.setProperty('--rotate2b', rotVarEnds[2] + "deg");

  document.documentElement.style.setProperty('--rotate3a', rotVarStarts[3] + "deg");
  document.documentElement.style.setProperty('--rotate3b', rotVarEnds[3] + "deg");

  document.documentElement.style.setProperty('--rotate4a', rotVarStarts[4] + "deg");
  document.documentElement.style.setProperty('--rotate4b', rotVarEnds[4] + "deg");

  document.documentElement.style.setProperty('--rotate5a', rotVarStarts[5] + "deg");
  document.documentElement.style.setProperty('--rotate5b', rotVarEnds[5] + "deg");
  
  let test1 = getComputedStyle(document.documentElement).getPropertyValue('--rotate0a');
  let test2 = getComputedStyle(document.documentElement).getPropertyValue('--rotate0b');
  
  console.log(test1 + "//" + test2);
  
}


setInterval(function () {
     setEnds();
     resetStarts();
     }, 3000);

:root {
  --rotate0a: 0deg;
  --rotate0b: 90deg;
  --rotate1a: 0deg;
  --rotate1b: 0deg;
  --rotate2a: 0deg;
  --rotate2b: 0deg;
  --rotate3a: 0deg;
  --rotate3b: 0deg;
  --rotate4a: 0deg;
  --rotate4b: 0deg;
  --rotate5a: 0deg;
  --rotate5b: 0deg;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

.rotater {
  width: 100%;
  background-color: blue;
  padding-bottom: 100%;
  position: relative;
}

.zero {
  animation: rotation0 1s infinite linear;
}

.one {
  animation: rotation1 1s infinite linear;
}

.two {
  animation: rotation2 1s infinite linear;
}

.three {
  animation: rotation3 1s infinite linear;
}

.four {
  animation: rotation4 1s infinite linear;
}

.five {
  animation: rotation5 1s infinite linear;
}

.inner {
  position: absolute;
  top: 0;
  left: 0;
}

@keyframes rotation0 {
  from {
    transform: rotate(var(--rotate0a));
  }
  to {
    transform: rotate(var(--rotate0b));
  }
}

@keyframes rotation1 {
  from {
    transform: rotate(var(--rotate1a));
  }
  to {
    transform: rotate(var(--rotate1b));
  }
}

@keyframes rotation2 {
  from {
    transform: rotate(var(--rotate2a));
  }
  to {
    transform: rotate(var(--rotate2b));
  }
}

@keyframes rotation3 {
  from {
    transform: rotate(var(--rotate3a));
  }
  to {
    transform: rotate(var(--rotate3b));
  }
}

@keyframes rotation4 {
  from {
    transform: rotate(var(--rotate4a));
  }
  to {
    transform: rotate(var(--rotate4b));
  }
}

@keyframes rotation5 {
  from {
    transform: rotate(var(--rotate5a));
  }
  to {
    transform: rotate(var(--rotate5b));
  }
}

<body onload = "setEnds()">
  <div class = "wrapper">
    <div class = "rotater zero">
      <div class = "inner"></div>
    </div>
    <div class = "rotater one">
      <div class = "inner"></div>
    </div>
    <div class = "rotater two">
      <div class = "inner"></div>
    </div>
    <div class = "rotater three">
      <div class = "inner"></div>
    </div>
    <div class = "rotater four">
      <div class = "inner"></div>
    </div>
    <div class = "rotater five">
      <div class = "inner"></div>
    </div>
  </div>
</body>

推荐答案

在Blink和Webkit浏览器中,将在第一次设置动画时(而不是在每次迭代时或在变量更改时)分析动画的值。

In Blink and Webkit browsers, the values for the animation are parsed the first time the animation is set and not at every iteration, nor when the variables change.

您需要强制新动画使用新变量:

You need to force a new animation for it to use the new variables:

  const rotaters = document.querySelectorAll('.rotater');
  rotaters.forEach( (elem) => {
    elem.style.animationName = "none";
  });
  //
  // update the variables here
  //
  document.body.offsetWidth; // force a single reflow
  rotaters.forEach( (elem, i) => {
    elem.style.animationName = "rotation" + i;
  });

let min = 0;
let max = 4;

let x;

let rotVar;
let rotVarStarts = [0, 0, 0, 0, 0, 0];
let rotVarEnds = [];


function getRandomInt() {
  min = Math.ceil(min);
  max = Math.floor(max);
  x = Math.floor(Math.random() * (max - min) + min); 
}

function resetStarts() {
  for (let i = 0; i < 6; i++) {
    rotVarStarts[i] = rotVarEnds[i];
  }
}


function setEnds(){
  for (let i = 0; i < 6; i++) {
    getRandomInt();
    if (x == 0) { 
      rotVar = 0; } else if 
      (x == 1) {
      rotVar = 90; } else if 
      (x == 2) {
      rotVar = 180; } else if 
      (x == 3) { 
      rotVar = 270; } else if 
      (x == 4) {
      rotVar = 360; }
    rotVarEnds[i] = rotVar;   
  }

  
  const rotaters = document.querySelectorAll('.rotater');
  rotaters.forEach( (elem) => {
    elem.style.animationName = "none";
  });

  document.documentElement.style.setProperty('--rotate0a', rotVarStarts[0] + "deg");
  document.documentElement.style.setProperty('--rotate0b', rotVarEnds[0] + "deg");
  
  document.documentElement.style.setProperty('--rotate1a', rotVarStarts[1] +"deg");
  document.documentElement.style.setProperty('--rotate1b', rotVarEnds[1] + "deg");

  document.documentElement.style.setProperty('--rotate2a', rotVarStarts[2] + "deg");
  document.documentElement.style.setProperty('--rotate2b', rotVarEnds[2] + "deg");

  document.documentElement.style.setProperty('--rotate3a', rotVarStarts[3] + "deg");
  document.documentElement.style.setProperty('--rotate3b', rotVarEnds[3] + "deg");

  document.documentElement.style.setProperty('--rotate4a', rotVarStarts[4] + "deg");
  document.documentElement.style.setProperty('--rotate4b', rotVarEnds[4] + "deg");

  document.documentElement.style.setProperty('--rotate5a', rotVarStarts[5] + "deg");
  document.documentElement.style.setProperty('--rotate5b', rotVarEnds[5] + "deg");
  
  let test1 = getComputedStyle(document.documentElement).getPropertyValue('--rotate0a');
  let test2 = getComputedStyle(document.documentElement).getPropertyValue('--rotate0b');
  console.log(test1 + "//" + test2);

  document.body.offsetWidth; // force a single reflow
  rotaters.forEach( (elem, i) => {
    elem.style.animationName = "rotation" + i;
  });
  
}


setInterval(function () {
     setEnds();
     resetStarts();
     }, 3000);

:root {
  --rotate0a: 0deg;
  --rotate0b: 90deg;
  --rotate1a: 0deg;
  --rotate1b: 0deg;
  --rotate2a: 0deg;
  --rotate2b: 0deg;
  --rotate3a: 0deg;
  --rotate3b: 0deg;
  --rotate4a: 0deg;
  --rotate4b: 0deg;
  --rotate5a: 0deg;
  --rotate5b: 0deg;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

.rotater {
  width: 100%;
  background-color: blue;
  padding-bottom: 100%;
  position: relative;
}

.zero {
  animation: rotation0 1s infinite linear;
}

.one {
  animation: rotation1 1s infinite linear;
}

.two {
  animation: rotation2 1s infinite linear;
}

.three {
  animation: rotation3 1s infinite linear;
}

.four {
  animation: rotation4 1s infinite linear;
}

.five {
  animation: rotation5 1s infinite linear;
}

.inner {
  position: absolute;
  top: 0;
  left: 0;
}

@keyframes rotation0 {
  from {
    transform: rotate(var(--rotate0a));
  }
  to {
    transform: rotate(var(--rotate0b));
  }
}

@keyframes rotation1 {
  from {
    transform: rotate(var(--rotate1a));
  }
  to {
    transform: rotate(var(--rotate1b));
  }
}

@keyframes rotation2 {
  from {
    transform: rotate(var(--rotate2a));
  }
  to {
    transform: rotate(var(--rotate2b));
  }
}

@keyframes rotation3 {
  from {
    transform: rotate(var(--rotate3a));
  }
  to {
    transform: rotate(var(--rotate3b));
  }
}

@keyframes rotation4 {
  from {
    transform: rotate(var(--rotate4a));
  }
  to {
    transform: rotate(var(--rotate4b));
  }
}

@keyframes rotation5 {
  from {
    transform: rotate(var(--rotate5a));
  }
  to {
    transform: rotate(var(--rotate5b));
  }
}

<body onload = "setEnds()">
  <div class = "wrapper">
    <div class = "rotater zero">
      <div class = "inner"></div>
    </div>
    <div class = "rotater one">
      <div class = "inner"></div>
    </div>
    <div class = "rotater two">
      <div class = "inner"></div>
    </div>
    <div class = "rotater three">
      <div class = "inner"></div>
    </div>
    <div class = "rotater four">
      <div class = "inner"></div>
    </div>
    <div class = "rotater five">
      <div class = "inner"></div>
    </div>
  </div>
</body>

请注意,Firefox会实时更新值,而且这种动画并不是Webkit + Blink中唯一遭受这种行为的动画(例如,在更新svg引用的元素时,我经常面对这种动画)。虽然我不确定这里的规格要求是什么...

Note that Firefox does update the values live, and that this kind of animation is not the only one to suffer from this behavior in Webkit+Blink (I faced it a lot with updating svg referenced elements for instance). Though I'm not sure what are the specs requirements here...

(对Cr进行二等分,发现它们确实暴露了FF的行为(使用更新的var()值)直到M54,这是错误发生此更改的地方,因为其中没有任何提及此行为的信息,我想这是一个副作用,而且可能是不希望的,请打开 BUG 1135443 )。

(Ran a bisect against Chromium and found they did expose FF's behavior (using updated var() values) until M54, here is the bug where this change happened, given there is nothing in there mentioning this behavior, I guess it's a side-effect, and maybe an unwanted one, opened BUG 1135443).

这篇关于为什么我的CSS变量不影响关键帧动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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