Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
272 views
in Technique[技术] by (71.8m points)

css - Extend the final state of the first animation for translated element

I know this is asked multiple times here, but I am asking for a different approach for these kind of animations.

Problem:

The 2nd box has multiple animations, trying to create the same effect as 1st one. It seems like the transform property is getting overwritten (as it should)*. I am trying to extend the 1st animation (of 2nd box) with the properties of 2nd animation. Tried to use animation-fill-mode: forwards but with no success. Maybe I am missing something basic. Is it possible with vanilla CSS?

*Reference

The ‘animation-name’ property defines a list of animations that apply. If multiple animations are attempting to modify the same property, then the animation closest to the end of the list of names wins.


Requirement:

Separate move2-right and move2-down key-frames rules but work on the same element, preserving the 1st animation transformation. If there is an alternate approach to this kind of animation, please guide me through it.


Current output:

.animation-1,
.animation-2 {
  width: 200px;
  height: 200px;
  display: inline-block;
  background: white;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.movable-1,
.movable-2 {
  background: #41A186;
  width: 50px;
  height: 50px;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
  text-align: center;
  vertical-align: middle;
  line-height: 50px;
}
.movable-1 {
  -webkit-animation-name: move1;
  animation-name: move1;
  -webkit-animation-duration: 4s;
  animation-duration: 4s;
  -webkit-animation-delay: 0s;
  animation-delay: 0s;
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}
.movable-2 {
  -webkit-animation-name: move2-right, move2-down;
  animation-name: move2-right, move2-down;
  -webkit-animation-duration: 2s, 2s;
  animation-duration: 2s, 2s;
  -webkit-animation-delay: 4s, 6s;
  animation-delay: 4s, 6s;
  -webkit-animation-fill-mode: forwards, forwards;
  animation-fill-mode: forwards, forwards;
}
@-webkit-keyframes move1 {
  0% {
    -webkit-transform: translateX(0px);
    transform: translateX(0px);
  }
  50% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
  100% {
    -webkit-transform: translateX(30px) translateY(50px);
    transform: translateX(30px) translateY(50px);
  }
}
@keyframes move1 {
  0% {
    -webkit-transform: translateX(0px);
    transform: translateX(0px);
  }
  50% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
  100% {
    -webkit-transform: translateX(30px) translateY(50px);
    transform: translateX(30px) translateY(50px);
  }
}
@-webkit-keyframes move2-right {
  0% {
    -webkit-transform: translateX(0px);
    transform: translateX(0px);
  }
  50% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
  100% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
}
@keyframes move2-right {
  0% {
    -webkit-transform: translateX(0px);
    transform: translateX(0px);
  }
  50% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
  100% {
    -webkit-transform: translateX(30px);
    transform: translateX(30px);
  }
}
@-webkit-keyframes move2-down {
  0% {
    -webkit-transform: translateY(0px);
    transform: translateY(0px);
  }
  50% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
  }
  100% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
  }
}
@keyframes move2-down {
  0% {
    -webkit-transform: translateY(0px);
    transform: translateY(0px);
  }
  50% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
  }
  100% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
  }
}
<div class="animation-1">
  <div class="movable-1">1</div>
</div>
<div class="animation-2">
  <div class="movable-2">2</div>
</div>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As far as I am aware this is not possible with pure CSS because (as you have already indicated), when we add an extra transformation rule to an element which already has a transform, the whole transform gets reset because it overwrites and does not append to the existing transform.

With JS this might be possible to achieve but even there it is going to be tough because we have to do the following:

  • Handle the animationend event on completion of the first animation.
  • In the handler, get the translateX(...) in pixels.
  • Get the CSS keyframe rules of the next animation, modify them to take the translateX(...) as the first part of the transform stack.

Note: I assume that you have a case where there is absolutely no way for you to use the first method mentioned in the question.


An alternate method to achieve a similar effect would be to animate the margin or position of an element instead of using transform: translate(). One major downside to this approach is that this would not done at the GPU layer (unlike transform) and hence would be slower when multiple such animations happen at the same time (and could also be expensive).

Using Margins:

The below snippet achieves the effect by animating margin-left and margin-top properties.

.animation-1,
.animation-2,
.animation-3 {
  width: 200px;
  height: 200px;
  display: inline-block;
  background: white;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
  vertical-align: middle;
}
.movable-1,
.movable-2,
.movable-3 {
  background: #41A186;
  width: 50px;
  height: 50px;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
  text-align: center;
  vertical-align: middle;
  line-height: 50px;
}
.movable-1 {
  animation-name: move1;
  animation-duration: 4s;
  animation-delay: 0s;
  animation-fill-mode: forwards;
}
.movable-2 {
  animation-name: move2-right, move2-down;
  animation-duration: 2s, 2s;
  animation-delay: 4s, 6s;
  animation-fill-mode: forwards, forwards;
  animation-timing-function: linear;
}
.movable-3 {
  animation-name: move3-diagonal;
  animation-duration: 4s;
  animation-delay: 8s;
  animation-fill-mode: forwards;
  animation-timing-function: linear;
}
@keyframes move1 {
  0% {
    transform: translateX(0px);
  }
  50% {
    transform: translateX(30px);
  }
  100% {
    transform: translateX(30px) translateY(50px);
  }
}
@keyframes move2-right {
  0% {
    margin-left: 0px;
  }
  100% {
    margin-left: 30px;
  }
}
@keyframes move2-down {
  0% {
    margin-top: 0px;
  }
  100% {
    margin-top: 50px;
  }
}
@keyframes move3-diagonal
 {
  0% {
    margin-top: 0px;
    margin-left: 0px;
  }
  100% {
    margin-top: 50px;
    margin-left: 30px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="animation-1">
  <div class="movable-1">1</div>
</div>
<div class="animation-2">
  <div class="movable-2">2</div>
</div>
<div class="animation-3">
  <div class="movable-3">3</div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...