這是spritejs 的微信小程式版,目前支援spritejs v 2.0 的大部分功能,具體可以參考幫助文檔
Sprite屬性更新自動(分批)重繪
以rpx為預設單位
動畫支援Web Animations API
支持事件機制
v1.10.0 版本之後,小程式版支援使用NPM 安裝。
npm install @spritejs/wxapp --save
然後在微信小程式中建構NPM 包。
安裝並建置之後,要使用SpriteJS,最簡單的方式是透過內建的scene 元件使用。
在小程式設定app.json 中註冊元件:
"usingComponents": {"s-scene": "@spritejs/wxapp/scene" }
然後在要使用的頁面引入元件:
<view> <s-scene id="container"layers="bglayer,fglayer"bindSceneCreated="onSceneCreated" ></s-scene> </view>
參數layers表示建立幾個layer以及它們的ID,預設為default。
bindSceneCreated為創建Scene後的回呼事件,事件方法中傳回所創建的layers:
const { Sprite } = require('@spritejs/wxapp');Page({ onSceneCreated({ detail: layers }) {const { bglayer, fglayer } = layers;const s = new Sprite({ size: [100, 100], pos: [300, 300], bgcolor: 'red',}); fglayer.append(s);const s2 = new Sprite({ size: [300, 300], pos: [200, 200], bgcolor: 'blue',});bglayer.append(s2);s.on('touchstart', () => { s.attr('bgcolor' , 'green');});s.on('touchmove', () => { s.attr('bgcolor', 'yellow');});s.on('touchend', () => { s.attr('bgcolor', 'red');}); },});
如果不想使用組件,你也可以自己創建canvas,然後構造scene
<view class="scene-layout" id="container" catchtouchmove="noop"> <block wx:for="{{layers}}" wx:key="{{item}}"> <canvas canvas-id="{{item}}" disable-scroll="true"></canvas> </block> </view>
const spritejs = require('@spritejs/wxapp');Page({ data: {layers: ['fglayer'],eventOffset: [0, 0], }, onTouchStart(event) {// 派發 touchstart 事件this.scene.layer('fglayer').dispatchEvent(event, this.data.eventOffset); }, onReady: function() {// 由於代理事件的scene-layout 相對視窗可能有偏移,所以需要傳入這個偏移量// 以正確定位事件座標const query = wx.createSelectorQuery();query.select( '.scene-layout').boundingClientRect().exec(([rect]) => { if(rect) {this.setData({ eventOffset: [rect.left, rect.top],}); }});const scene = new spritejs.Scene();this.scene = scene;const layer = scene.layer('fglayer');// 預載入資源scene.preload(['../../assets/img/birds.png', require('../../assets/img/birds.json.js')]);const bird = new spritejs.Sprite('bird1.png');bird.attr({ anchor: [0.5, 0.5] , pos: [100, 200],});// 增加ontouch 事件bird.on('touchstart', evt => { console.log(evt)});// 紋理動畫let i = 0;setInterval(() => { bird.textures = [`bird${i++%3+1}.png`];}, 100); // 新增文字const text = new spritejs.Label('Hellon World!');text.attr({ //anchor: [0.5, 0.5], font: '44px Arial', border: [2, 'red'],});const posFrom = [0, 0];const posTo = [100, 0];// 播放一個移位動畫text.animate([ {pos : posFrom}, {pos: posTo},], { duration: 2000});// 將兩個精靈加入layerlayer.append(bird, text); },})
注意,自己呼叫的時候,建立canvas需要設定canvas-id屬性與建立的layer的ID一致。
有別於web/node版,小程式版的Scene建構函式只能傳width和height,單位是rpx。 rpx是微信小程式特有的單位,具體描述參考文件。
const info = wx.getSystemInfoSync();const scene = new Scene(750, 1433); // 單位是rpx
如果透過元件載入方式使用, touchstart, touchend, touchmove, tap, longpress
等事件被scene自動代理,所以你可以在sprite元素中加入對應的事件處理函數,能夠正常觸發事件。
如果是自己創建scene,那麼需要自己手動代理事件:
<!--index.wxml--><view class="scene-layout" id="container"> <block wx:for="{{layers}}" wx:key="{{item}}"> <canvas canvas-id="{{item}}" bindtouchstart="touched"></canvas> </block> </view>
const spritejs = require('@spritejs/wxapp')Page({ data: {layers: ['fglayer'],eventOffset: [0, 0], }, touched: function(event) {this.scene.layer('fglayer').delegateEvent(event, this.data.eventOffset); }, onReady: function() {// 由於代理事件的scene-layout 相對視窗可能有偏移,所以需要傳入這個偏移量// 以正確定位事件座標const query = wx.createSelectorQuery();query.select( '.scene-layout').boundingClientRect().exec(([rect]) => { if(rect) {this.setData({ eventOffset: [rect.left, rect.top],}); }});const scene = new spritejs.Scene();this.scene = scene;const layer = scene.layer('fglayer');// 如果在自訂元件中使用,傳遞第二個參數為元件實例的參考。 // const layer = scene.layer('fglayer', this) ... },})
微信不支援動態創建元素,因此canvas要先在模板裡創建好,並賦給對應的canvas-id。
目前不支援遠端url的加載,只支援本地圖片素材,另外web/node版的Sprite可以預先載入圖片並獲得圖片寬高,所以sprite可以預設自適應寬高,而微信小程式版除非使用texturepacker打包圖片,否則無法獲得預設的寬高,必須指定寬高才可以將sprite物件顯示出來。
另外注意scene.preload預加frames資源載時,不支援從json檔案載入frameData,必須是js對象,可以將frameData存成js,然後在app中require進來。
另外目前不支援texture packer 的rotated 和trimmed 功能。
// 微信小程式版的scene.preload 是同步的scene.preload(['../../assets/img/birds.png', require('../../assets/img/birds.json .js')])const sprite1 = new Sprite('bird1.png') sprite1.attr({ pos: [0, 0],})// 從frames載入的圖片有預設大小,可以正常顯示scene.layer().append(sprite1)const sprite2 = new Sprite('../../assets/ img/rambda.png')sprite2.attr({ pos: [50, 50], size: [100, 100], // 非frames的圖片必須指定寬高})scene.layer().append(sprite2)
我們放了一個「十滴水」小遊戲的例子在app
資料夾下。
要調試範例程式碼,可以啟動webpack編譯
npm start
然後用微信開發者工具調試程式碼
微信不支援動態創建Dom元素,不相容d3,目前d3的功能暫時不支援(未來打算透過shim適配)。
微信context不支援濾鏡,所以濾鏡filter無效果。
微信canvas不支援漸層(linearGradients 和createRadialGradient),如果在attr 中使用漸層屬性會出錯。
微信的canvas不支援動態創建context,因此無法使用快取優化。
由於微信的模擬器的clip有問題,所以在模擬器下sprite元素的clip區域可能不正確
微信的canvas的globalAlpha只有setter沒有getter,因此小程式設定opacity屬性的時候沒辦法層疊,子元素的opacity會覆蓋父容器的opacity值