小程序技术分享| 小程序集成 pixi 渲染引擎

开发小程序时一些特殊场景需要使用canvas,但canvas渲染一些特效时太过耗费性能造成页面卡顿并且展示效果也不好(拖动卡顿不连贯等),因此使用渲染引擎来满足需求。本文在小程序中使用 pixi 渲染引擎。

引入改造后的 pixi

pixi与小程序不是很匹配,需要进行对应改造才可在小程序中使用。
本文中使用spine、animate等,可保存至同一文件夹下

下载地址 gitee 仓库

  • pixi-animate.js

  • pixi-spine.js

  • pixi.miniprogram.js

  • unsafeEval.js(必备,牵连到一些事件转换)

使用

页面中添加 canvas

   <canvas type="webgl" id="croplandCanvas" class="cropland_canvas" bindtouchstart="touchEvent" bindtouchmove="touchEvent" bindtouchend="touchEvent" bindtouchcancel="touchEvent"></canvas>
   <canvas type="2d" id="canvas2d" class="canvas_test"></canvas>
   <canvas type="2d" id="canvas2dText" class="canvas_test"></canvas>

特效实现

初始定义

/** pixi 相关 */
import {
    createPIXI
} from "../libs/pixi.miniprogram";
const unsafeEval = require("../libs/unsafeEval");
const installSpine = require("../libs/pixi-spine");
const installAnimate = require("../libs/pixi-animate");

// 动画定时器
let animationFrame= null;
// pixi 实例
let storePIXI = null;
// pixi 全局舞台容器
let pixiRenderer = null;
// canvas 容器实例
let canvasInstance = null;

pixi 初始化

// 获取 canvas
wx.createSelectorQuery().select('#croplandCanvas').fields({
            node: true,
            size: true
        })
            .exec((res) => {
                const canvas = res[0].node;
                canvasInstance = canvas;
                // 设置canvas实际宽高
                canvas.width = 400;
                canvas.height = 800;
                 // 方便pixi定位
                 wx.createSelectorQuery().select('#canvas2d').fields({
                    node: true,
                    size: true
                }).exec(function (res2d) {
                    const canvas2d = res2d[0].node;
                    canvas2d.width = 16;
                    canvas2d.height = 16;
                    // 方便pixi定位
                    wx.createSelectorQuery().select('#canvas2dText').fields({
                        node: true,
                        size: true
                    }).exec(async function (res2dText) {
                        const canvas2dText = res2dText[0].node;
                        canvas2dText.width = 16;
                        canvas2dText.height = 16;
                      
                       /** 传入canvas,传入canvas宽度,用于计算触摸坐标比例适配触摸位置 */
                       // PIXI 初始化 -----start
                       storePIXI = createPIXI(canvas, 400, canvas2d, canvas2dText)

                       unsafeEval(storePIXI); //适配PIXI里面使用的eval函数
                       installSpine(storePIXI); //注入Spine库
                       installAnimate(storePIXI); //注入Animate库

                       // 通过view把小程序的canvas传入
                       pixiRenderer = Store.PIXI.autoDetectRenderer({
                           width: 400,
                           height: 800,
                           'transparent': true,
                           'view': canvas
                       });
                       // PIXI 初始化 -----end
                       
       
                       // PIXI 舞台+精灵(特效实现) -----start
                       /** 创建总舞台 */ 
                       const allStage = new Store.PIXI.Container();
                       // 舞台层级开关
                       allStage.sortableChildren = true;
                       
                       /** 例子:添加一个精灵图可拖拽 */
                        const bgStage = new storePIXI.Sprite.from(线上图片地址)
                        bgStage.sortableChildren = true;
                        
                        // 添加到总舞台
                        allStage.addChild(bgStage);
                       /** 对应事件触发 */
                        baseMapPIXIEvent(bgStage);
                       // PIXI 舞台+精灵(特效实现) -----end
                      
                       
                      // 视图渲染
                      function animate() {
                          pixiRenderer.render(allStage);
                          animationFrame = canvas.requestAnimationFrame(animate);
                      }
                      animate();
                    })

pixi 事件绑定

// 小程序事件绑定至pixi
touchEvent(e) {
        storePIXI.dispatchEvent(e)
}

// pixi 事件处理
baseMapPIXIEvent(stage) {
  stage.on("touchstart", function (e) {
        const global = e.data.global;
        console.log("touchstart-开始移动", global);
  });
  stage.on("touchmove", function (e) {
        const global = e.data.global;
        console.log("touchstart-移动中", global);
  });
  stage.on("pointerup", function (e) {
        const global = e.data.global;
        console.log("touchstart-移动结束", global);
  });
  stage.on("pointertap", function (e) {
        const global = e.data.global;
        console.log("touchstart-点击", global);
  });
}

pixi 销毁

 allStage && allStage.destroy();
 animationFrame && canvasInstance.cancelAnimationFrame(animationFrame);
 pixiRenderer && pixiRenderer.destroy();

注意

图片大小最好不要超过300k

pixi 可参考对应官网文档实现需求特效

在这里插入图片描述

posted @ 2023-06-27 15:45  anyRTC  阅读(156)  评论(0编辑  收藏  举报