This is the 13th day of my participation in the August More Text Challenge.More challenges in August

The animation of goods flying into shopping cart is a common effect of shopping apps, such as Meituan Takeout and Ele. me takeout, etc. The animation effect of flying in can be realized in various ways.

1. Technical solution

In the first scheme, there are two methods based on CSS3 to achieve the same effect:

  1. Using animation
  2. Use transform and Transition

Second, javascript also has the concept of motion functions:

  1. Friends can refer to this article

  2. Zhang Xinxu has a blog post about javascript parabolic motion, which is very detailed:

    Parabolic trajectories between JavaScript and elements

The third solution, in VUE, provides a component for transition: Transition

In general, I prefer to combine cSS3 with animation in VUE.

2. Straight motion

Transform and Transition can only control one object to move in a straight line. For example:

  <style>
    #ball{
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: red;
      transition: all 1s linear;
    }
  </style>
  <body>
    <div id="ball"></div>
  </body>
  <script>
     setTimeout(function(){
      ball.style.transform= "translate(800px, 500px)";
     },1000)
  </script>
Copy the code

The effect of this code is to fly a ball from coordinate [0,0] to coordinate [800,500] for 1s

If we want to implement a path that looks like a parabola, we have to start with bezier curves.

3. Cubic Bezier curve

Here’s a blog about the Bezier curve that goes a little deeper: Click me

Of course, it’s a little overkill to understand bezier curves purely from a mathematical point of view. This is a CSS3 Bessel curve tool, CSS3 Bessel curve template website, can be used for debugging curves

Of course, you’ve probably seen Bezier curves before, if you’ve used jquery animations.

The timing-function set in jquery animation, such as easy, easy-in, easy- out, etc., is actually written Bezier curve.

Essentially, the Bezier curve is used to control the speed of the animation, which basically means that the change is constant, right? Or is it faster then slower? Or slow first and then fast?

It’s not the path that the ball takes, and in fact, even with Bezier, a ball travels in a straight line.

That’s because the motion of objects is always influenced by the x and y axes, and when the two axes are controlled by the same transition, they always merge into a fixed direction.

It’s like synthesizing forces in high school physics.

You can see the effect of the Bezier curve here, but I won’t go over it.

According to the above statement, a simple summary:

To make the object move in a curve, we can create two objects, one is responsible for the animation on the X axis and the other is responsible for the animation on the Y axis, and the duration of the animation should be exactly the same, but the timing function is not synchronized, so that the motion of the two objects will affect each other and form a curve motion track.

4, code,

Let’s do a simple example.

First, we need to lay out two objects, one moving along the x axis and the other moving along the y axis.

<template>
  <div class="home">
    <div class="cart">cart</div>
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter"
    >
      <div class="ball" v-show="ball.show">
        <div class="innerBall">
          <i class="iconfont icon-xingxing"></i>
        </div>
      </div>
    </transition>
    <div class="menu" @click="addToCart($event)">menu</div>
  </div>
</template>
Copy the code

So here we have three things

  • Shopping cart cart
  • Menu, a button for clicking
  • The ball consists of two divs, the outer ball and the innerBall, called innerBall, using the built-in components of vuetransition

Next we’ll define some simple CSS styles.

<style lang="scss">
.cart..ball {
  position: fixed; right: 700px; top: 100px;
}
.cart {
  border: 1px solid blue; padding: 5px 12px;
}
.ball {
  width: 10px;  height: 10px; transition: all 1s cubic-bezier(0.49, -0.29.1.1);
}
.innerBall {
  width: 10px; height: 10px; transition: all 1s linear;
}
.menu {
  position: absolute; top: 500px; left: 50px; border: 1px solid blue; 
  padding: 5px 12px; cursor: pointer;
}
</style>
Copy the code

For the ball and innerBall, we use the TRANSITION of CSS3 to add the effect of transition. We make the ball’s motion model be Cubic – Bezier (0.49, -0.29, 1, 1). The innerBall’s motion model is Linear

The Transition component of vue allows you to define animations during transitions, either using CSS class names or by binding events

There are six CSS class names as follows:

Instead of using class names, I’m going to use JS events. Here I’ll briefly state the event logic:

The events are divided into before,after, and after the animation starts. The names of the binding events are before-Enter, Enter, and after-Enter

Before the animation starts, we need:

  1. Get the ball and innerBall
  2. Calculate the distance x and y from the position of the ball to the position of the cart
  3. Reset the ball position to its original position

In the animation execution phase, we need:

  1. Let the ball move along the x axis
  2. Let’s move the innerBall along the Y-axis
  3. The motion is implemented by transform: Translate

After the animation technique, we hid the ball so that when we reworked the ball’s position before the animation started, the user wouldn’t see it.

Here’s the code, and I’ve commented it out

<script>
export default {
  name: 'home'.data() {
    return {
      ball: {
        el: null.show: false,}}},methods: {
    beforeEnter(el) {
      let ele = this.ball.el // The item to add to the cart
      let ract = ele.getBoundingClientRect() // The location of the item
      let elRight = this._getStyle(el, 'right') // Shopping cart right
      let elTop = this._getStyle(el, 'top') // Shopping cart top
      let x = window.innerWidth - ract.left - parseFloat(elRight) // Calculate the X-axis distance that the ball moves
      let y = ract.top - parseFloat(elTop)// Calculate the distance of the ball moving along the Y-axis

      el.style.display = ' '
      el.style.transform = `translateY(${y}px)` // Reset the ball's X-axis position

      let innerBall = el.querySelector('.innerBall')
      innerBall.style.transform = `translateX(-${x}px)`// Reset the ball's Y-axis position
    },
    enter(el, done) {
      this._offset = document.body.offsetHeight // Activate redraw

      el.style.transform = `translate(0, 0)` // The ball moves along the Y-axis to the cart

      let innerBall = el.querySelector('.innerBall')
      innerBall.style.transform = `translate(0, 0)`// The ball moves along the X-axis to the cart

      el.addEventListener('transitionend', done)
    },
    afterEnter(el) {
      this.ball.show = false
      el.style.display = 'none'
    },
    addToCart(event) {
      this.ball.el = event.target
      this.ball.show = true
    },
    _getStyle(el, attr) {
      return el.currentStyle
        ? el.currentStyle[attr]
        : getComputedStyle(el, false)[attr]
    },
  },
}
</script>

Copy the code

After that, let’s start the local service and see what it looks like in the browser: