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:
- Using animation
- Use transform and Transition
Second, javascript also has the concept of motion functions:
-
Friends can refer to this article
-
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 vue
transition
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:
- Get the ball and innerBall
- Calculate the distance x and y from the position of the ball to the position of the cart
- Reset the ball position to its original position
In the animation execution phase, we need:
- Let the ball move along the x axis
- Let’s move the innerBall along the Y-axis
- 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: