International practice first look at the final implementation effect ~
Project Background (Bullshit)
During the World Cup, the company pulled up a beer sponsorship. There was a sharing event where pian friends were invited to get mai members to drink beer. Up to eight bottles of beer earned a case. Tempting as it may sound, there’s nothing better in the world than watching a ball, having a drink and flirting (it doesn’t).
The preparatory work
My job was to make it cool, because I’m a bit of an art bug, and I came up with the rocking and rising animation right away. I rolled up my sleeves, opened Codepen with my backhand, searched for the keywords “beer shaking”, “beer pouring”, and finally found an example that I was happy with. I’m really a smart cookie. I’ll just change the code.
twist
When I was smug, I got the corresponding design draft. WTF??? Is this bottle a diagram? Is this bubble still moving? The wine in this picture has to rise? Come on, you can do it… Because the wine bottle is a customized picture, there is no way to customize the color and height of the wine, even if the absolute positioning is difficult to harmonize, which requires animation, I will do! @ # $%…… &* No, I have to calm down, I’ll figure it out!
implementation
Finally ushered in the body (I am really not a consumption), after some thinking, I found that the difficulties are mainly in the following three aspects: 1. Beer foam animation 2. Beer rising animation 3. After the rising animation of a bottle is complete, the next beer animation can be started
The first two problems are customized, so it is not possible to use CSS to draw, can only be used to replace the image (GIF), that is, dynamic replace img tag SRC, practice, this implementation effect is good, can not see the trace of switching, of course, if the network speed is slow, You can pre-load all images to be replaced for caching, which makes switching smoother. As for the last question, if you think about it, does it look like the same thing? Isn’t making one damn Promise after you finish another one? , nonsense do not say directly on the code:
// Define the addresses of the 10 images first
const pics = [
'1.gif'.'2.gif'.'3.gif'.'4.gif'.'5.gif'.'6.gif'.'7.gif'.'8.gif'.'9.gif'.'10.png'
];
const pouredQuantity = 2.1; // Number of bottles that have been filled
const pourQuantity = 0.2; // The amount of alcohol consumed this time
const max = Math.ceil(pouredQuantity);
const startIndex = max === pouredQuantity ? max : max - 1; // The number of the bottle that started filling
@param {Number} leftQuantity * @param {Number} total Number of drinks */
function recursion(index, leftQuantity, total) {
if (leftQuantity === 0) {
// The callback can be executed after the animation is completed
return;
}
const decimal = total - index === 0 ? 0 : calc(total, -index);
new Promise(resolve= > {
const start = decimal === 0 ? 1 : decimal * 10 + 1;
const end =
decimal + leftQuantity >= 1
? pics.length
: calc(decimal, leftQuantity) * 10;
pourAnimation($bottles[index], start, end, resolve);
}).then((a)= > {
index++;
const left =
decimal + leftQuantity > 1 ? calc(leftQuantity, -calc(1, -decimal)) : 0;
recursion(index, left, calc(total, calc(leftQuantity, -left)));
});
}
recursion(startIndex, pourQuantity, pouredQuantity);
* @param {Element} ele * @param {Number} start * @param {Number} end * @param {Function} resolve */
function pourAnimation(ele, start, end, resolve) {
let index = start - 1;
(function loop() {
ele.src = pics[index];
index++;
if (index < end) {
setTimeout(loop, 300);
} else {
resolve();
}
})();
}
@param {Number} a * @param {Number} b */
function calc(a, b) {
return parseFloat((a + b).toFixed(1));
}
Copy the code
Except for several auxiliary methods, the core code is all in the recursive method. The main idea is to first grade the beer capacity (here is 10 equal points). After the animation of a beer is completed, call the Resolve method of Promise and then execute the animation of the next beer. The animation is done by replacing the beer image with a setTimeout.
conclusion
Actually, any problems after think the thing is, most of the questions are seeking solutions in specific situations, so we need to do is to try to nature of thinking, think about the pain points where the difficulty, to the level of abstraction problem, modeling, and then slowly, you will find that most of the problems you have encountered and solved before, The problem is no longer a problem ~ (BTW, the algorithm in this paper has not been simplified, if there is a better method can also be discussed)