Базовое руководство по PixiJS

Canvas
Базовое руководство по PixiJS

PixiJSЭто облегченный механизм 2D-рендеринга, который автоматически определяет, следует ли использовать WebGL или Canvas для создания графики. Эта библиотека часто используется для создания игр HTML5 и страниц активности H5 со сложными взаимодействиями.

среда сборки

Примечание. В этой статье используется последняя версия pixi v5, при этом используетсяParcelмодульная упаковка

pixi.jsВерсия v5 по умолчанию использует рендеринг webgl.Если вы хотите вернуться к холсту, вам нужно использоватьpixi.js-legacy, видетьissue

Инициализация проекта

mkdir learn-pixi
cd learn-pixi
npm init -y

Установить зависимости

npm i pixi.js -save
npm i parcel-bundler -save-dev

создание корневого каталогаindex.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>learn-pixi</title>
</head>
<body>
  <script src="./src/index.js"></script>
</body>
</html>

создание корневого каталогаsrcкаталог, новыйsrc/index.js

alert('pixi');

Исправлятьpackage.json

"scripts": {
  "dev": "parcel index.html -p 8080",
  "build": "parcel build index.html"
}

бегатьnpm run dev,доступhttp://localhost:8080/увидеть эффект

быстрый старт

index.js

import { Application } from 'pixi.js';

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

// app.view就是个canvas元素,挂载到页面上
document.body.appendChild(app.view);

На странице появляется синий прямоугольник 300*300, и этот прямоугольник отображается холстом, созданным pixi.js.

Мы можем продолжать создавать новую графику и отображать ее на холсте.

import { Application, Graphics } from 'pixi.js';

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

// 创建一个半径为32px的圆
const circle = new Graphics();
circle.beginFill(0xfb6a8f);
circle.drawCircle(0, 0, 32);
circle.endFill();
circle.x = 130;
circle.y = 130;

// 添加到app.stage里,从而可以渲染出来
app.stage.addChild(circle);

Мы также можем сделать фотографии

import { Application, Sprite } from 'pixi.js';

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

// 创建一个图片精灵
const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');

// 图片宽高缩放0.5
avatar.scale.set(0.5, 0.5);

app.stage.addChild(avatar);

Делаем этот спрайт изображения интерактивным: после нажатия на изображение прозрачность изображения становится 0,5

const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
avatar.scale.set(0.5, 0.5);
// 居中展示
avatar.x = 100;
avatar.y = 100;

// 可交互
avatar.interactive = true;
// 监听事件
avatar.on('click', () => {
   // 透明度
   avatar.alpha= 0.5;
})
app.stage.addChild(avatar);

Мы также можем сделать изображение вращать все время

const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
avatar.scale.set(0.5, 0.5);
avatar.x = 150;
avatar.y = 150;

// 修改旋转中心为图片中心
avatar.anchor.set(0.5, 0.5)

app.stage.addChild(avatar);

app.ticker.add(() => {
  // 每秒调用该方法60次(60帧动画)
  avatar.rotation += 0.01;
})

основная концепция

pixiЕсть несколько важных классов:

  • Контейнер (сцена, сцена)
  • Рендерер
  • Тикер (таймер)
  • Загрузчик (загрузчик ресурсов)
  • Спрайт
const app = new Application({
  width: 300,
  height: 300
});

ApplicationЭто инструментальный метод, предоставляемый pixi, который может автоматически создавать визуализатор, тикер и контейнер.Мы обычно используем этот метод для быстрого создания приложений.

Container

app.stageЯвляетсяContainerЭкземпляр , как самая нижняя стадия, внутри которой должна быть размещена вся визуализируемая графика.

const app = new Application({
  width: 300,
  height: 300
});
// 添加不同的图形
app.stage.addChild(circle1);
app.stage.addChild(circle2);

Мы также можем создать свой собственныйContainer, пользовательский контейнер обычно используется для группировки

import { Application, Container, Graphics } from 'pixi.js';

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

// 自定义Container
const myContainer = new Container();
// 相对于根节点偏移
myContainer.position.set(40, 40);

let rectangle = new Graphics();
rectangle.beginFill(0x000000);
rectangle.drawRect(0, 0, 64, 64);
rectangle.endFill();

let rectangle2 = new Graphics();
rectangle2.beginFill(0xFFFFFF);
rectangle2.drawRect(0, 0, 64, 64);
rectangle2.endFill();
// 相对于自定义Container偏移
rectangle2.position.set(20, 20);

// 两个图形加到自定义Container里
myContainer.addChild(rectangle);
myContainer.addChild(rectangle2);

// 自定义Container最后需要添加到app.stage
app.stage.addChild(myContainer);

document.body.appendChild(app.view);

Преимущество группировки в том, что при изменении свойств контейнера будут затронуты расположенные в нем дочерние узлы. Например, в приведенном выше примере мы имеемrectangleа такжеrectangle2Они назначены одной и той же группе. Если вы хотите скрыть эти два элемента одновременно, вам нужно только изменить прозрачность своего родительского контейнера.

// 父级透明,则子级也透明
myContainer.alpha = 0;

Обычная практика заключается в том, что мы создаем самый верхнийrootContainer, и все, что после этого, добавляется вrootContainerвнутри. а такжеrootContainerВ качестве элемента верхнего уровня можно выполнить некоторое масштабирование для соответствия различным разрешениям:

const rootContainer = new Container();
app.stage.addChild(rootContainer);

// 相对于设计稿750px进行缩放(竖屏状态)
const screenScaleRito = window.innerWidth / 750; // 横屏则用innerHeight
rootContainer.scale.set(screenScaleRito, screenScaleRito);

Этот метод похож на макет rem нашего внешнего интерфейса.

Renderer

app.rendererЯвляетсяRendererнапример, вам нужно использовать его, если вы хотите повторно отобразить страницу

// 把画布重新渲染为500*500大小
app.renderer.resize(500, 500);

// 渲染一个容器
const container = new Container();
app.renderer.render(container);

Sprite

Спрайт можно считать обычной векторной графикой, но рендерится он по картинке.

const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');

// 和普通的图形一样可以设置各种属性
avatar.width = 100;
avatar.height = 200;
avatar.position.set(20, 30);
avatar.scale.set(2, 2);

Загрузка изображений обычно занимает определенное время, поэтому мы часто используемLoaderЧтобы предварительно загрузить изображение, когда все изображение успешно загружено, оно будет отображено.

Loader

import { Application, Sprite, Loader } from 'pixi.js';

// Loader.shared内置的单例loader
const loader = Loader.shared;

// 也可以使用自定义的loader
const loader = new Loader();

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.add('avatar', 'http://anata.me/img/avatar.jpg')
.load(setup)

// 监听加载事件
loader.onProgress.add((loader) => {
  console.log(loader.progress);
}); 

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;
  
  const avatar = new Sprite(
    loader.resources["avatar"].texture
  );
  avatar.width = 50;
  avatar.height = 50;
  avatar.position.set(50, 50);

  app.stage.addChild(bili);
  app.stage.addChild(avatar);
}

пройти черезaddметод добавления изображений для загрузки после загрузки всех изображений,loadМетод будет вызывать входящийsetupФункция обратного вызова, затем вы можете добавить спрайт изображения вapp.stageвнутри.onProgressСобытия могут отслеживать ход загрузки, благодаря этому методу очень удобно анимировать индикатор выполнения.

Внешний интерфейс иногда объединяет несколько изображений в одно изображение, установивbackground-positionдля отображения различных изображений.pixi.jsЕсть аналогичные методы, которыми мы можем воспользоватьсяTexture PackerПрограммное обеспечение, объедините несколько изображений в одно изображение, и в то же время программное обеспечение создаст копиюjsonФайл конфигурации записывает относительное положение каждого изображения.

Конкретные руководства см.здесь

import { Application, Container, Sprite, Graphics, Loader, Spritesheet } from 'pixi.js';

// myjson记录了每张图片的相对位置
import myjosn from './assets/treasureHunter.json';

// mypng里面有多张图片
import mypng from './assets/treasureHunter.png';

const loader = Loader.shared;

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

loader
.add('mypng', mypng)
.load(setup)

function setup() {
  const texture = loader.resources["mypng"].texture.baseTexture;
  const sheet = new Spritesheet(texture, myjosn);
  sheet.parse((textures) => {
    // mypng里面的一张叫treasure.png的图片
    const treasure = new Sprite(textures["treasure.png"]);
    treasure.position.set(0, 0);

    // mypng里面的一张叫blob.png的图片
    const blob = new Sprite(textures["blob.png"]);
    blob.position.set(100, 100);
    
    app.stage.addChild(treasure);
    app.stage.addChild(blob);
  });
}

Ticker

TickerПохож на переднюю частьrequestAnimationFrame, эта функция будет выполняться при обновлении частоты отображения браузера, поэтому она часто используется для создания анимации.

app.tickerтолько одинTickerпример.

import { Application, Sprite, Loader } from 'pixi.js';

const loader = Loader.shared;

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')                      
.load(setup)

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;

  app.stage.addChild(bili);

  app.ticker.add(() => {
    if (bili.x <= 200) {
      bili.x += 1;
    }
  })
}

Мы также можем использоватьrequestAnimationFrameдостичь этого эффекта

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;

  app.stage.addChild(bili);

  function move() {
    if (bili.x <= 200) {
      bili.x += 1;
      requestAnimationFrame(move)
    }
  }

  requestAnimationFrame(move)

}

промежуточная анимация

TickerПростых анимаций можно добиться, но если мы хотим добиться каких-то сложных эффектов, нам нужно самим написать много кода, тогда мы можем выбрать совместимыйpixiбиблиотека анимации. Наиболее распространенные библиотеки анимации на рынке:Tween.js,TweenMax, здесь мы используемTweenMaxдля демонстрации эффекта.

Установить библиотеку анимации

npm i gsap
import { Application, Sprite, Loader } from 'pixi.js';

import { TweenMax } from 'gsap/all';

const loader = Loader.shared;

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});


document.body.appendChild(app.view);

loader
  .add('bili', 'http://pic.deepred5.com/bilibili.jpg')
  .load(setup)

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;

  app.stage.addChild(bili);

  // 1s内x和y轴移动100
  TweenMax.to(bili, 1, { x: 100, y: 100 });

}

TweenMaxтакже обеспечиваетPixiPlugin, вы можете изменить несколько свойств pixi одновременно

import { Application, Sprite, Loader } from 'pixi.js';
import * as PIXI from 'pixi.js';
import gsap, { TweenMax, PixiPlugin } from 'gsap/all';

// 注册插件
gsap.registerPlugin(PixiPlugin);
PixiPlugin.registerPIXI(PIXI);

const loader = Loader.shared;

const app = new Application({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

document.body.appendChild(app.view);

loader
  .add('bili', 'http://pic.deepred5.com/bilibili.jpg')
  .load(setup)

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;

  app.stage.addChild(bili);


  // 一次修改多个属性
  TweenMax.to(bili, 1, { pixi: { scaleX: 1.2, scaleY: 1.2, skewX: 10, rotation: 20 } });

}

Пользовательское приложение

Обычно мы используем те, которые предоставляет Pixi.Applicationметод для создания приложения, которое автоматически создает средства визуализации, бегущие строки и контейнеры. Но на самом деле мы можем создавать эти объекты сами.

import { Container, Renderer, Sprite, Loader, Ticker } from 'pixi.js';
import { TweenMax } from 'gsap/all';

// 自定义render
const renderer = new Renderer({
  width: 300,
  height: 300,
  antialias: true,
  transparent: false,
  resolution: 1,
  backgroundColor: 0x1d9ce0
});

// 自定义container
const stage = new Container();

// 自定义loader
const loader = new Loader();

// 自定义ticker
const ticker = new Ticker();

// 每次屏幕刷新重新渲染,否则只会渲染第一帧
ticker.add(() => {
  renderer.render(stage);
});

// 开始执行ticker,一定要调用这个方法,注册的回调函数才会被执行!!!
ticker.start();


document.body.appendChild(renderer.view);

loader
  .add('bili', 'http://pic.deepred5.com/bilibili.jpg')
  .load(setup)

function setup() {
  const bili = new Sprite(
    loader.resources["bili"].texture
  );
  bili.width = 50;
  bili.height = 50;

  stage.addChild(bili);

  // 动画效果
  ticker.add(() => {
    if (bili.x <= 200) {
      bili.x += 2;
    }
  });

  TweenMax.to(bili, 1, { y: 100, delay: 3 });
}

фактическиPIXI.ApplicationНижний слой поможет нам упростить вышеуказанные операции.

Ссылаться на

Pixi Tutorial Китайская версия

Pixi wiki

Изучите PixiJS — анимацию движения