preface

This article comes from a business project requirement some time ago, to achieve a relatively complex H5 interactive animation. When it comes to animation, the common technical scheme is nothing more than the following:

  • GIF figure
  • Css3 animation properties
  • Native Javascript implementation
  • Canvas
  • WebGL

GIF and CSS3 animation properties can obviously only achieve display animation, and interactive animation through native code is very complex, but also have to consider animation compatibility and performance issues. Since WebGL can provide hardware-accelerated rendering, its rendering performance is definitely higher than that of Canvas. However, considering the compatibility comparison between Canvas and WebGL (as shown in the figure below) and comprehensive requirements of our project, canvas was selected for implementation in the initial scheme.

But the core of interactive animation is the user interaction, which is event-based. The graph drawn on canvas itself does not support DOM events, and only the Canvas tag supports DOM event monitoring. Therefore, it is still necessary to encapsulate canvas events and realize monitoring and processing of corresponding events, which is quite complicated. At this time, it would be good to have a Canvas framework. Three commonly used Canvas frameworks such as Fabric.js, Pixi. js and Phaser.js are searched and compared on the Internet as follows:

The framework Canvas support Apply colours to a drawing Order of magnitude The event end
fabric.js all SVG and canvas light Encapsulates the Canvas tag to listen for events pc
pixi.js all WebGL, canvas, light Support events directly on draw elements PC, mobile, desktop
phaser.js all WebGL, canvas, heavy Support events directly on draw elements PC, mobile, desktop

The comparison found that PIxi in the frame level and rendering are particularly good, and its API is simple and easy to use, the event operation is also very simple in the draw object can directly manipulate events, while providing mouse and mobile touch events; Fabric is inferior to Pixi in rendering, event flexibility, and side support; Phaser is built on top of Pixi’s excellent rendering and encapsulate many game features such as gamepad input, sound support, etc., so phaser is more suitable for games. It is a game engine.

Based on the above selection analysis, PixiJs is very suitable for us to do interactive animation and small games.

PixiJs

So what exactly does PixiJs look like?

It is a Canvas based 2D WebGL rendering engine that can create rich interactive graphics, animations and games. Pixi aims to provide a fast, lightweight, all-device compatible 2D library that allows developers to enjoy hardware acceleration without WebGL knowledge. It uses WebGL rendering by default, but gracefully degrades to Canvas rendering if the browser doesn’t support it. Full mouse and touch events are also supported for drawing content.

Its characteristics can be summed up as follows:

  • Support WebGL rendering, because can call GPU rendering, so high rendering performance
  • Support for Canvas rendering. Canvas rendering is automatically used when the device does not support WebGL, or you can manually select Canvas rendering
  • Easy to use API, provides a lot of packaged modules
  • Rich interactive events, support for complete mouse and mobile touch events
  • Be free to use as much of it as you want without invading your coding style
  • Seamless integration with other plug-ins or frameworks

Now that you know Pixi and see how it works, it’s very convenient to reference Pixi, right

npm i pixi.js
import * as PIXI from "pixi.js"
Copy the code

Then we’re going to create an animation that looks something like this:

  • Create a stage
  • Create a canvas
  • Mount the canvas onto the DOM
  • Create elven
  • According to the elves
  • Operating the elves

1. Create a stage and canvas

First explain what is the stage, what is the canvas?

  • The stage is the root container for all the visible objects in your scene. We can think of it as an empty box. Everything we put on the stage will be displayed on the canvas and will only be displayed if we add objects to the stage to render.
  • A canvas is a render area. After adding the canvas to the DOM, a Canvas tag will be created and the canvas object will default to WebGL engine rendering mode.

Application can automatically create stages and renderers, as shown in the following figure:

App.stage.addchild (XXX) = app.stage.addChild(XXX) App. renderer is a canvas object. If you need to change its backgroundColor after creating the canvas tag, set the backgroundColor property of the app.renderer object to any hexadecimal color

app.renderer.backgroundColor = 0xffffff;
Copy the code

If you want to get the width and height of the canvas, use app.renderer.view.width and app.renderer.view.height, and use the canvas resize method to reset the width and height of the canvas

 app.renderer.autoResize = true;
 app.renderer.resize(512.512);
Copy the code

Mount the canvas to the DOM

Now that the stage and canvas have been created, add HTMLCanvasElement (app.view) created in the Pixi application to the DOM, and you can see the canvas rendering area with white background in the browser, as shown below:

 document.getElementById('draw').appendChild(app.view)
Copy the code

3. Create sprites

Now that we have the stage and canvas, we can add images to the stage and display them on the canvas.

We call special image objects that we can put on the stage sprites, sprites are pictures that we can control with code, you can control their position, size, level, use it to generate interaction and animation, is a key factor in pixi animation.

Pixi has a Sprite class, pixi. Sprite, which creates one or more sprites by passing in a single image, or Sprite, or a JSON object containing image information directly to the Sprite creation method.

However, since Pixi uses WebGL and GPU to render the image, the image needs to be transformed into a form that CAN be processed by GPU. We call the image that can be processed by GPU as texture. In general, you can’t upload images directly in pixi. Sprite, you need to upload textures. How do you load an image and turn it into a texture? Pixi provides a powerful Loader object that can be used to convert the above three types of image resources (sheet, Sprite, JSON) into texture resources, as shown in the following code:

PIXI.loader
  .add(['image1.png']) // Load the image
  .load(setup);
// Use the setup method when the image is loaded
function setup() {
  // Generate sprites
  let sprite = new PIXI.Sprite(
    // Convert the image to a texture
    PIXI.loader.resources['image1.png'].texture
  );
}
Copy the code

4. Add sprites to the stage

Sprites have been created. Add sprites to the stage to display sprites on canvas

app.stage.addChild(sprite)
Copy the code

If you have a complex scene and want to manage a group of images, you can use the Pixi. Container object to aggregate a group of sprites. If you want to control a group of sprites at the same time, you can use the Container object to create two rows and two columns of bird sprites. These sprites are added to the container container and the container rotates in the center of the canvas:

The code is as follows:

const container = new PIXI.Container();
app.stage.addChild(container);
const birdTexture = PIXI.Texture.fromImage('bird.png');
for (let i = 0; i < 4; i++) {
  const bird = new PIXI.Sprite(birdTexture);
  bird.width = 40
  bird.height = 40
  bird.anchor.set(0.5);
  bird.x = (i % 2) * 40;
  bird.y = Math.floor(i / 2) * 40;
  container.addChild(bird);
}
// Set the container location
container.x = 300;
container.y = 300;
// Set the container origin
container.pivot.x = container.width / 2;
container.pivot.y = container.height / 2;
// Loop rotation
app.ticker.add((delta) = > {
  container.rotation -= 0.01 * delta;
});
Copy the code

A root Container (app.stage) contains all renderable elements. Containers can also contain other containers. Here is a complete pixi tree:

5. Operation wizard

After the creation of a single Sprite or a group of sprites, you can control the position, size and level of sprites for animation interaction. Common interaction events in Pixi include:

  • Pointer event (compatible with mouse and touch screen trigger)
  • Mouse events (triggered by the mouse)
  • Touch event (touch screen triggered)

The use of events is described in more detail in the following examples. These five steps probably cover the complete animation creation process, the following will use a sky background, drag the mouse bird dancing in the sky example to introduce the specific implementation of pixi animation.

PixiJs practice

1. Set up the stage and canvas

  const app = new PIXI.Application({
    width: 600.height: 600.antialias: true.transparent: false.resolution: 2.autoResize: true.backgroundColor: 0xffffff
  })
  const drawing: any = document.getElementById('draw')
  drawing.appendChild(this.app.view)
Copy the code

2, set the blue sky background

PIXI.loader
  .add('sky.png')
  .load(setup)
function setup() {
  let bgSprite = new PIXI.Sprite(PIXI.loader.resources['sky.png'].texture)
  bgSprite.width = 600
  bgSprite.height = 600
  app.stage.addChild(bgSprite);
}
Copy the code

The renderings are as follows:

3. Add bird sprites

let birdSprite = new PIXI.Sprite(PIXI.loader.resources['bird.png'].texture)
birdSprite.width = 80
birdSprite.height = 80
birdSprite.position.set(20.20) // Set the location
app.stage.addChild(birdSprite)
Copy the code

The renderings are as follows:

4, drag the bird dance

// Add events to the bird Sprite
birdSprite
.on('pointerdown'.this.onDragStart)
.on('pointermove'.this.onDragMove)
.on('pointerup'.this.onDragEnd)
.on('pointerupoutside'.this.onDragEnd)
// Start dragging
onDragStart(event) {
  this.dragging = true
  this.data = event.data
  // The offset of mouse click position and bird position, used for mobile computing
  this.diff = { x: event.data.global.x - this.x, y: event.data.global.y - this.y }
}
// The drag is moving
onDragMove() {
  if (this.dragging) {
    const newPosition = this.data.getLocalPosition(this.parent)
    // Make sure that the birds do not exceed the background area in the drag
    this.x = Math.min(Math.max(this.boundary.left || 0, newPosition.x - this.diff.x), this.boundary.right)
    this.y = Math.min(Math.max(this.boundary.top || 0, newPosition.y - this.diff.y), this.boundary.bottom)
  }
}
// When the drag is complete, release the mouse or lift the finger
onDragEnd() {
  if (this.dragging) {
    this.dragging = false
    this.data = null}}Copy the code

5. Overall effect drawing

conclusion

So how to use pixi to achieve an interactive animation on the end of the story, animation scenes and set up a complex point, and then add audio modules to develop a cool small game is not at all ~. Of course, pixi does more than that. It also supports drawing text, drawing geometry, more than 20 filters, masking layers, and animation properties. Here’s a breakdown of pixi support in detail:

Pixi function is very powerful, is a lot of people make complex animation and small games of first choice, but learning PiXI Chinese information is not much, more complex functions need to view the official English documents and study the source code to understand, welcome to study together, explore piXI more and better play features!

The resources

Pixi official document

pixi_github