This article will use the dynamic effect factory from 0 to 1 to build and generate a variety of particle animation, using the visual editing ability, and you can achieve through simple operation, I will show you step by step how to achieve a particle Action, precisely according to a business to achieve a custom Action.
Here are a few things you can learn from reading this article:
- How to implement a custom action
- How to use the dynamic effect factory
Dynamic effect factory
Before implementing custom actions, LET me briefly introduce the background of our project. What is a kinetic factory?
Our team used a lot of dynamic effect scenes, so we deposited some dynamic effect, in order to better reuse in the next encounter. So how many dynamic effects we can support, or which dynamic effects can be reused, can be found in the dynamic effect factory.
At this time, some students will say that these things do not meet the needs of the general, so there is a custom action, that is, to achieve an animation that does not have a dynamic effect library, and then submit to the dynamic effect library, there are similar dynamic effects, others can reuse.
Particle animations
Here I take you to achieve a particle animation, first or explain what is the particle animation ????
Particle animation is composed of a large number of randomly generated particles in a certain range of motion animation, is widely used in the simulation of weather system, smoke light effect and other aspects. In the micro-gamification scenes of e-commerce platforms, particle animation is mainly used to present special effects in energy collection and gold coin collection.
Here I have prepared two examples for you to use in our business scenario:
The above particles or not enough, and to the particles affixed with the corresponding texture, and then some animation to show, so as to achieve a visual feeling very cool state, is a lot of 💰 feeling!
Creating a particle class
In fact, no matter what kind of particle effect, you just look at the effect you do not know how to analyze this animation. In fact, to analyze animation, we can first look at how a particle changes. Take a look at the picture below:
Particle A on the canvas, it could be A linear change, it could be A parabola, it could be our third-order Bessel curve. But all changes are essentially changes in x and y, but x goes from x0 to x1, and y goes from y0 to y1, so it actually corresponds to this one particle which has two properties, vx and vy. The most basic properties of such a particle are actually enough for basic animation. Let’s write the following code:
class Particle {
constructor(x = 0, y = 0) {
this.x = x
this.y = x
this.radius = 1
this.vx = 0
this.vy = 0
this.color = 'hsla(197,100%,50%,80%)'
}
draw(ctx) {
ctx.save()
ctx.fillStyle = this.color
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
ctx.restore()
}
move() {
this.x += this.vx
this.y += this.vy
}
}
Copy the code
So we can actually construct the properties that we need for the current particle. But at this time we still need a particle manager to manage all the particles, mainly for
- Control the number of particles
- Generate multiple types of particles
- Perform render operation
- What is the interval between the x and y velocity of the control particle
In fact, this is called unified management, so I won’t show you the code. These actions are actually configurations of particle actions
The ACTION to write
Let’s go to this directory
This contains all the actions in our action factory, for example, I’m actually creating a new particle-action.ts
Here’s how the basic structure of the next action is implemented.
ActionConfig, in this case, refers to the properties corresponding to the action factory visual view. We will have some default properties, which are fixed for each action, but there will also be special cases to keep. Then you export an Action function
So let’s see how it’s written here, it’s all fixed. But I want to be clear:
First of all, the action must be on the View, in the action factory is actually the corresponding View
And then we’re going to have some parameters for a slow animation, so let’s look at the code
export const particleAction: Action<particleActionConfig> = ( view: View, { timing, color, radius, duration, ... config }, ) => { let ctx: CanvasRenderingContext2D | null return (time: number) => { const progress = useProgress(time, timing, duration, config) useOnce(() => { ctx = view.makeCanvas().getContext('2d') }) if (ctx) { view.addLayer(ctx.canvas) } } }Copy the code
Two separate hooks are used here
UseOnce and useProgress
The main reason for using a hook is to make it easier for an action to interact with a frame when it is called.
Set or get the duration of the current frame
useCache
Caches variables to keep the action running
useState
Save and modify the state of the action
useOnce
It is executed only once in the lifetime of the Frame.
useFinish
Execute when the Frame is removed
useContext
Gets the current wind of the frame.
useProgress
Get the current progress
useOnce
In fact, it’s a bit like a singleton, we only create it once, because the above function is called every frame, so to avoid the problem of duplicate creation
I’m just going to say a little bit about this line of code
ctx = view.makeCanvas().getContext(‘2d’)
In fact, the View is just something we abstract out. Whatever you do, that is, render the image, depends on the canvas. So all the makeCanvas instance methods on the view, and all the subsequent actions, are rendered on this canvas to animate.
2D is actually the simplest and most commonly used method, but Canvas has not only 2D but also WebGL and WebGL2.
In fact, to say the truth, it is OK for us to expand the 3D capability behind this thing. In fact, I also made some attempts, but since there are not many business scenes, it is also displayed by myself.
I can share with you the animation I made with our Motion Effects Factory 3D.
Okay, so let’s get back to our particle action
Take a look at this picture:
If you have a particle moving in a fixed view, if you move the boundary, what happens to the velocity, what’s called collision detection
What I’m doing here is I have a spring coefficient, and when the particle moves to the boundary where the vx and vy directions of the particle go in opposite directions, if collision detection is not turned on, what I’m doing here is changing the position of the particle, setting the x and y values of the particle at the corresponding positions. Look at the graph below
I’m just going in one direction. The code is as follows:
// Collision detection
checkWall(isWallCollisionTest = true, bounce = 1, W = 1000, H = 1000) { if (isWallCollisionTest) { if (this.x + this.radius > W) { this.x = W - this.radius; this.vx *= -bounce; } else if (this.x - this.radius < 0) { this.x = this.radius; this.vx *= -bounce; } if (this.y + this.radius > H) { this.y = H - this.radius; this.vy *= -bounce; } else if (this.y - this.radius < 0) { this.y = this.radius; this.vy *= -bounce; } } else { if (this.x - this.radius > W) { this.x = 0; } else if (this.x + this.radius < 0) { this.x = W; } if (this.y - this.radius > H) { this.y = 0; } else if (this.y + this.radius < 0) { this.y = H; }}}Copy the code
Let’s see what collision detection looks like:
The Caton here is the caton that was unrelated to the rest of us when the video was made. Canvas particles will not get stuck if the number is not enough.
Text particles
And then we expand on the current particle, the text particle. In fact, the whole canvas is actually pixels. We can implement the principle is actually very simple. There is a getImageData method in the canvas, which can get all the pixel data in a rectangular range. So let’s try to get the shape of a text.
The data property returns a Uint8ClampedArray, which can be used to view initial pixel data. Each pixel uses four 1bytes values (in order of red, green, blue, and transparent values; This is the “RGBA” format) to represent. Part of each color value is represented by 0 to 255. Each portion is assigned a contiguous index in the array, with the red portion of the upper-left pixel at index 0. Pixels are processed from left to right, and then down, traversing the entire array
So the canvas that I’m using here is 1000 by 1000, and it’s going to be 1000 on the x axis, 1000 on the y axis
In fact, RGBA(255,255,255,0) these four similar numbers represent a pixel, the 1000*1000 canvas is represented by the Uint8ClampedArray array, how many elements in total? It’s 1000 times 1000 times 4 elements
First, measureText was used to calculate the appropriate size and position of text.
const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d'); canvas.setAttribute('width', 1000); canvas.setAttribute('height', 1000); ctx.clearRect(0, 0, 1000, Font = 'bold 10p Arial' const measure = ctx.measureText(this.text) const size = 0.15 const fSize = Math.min(1000 * size * 10 / 7, 1000 * size * 10 / measure.width); Font = '${fSize}px Arial'; let left = (1000 - measure.width) / 2 - measure.width / 2; const bottom = (1000 + fSize / 10 * 7) / 2; ctx.fillText(this.text, left, bottom) const imageData = ctx.getImageData(0, 0, 1000, 1000).data for (let x = 0; x < 1000; x += 4) { for (let y = 0; y < 1000; y += 4) { const fontIndex = (x + y * 1000) * 4 + 3; if (imageData[fontIndex] > 0) { this.points.push({ x, y }) } } }Copy the code
In fact, here we get the pixels, the pixels of the text. Then we can render. Here’s the video below:
Why use an action factory?
You don’t need to rewrite any of this, you just need to know how to use our dynamic effects factory, simple configuration can generate the above particle animation.
Configure it on the page
You can configure it in this page, configure the property that corresponds to the current action, and then this is related to our DSL, so you have to name this property carefully. I will analyze it step by step in a later article.
Analysis of the animation
The above text particle animation from the animation point of view is 4 keyframes, and then to the step to switch. And that actually corresponds to our kinetic effect factory which is actually the timeline that looks like this
The animation parameters corresponding to my first keyframe, and the duration; Then the end of the first frame, play the second 幁.
So the corresponding view is actually four views, because the view corresponds to the action one-to-one, or one-to-many.
The root node has four views under the root node:
Then we select any view and click the + sign to select the bullet box as follows:
Select the particle, and then the progress bar will appear below, click, you can edit in the animation properties.
We set the parameters of the text, the size of the text particle.
As shown in figure:
The second delay is 1000 seconds, the third delay is 2000, and so on.
And when you look at the progress bar and see what it looks like, it makes sense
Then click the Play button to preview the animation:
HOW TO USE
This is actually very simple, click the download button in the lower left corner, will generate a TS file
The TS file contains all the information about the current view and the resource view, but you don’t need to worry about it.
Install our SDK directly
yarn install @wind/core
Copy the code
And then call
Import {play} from '@wind/core' play(animation(), {container: canvas node})Copy the code
Then it’s ready to use!
The last
If you have any questions, please share them in the comments section.
The text/Fly
Pay attention to the technology, do the most fashionable technology!