angularjs - 在定义不同动画的同一元素上切换类时,是否可以限制 CSS 动画仅播放一次?

标签 angularjs css css-animations ng-animate

基本上,我试图在“最近的操作”中受影响的某些元素上显示动画。该动画完成后不应再次播放。我目前遇到的问题是我还定义了一个在“选择”元素时运行的动画。取消选择该元素后,即使已达到 animation-iteration-count 1,原始动画也会再次播放。我当然可以为 animationend 触发时设置一个事件监听器,然后删除与动画关联的类。我更想解释为什么这不能按预期工作。我想这与 question 相反.

document.querySelector('.one-time-animation').addEventListener("click", function(e) {
	e.target.classList.toggle('selected');
})
.one-time-animation {
    animation: one-time-animation 2s forwards 1;
}

.selected {
    animation: selected 2s forwards 1;
}

@keyframes one-time-animation {
    from {
        background:red;
    }
    to {
        background:transparent;
    }
}

@keyframes selected {
    from {
        box-shadow: 0 0 0 green inset;
    }
    to {
        box-shadow: 0 0 10px green inset;
    }
}
<div class="one-time-animation">Click to toggle selected class</div>

最佳答案

纯 CSS 解决方案:(不会污染所选样式)

假设所提供的动画与您的应用程序中使用的完全相同,而不仅仅是一些随机样本,您实际上可以将其替换为 transition 而不是 animation 。这也将确保原始动画永远不会被删除,因此永远不会重播。

document.querySelector('.one-time-animation').addEventListener("click", function(e) {
  e.target.classList.toggle('selected');
})
.one-time-animation {
  animation: one-time-animation 2s forwards 1;
}
@keyframes one-time-animation {
  from {
    background: red;
  }
  to {
    background: transparent;
  }
}

/* do the following changes */

.selected {
  box-shadow: 0 0 10px green inset;
  transition: box-shadow 2s ease;
}

/* the below is generally not required but if the box-shadow just appears instantly instead of gradually then uncomment it
div {
  box-shadow: 0 0 0 green inset;
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>


原因:

动画正在按照规范运行。单击时,当 selected 类添加到元素时,它不再具有一次性动画。这是因为 animation 属性的最新指定值会覆盖先前指定的值(正如 shennan 正确指出的那样)。

selected类关闭时,一次性动画变得适用,并且现在用户代理不记得该动画已经存在于较早的元素。即使 animation-iteration-count 设置为 1,这也会导致动画重新执行。

解决此问题的一种方法是让用户代理知道原始动画从未真正从元素中删除。这可以通过将其保留为 selected 类中堆栈的一部分来执行。动画属性可以支持逗号分隔格式的多个动画。原始动画不会再次运行,因为用户代理现在将其视为曾经存在,从而维护迭代计数器。

document.querySelector('.one-time-animation').addEventListener("click", function(e) {
  e.target.classList.toggle('selected');
})
.one-time-animation {
  animation: one-time-animation 2s forwards 1;
}
.selected {
  animation: one-time-animation 2s forwards 1, selected 2s forwards 1;
}
@keyframes one-time-animation {
  from {
    background: red;
  }
  to {
    background: transparent;
  }
}
@keyframes selected {
  from {
    box-shadow: 0 0 0 green inset;
  }
  to {
    box-shadow: 0 0 10px green inset;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>

如果无法将原始动画添加为 selected 类的堆栈的一部分(比如因为它用于多个元素,每个元素都有不同的原始动画),那么该方法应该是要获取当前的动画,请将选择的动画附加到其上,然后通过JS进行设置。

我不是 JS 专家,但下面的代码片段应该能让你明白我的意思。

var i = false;

document.querySelector('.one-time-animation').addEventListener("click", function(e) {
  var style = window.getComputedStyle(e.target);
  var currAnim = style.getPropertyValue(PrefixFree.prefix + 'animation-name') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-duration') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-fill-mode') + ' ' + style.getPropertyValue(PrefixFree.prefix + 'animation-iteration-count');
  var newAnim;
  if (!i)
    newAnim = currAnim + ', selected 2s forwards 1;';
  else
    newAnim = currAnim.substring(0, currAnim.indexOf(','));
  e.target.setAttribute('style', PrefixFree.prefix + 'animation: ' + newAnim);
  i = !i;
});
.one-time-animation {
  animation: one-time-animation 2s forwards 1;
}
@keyframes one-time-animation {
  from {
    background: red;
  }
  to {
    background: transparent;
  }
}
@keyframes selected {
  from {
    box-shadow: 0 0 0 green inset;
  }
  to {
    box-shadow: 0 0 10px green inset;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="one-time-animation">Click to toggle selected class</div>

关于angularjs - 在定义不同动画的同一元素上切换类时,是否可以限制 CSS 动画仅播放一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32832833/

相关文章:

javascript - AngularJS : concatenate depending on variable value

javascript - 如何使用 Highcharts 和大量动态数据构建 Angular

带有类选择器的 CSS last-child

css - 在angular js中用空格加入逗号

react-native - 动画从 360 度旋转到 0 度 - iOS 传感器

javascript - 第一次单击时播放关键帧动画,第二次单击时反向播放

javascript - 如何在 ionic (angular.js)中调用相同服务的其他功能

javascript - 在 angularjs 服务之间共享数据而不会出现循环依赖错误?

javascript - CSS3 动画后的 iOS 右侧空白

jquery - 不能按 ID 选择对象,只能用 jQuery 按类选择对象?