为什么在具有范围样式的Vue组件中破坏了CSS关键帧动画? [英] Why are CSS keyframe animations broken in Vue components with scoped styling?

查看:47
本文介绍了为什么在具有范围样式的Vue组件中破坏了CSS关键帧动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Vue中实现CSS输入指示器.没有Vue,它看起来像这样:

I'm trying to implement a CSS typing indicator in Vue. Without Vue, it looks like this:

.typing-indicator {
  background-color: #E6E7ED;
  width: auto;
  border-radius: 50px;
  padding: 20px;
  display: table;
  margin: 0 auto;
  position: relative;
  -webkit-animation: 2s bulge infinite ease-out;
          animation: 2s bulge infinite ease-out;
}
.typing-indicator:before, .typing-indicator:after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: -2px;
  height: 20px;
  width: 20px;
  border-radius: 50%;
  background-color: #E6E7ED;
}
.typing-indicator:after {
  height: 10px;
  width: 10px;
  left: -10px;
  bottom: -10px;
}
.typing-indicator span {
  height: 15px;
  width: 15px;
  float: left;
  margin: 0 1px;
  background-color: #9E9EA1;
  display: block;
  border-radius: 50%;
  opacity: 0.4;
}
.typing-indicator span:nth-of-type(1) {
  -webkit-animation: 1s blink infinite 0.3333s;
          animation: 1s blink infinite 0.3333s;
}
.typing-indicator span:nth-of-type(2) {
  -webkit-animation: 1s blink infinite 0.6666s;
          animation: 1s blink infinite 0.6666s;
}
.typing-indicator span:nth-of-type(3) {
  -webkit-animation: 1s blink infinite 0.9999s;
          animation: 1s blink infinite 0.9999s;
}

@-webkit-keyframes blink {
  50% {
    opacity: 1;
  }
}

@keyframes blink {
  50% {
    opacity: 1;
  }
}
@-webkit-keyframes bulge {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}
@keyframes bulge {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}
html {
  display: table;
  height: 100%;
  width: 100%;
}

body {
  display: table-cell;
  vertical-align: middle;
}

<div class="typing-indicator">
  <span></span>
  <span></span>
  <span></span>
</div>

–来源: http://jsfiddle.net/Arlina/gtttgo93/

问题是,将 scoped 属性添加到组件的样式定义(< style lang ="scss"范围> )时,动画不起作用.我认为这可能与应该在全局范围内声明的关键帧有关.

The problem is that the animation does not work when adding the scoped attribute to the component's style definition (<style lang="scss" scoped>). I believe it may be related to keyframes that should be declared globally.

具有 .typing-indicator 的元素位于具有范围样式的组件的模板中.

The element with .typing-indicator is in the template of the component with scoped styling.

有人知道如何在使关键帧动画正常工作的同时允许我的组件具有范围化样式吗?

Does anyone have an idea of how I can allow my component to have scoped styling while making the keyframe animations work?

推荐答案

问题

问题出在Vue的Webpack加载器( vue-loader )错误地,在将ID添加到作用域选择器和其他标识符时解析动画名称.这很重要,因为vue-loader的CSS作用域使用添加到元素的唯一属性来复制CSS作用域的行为.虽然您的关键帧名称会附加ID,但在作用域样式中的动画规则中不会引用关键帧.

Problem

The problem is down to how the Webpack loader for Vue (vue-loader), incorrectly, parses animation names when adding IDs to scoped selectors and other identifiers. This is important because vue-loader's CSS scoping uses unique attributes added to elements to replicate the behaviour of CSS scoping. While your keyframe names get IDs appended, references to keyframes in animation rules in scoped styles do not.

您的CSS:

@-webkit-keyframes blink {
  50% {
    opacity: 1;
  }
}

@keyframes blink {
  50% {
    opacity: 1;
  }
}
@-webkit-keyframes bulge {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}
@keyframes bulge {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}

.typing-indicator {
  ...
  -webkit-animation: 2s bulge infinite ease-out;
          animation: 2s bulge infinite ease-out;
}

.typing-indicator span:nth-of-type(1) {
  -webkit-animation: 1s blink infinite 0.3333s;
          animation: 1s blink infinite 0.3333s;
}
.typing-indicator span:nth-of-type(2) {
  -webkit-animation: 1s blink infinite 0.6666s;
          animation: 1s blink infinite 0.6666s;
}
.typing-indicator span:nth-of-type(3) {
  -webkit-animation: 1s blink infinite 0.9999s;
          animation: 1s blink infinite 0.9999s;
}

应转换为:

@-webkit-keyframes blink-data-v-xxxxxxxx {
  50% {
    opacity: 1;
  }
}

@keyframes blink-data-v-xxxxxxxx {
  50% {
    opacity: 1;
  }
}
@-webkit-keyframes bulge-data-v-xxxxxxxx {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}
@keyframes bulge-data-v-xxxxxxxx {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}

.typing-indicator {
  ...
  -webkit-animation: 2s bulge-data-v-xxxxxxxx infinite ease-out;
          animation: 2s bulge-data-v-xxxxxxxx infinite ease-out;
}

.typing-indicator span:nth-of-type(1) {
  -webkit-animation: 1s blink-data-v-xxxxxxxx infinite 0.3333s;
          animation: 1s blink-data-v-xxxxxxxx infinite 0.3333s;
}
.typing-indicator span:nth-of-type(2) {
  -webkit-animation: 1s blink-data-v-xxxxxxxx infinite 0.6666s;
          animation: 1s blink-data-v-xxxxxxxx infinite 0.6666s;
}
.typing-indicator span:nth-of-type(3) {
  -webkit-animation: 1s blink-data-v-xxxxxxxx infinite 0.9999s;
          animation: 1s blink-data-v-xxxxxxxx infinite 0.9999s;
}

但是只能转换为:

@-webkit-keyframes blink-data-v-xxxxxxxx {
  50% {
    opacity: 1;
  }
}

@keyframes blink-data-v-xxxxxxxx {
  50% {
    opacity: 1;
  }
}
@-webkit-keyframes bulge-data-v-xxxxxxxx {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}
@keyframes bulge-data-v-xxxxxxxx {
  50% {
    -webkit-transform: scale(1.05);
            transform: scale(1.05);
  }
}

.typing-indicator {
  ...
  -webkit-animation: 2s bulge infinite ease-out;
          animation: 2s bulge infinite ease-out;
}

.typing-indicator span:nth-of-type(1) {
  -webkit-animation: 1s blink infinite 0.3333s;
          animation: 1s blink infinite 0.3333s;
}
.typing-indicator span:nth-of-type(2) {
  -webkit-animation: 1s blink infinite 0.6666s;
          animation: 1s blink infinite 0.6666s;
}
.typing-indicator span:nth-of-type(3) {
  -webkit-animation: 1s blink infinite 0.9999s;
          animation: 1s blink infinite 0.9999s;
}

注意事项:在实际转换中,动画规则中对关键帧名称的引用在最后缺少 -data-v-xxxxxxxx .这是错误.

Something to note: in the actual transformation, references to keyframe names in animation rules are missing the -data-v-xxxxxxxx at the end. This is the bug.

当前(截至 47c3317 )是简写动画规则声明中的动画名称通过从用任何空格字符分割动画规则中获取第一个值来标识

Currently (as of 47c3317) the animation name in shorthand animation rule declarations is identified by getting the first value out of splitting the animation rule by any whitespace character[1]. However the formal definition for the animation property states the animation name could appear anywhere within the rule definition.

< single-animation>=< time>||<单定时功能>||<时间>||<单一动画迭代次数>||<单一动画方向>||<单动画填充模式>||<单一动画播放状态>||[无|< keyframes-name>]

animation 正式语法 [2]

animation formal syntax[2]

因此,当您的动画声明有效时,vue-loader无法解析它.

Therefore, while your animation declarations are valid, vue-loader is not able to parse it.

当前的解决方法是将动画名称移动到动画规则声明的开头.您的关键帧声明不需要更改,它们保留在作用域样式表中.您的动画声明现在应如下所示:

The current workaround for this is to move your animation names to the beginning of animation rule declarations. Your keyframe declarations do not need changing, they remain inside the scoped stylesheet. Your animation declarations should now look like this:

.typing-indicator {
  ...
  -webkit-animation: bulge 2s infinite ease-out;
          animation: bulge 2s infinite ease-out;
}
.typing-indicator span:nth-of-type(1) {
  -webkit-animation: blink 1s infinite 0.3333s;
          animation: blink 1s infinite 0.3333s;
}
.typing-indicator span:nth-of-type(2) {
  -webkit-animation: blink 1s infinite 0.6666s;
          animation: blink 1s infinite 0.6666s;
}
.typing-indicator span:nth-of-type(3) {
  -webkit-animation: blink 1s infinite 0.9999s;
          animation: blink 1s infinite 0.9999s;
}

参考

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