Home > Software design >  Split animation with Vue
Split animation with Vue

Time:10-11

I'm struggling with creating split animation with two icons. I want to split icons with some translation in X axis after hover on container but it seems that I'm doing something wrong. On codepen its not even animating, in my app its working but icons return to their original position after animation, forwards property doesn't help.

<html>
  <head>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <div @mouseenter="showButtons()" @mouseleave="hideButtons()" >
        <transition name="icon-left">
          <span v-show="show_buttons"> A </span>
        </transition>
        <transition name="icon-right">
          <span v-show="show_buttons"> B </span>
        </transition>
      </div>
    </div>
  </body>
</html>


const { createApp } = Vue

createApp({
  data() {
    return {
      show_buttons: false,
    }
  },
  methods: {
    showButtons() {
      this.show_buttons = true
    },
    hideButtons() {
      this.show_buttons = false
    }
  }
}).mount('#app')


.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 800px;
  height: 400px;
  border: 1px black solid ;
}
.icon-left-enter-from {
  opacity: 0;
  transform: translate(0px);
}
.icon-left-enter-active {
  transition: all 0.3s forwards;
}
.icon-left-enter-to {
  opacity: 1;
  transform: translate(-200px);
}

.icon-right-enter-from {
  opacity: 0;
  transform: translate(0px);
}
.icon-right-enter-active {
  transition: all 0.3s forwards;
}
.icon-right-enter-to {
  opacity: 1;
  transform: translate(200px);
}

Here is live codepen https://codepen.io/dymek662/pen/bGMxJwY

CodePudding user response:

Here I have it working: https://codepen.io/yoduh/pen/yLjRRRN

I slowed the left one down so you can see the opacity change more clearly. Here's all the relevant code:

<transition name="icon-left" >
  <span v-show="show_buttons"> A </span>
</transition>
<transition name="icon-right" >
  <span v-show="show_buttons"> B </span>
</transition>
.icon-left-enter-from {
  opacity: 0
}
.icon-left-enter-active {
  animation: left-translate 3s;
  transition: opacity 3s;
}
.left {
  transform: translate(-200px);
}

@keyframes left-translate {
  0% {
    transform: translate(0px);
  }
  100% {
    transform: translate(-200px);
  }
}

.icon-right-enter-active {
  animation: right-translate 0.3s;
  transition: opacity 0.3s;
}
.right {
  transform: translate(200px);
}

@keyframes right-translate {
  0% {
    transform: translate(0px);
  }
  100% {
    transform: translate(200px);
  }
}

"forwards" is not used with transition, but with animation instead, specifically it is shorthand for animation-fill-mode. If you want to maintain the end state, you should use animation. However, animation-fill-mode: forwards only holds the final animation state for as long as the animation property exists, e.g. for as long as a hover event is ongoing. In your case, once the animation is complete the animation property is removed. There is a workaround which is to set the "default" state of your element to match the final state of your animation. That's why I added a separate left and right class to always apply the translate transformation as long as the elements are visible (and not currently animating)

  • Related