Code Monkey home page Code Monkey logo

sprite-wxapp's Introduction

spritejs 微信小程序版

这是 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('Hello\n 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
    });

    // 将两个精灵添加到 layer
    layer.append(bird, text);
  },
})

注意,自己调用的时候,创建canvas需要设置canvas-id属性与创建的layer的ID一致。

小程序版与原版限制/差异

Scene 的参数差异

不同于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)
    
    ...
  },
})

layer的canvas元素需要预先创建

微信不支持动态创建元素,因此canvas要先在模板里创建好,并赋给对应的canvas-id。

资源预加载和Sprite图片支持的限制

目前不支持远程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,因此无法使用缓存优化。

目前暂时无法解决的Bug

  • 由于微信的模拟器的clip有问题,所以在模拟器下sprite元素的clip区域可能不正确
  • 微信的canvas的globalAlpha只有setter没有getter,因此小程序设置opacity属性的时候没法层叠,子元素的opacity会覆盖父容器的opacity值

sprite-wxapp's People

Contributors

akira-cn avatar crossjs avatar manyuanrong avatar welefen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

sprite-wxapp's Issues

小程序Label方法在真机上不显示

Label方法在小程序开发者工具上看到显示,真机上无法显示
机型:小米5s
安卓版本:7.0
小程序基础库:2.1.0
代码:github上的demo
————————————
目前发现在在给文字加上border属性时无法显示

小游戏 Sprite 无法加载图片

game.js

  • dice.png 跟 game.js 在相同文件夹
import './js/libs/symbol';
import {Label, Scene, Layer, Sprite, Group} from './js/libs/sprite-wxapp';

const scene = new Scene()
const bglayer = scene.layer('bglayer');
let s = new Sprite('./dice.png')
s.attr({
  size: [200, 200],
  pos: [50, 50]
})
bglayer.append(s)

编译时页面报错

VM4974:1 gameThirdScriptError
Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
    at http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:20223:38
    at Array.forEach (<anonymous>)
    at ResSprite.render (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:20187:18)
    at ResSprite.draw (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:1863:14)
    at ExLayer.drawSprites (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:18975:19)
    at ExLayer.drawSprites (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:6778:128)
    at ExLayer.renderRepaintAll (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:19002:12)
    at ExLayer.draw (http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:18933:7)
    at http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:18888:22
    at http://127.0.0.1:39519/game/js/libs/sprite-wxapp.js:9079:9

另外:

  • 使用 scene.preload 方法报相同错误。

小程序内touch事件未生效

示例如下:
this['level1_1'].isDraggable = true
this['level1_1'].on('touchstart', evt => {
this['level1_1'].attr({
opacity: 0.5
})
})

在安卓手机:小米 5s,系统 MIUI 9.6 | 稳定版,微信版本 6.6.6,Sprite 设置 borderRadius 属性,界面裁剪错

我使用网络图片,本地图片。或者 bgcolor 属性设置 Sprite。加上 borderRadius 就会裁剪错。在模拟器上没问题,暂时只在小米5s上遇到了。

21391536726070_ pic
21381536725945_ pic
21371536725943_ pic
21401536727915_ pic
21411536728643_ pic

测试代码

<template>
  <view>
    <canvas class="myCanvas" canvas-id="myCanvas" />
  </view>
</template>
<script>
import wepy from 'wepy';
const spritejs = require('../../utils/sprite-wxapp');
export default class GenerateImage extends wepy.page {
  config = {
    navigationBarTitleText: '一起燃烧卡路里',
    navigationBarBackgroundColor: '#FA4676'
  };
  data = {
    avatarUrl: 'https://wx.qlogo.cn/mmopen/vi_32/ZrA7SPMNXYibCdRlsTH0oYnfkv0fKx2FVxHfO7MsiaUubIHRtCTp0Ej2f98lvcWVh9wUXuaHAyepWCTYb2HIy8Ug/132'
  };
  methods = {};
  async onLoad() {
    let scene = new spritejs.Scene(0);
    let layer = scene.layer('myCanvas');
    let avatarUrl = await wepy.downloadFile({
      url: this.avatarUrl
    });
    // let avatar = new spritejs.Sprite(avatarUrl.tempFilePath);
    let avatar = new spritejs.Sprite();
    avatar.attr({
      anchor: [0],
      pos: [50, 100],
      size: [72, 72],
      bgcolor: 'red',
      borderRadius: 10
    });
    layer.append(avatar);
  }
}
</script>
<style lang="less">
page{
  background: #000;
}
.myCanvas {
  position: fixed;
  left: 0;
  top: 0;
  height: 1242px;
  width: 750px;
}
</style>

小游戏中事件不工作

代码直接修改自 game/game.js

  • 所有 click,touch 事件都没反应
import { Scene, Layer, Sprite } from './js/libs/sprite-wxapp';

const scene = new Scene();
const fglayer = scene.layer('fglayer');
const bglayer = scene.layer('bglayer');

// const layer = new Layer({context: canvas.getContext('2d')})
// canvas.width = 200

const s = new Sprite('https://p3.ssl.qhimg.com/t01d435c21276da7d3b.png');

s.attr({
  size: [100, 100],
  pos: [100, 100],
  bgcolor: 'red',
});

s.on('click', () => {
  console.log('click');
});
s.on('touchstart', () => {
  s.attr('bgcolor', 'green');
});
s.on('touchmove', () => {
  s.attr('bgcolor', 'yellow');
});
s.on('touchend', () => {
  s.attr('bgcolor', 'red');
});

bglayer.append(s);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.