開發小程式時一些特殊場景需要使用canvas,但canvas渲染一些特效時太過耗費性能造成頁面卡頓并且展示效果也不好(拖動卡頓不連貫等),是以使用渲染引擎來滿足需求。本文在小程式中使用 pixi 渲染引擎。
引入改造後的 pixi
pixi與小程式不是很比對,需要進行對應改造才可在小程式中使用。
本文中使用spine、animate等,可儲存至同一檔案夾下
下載下傳位址 gitee 倉庫(https://gitee.com/zhangyao123-ZY/pixi-adaptation-mini-program.git)
- 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 可參考對應官網文檔實作需求特效