开发小程序时一些特殊场景需要使用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 可参考对应官网文档实现需求特效