服务端渲染

spritejs通过node-canvas支持服务端渲染,也就是说我们可以在node环境下使用spritejs,将绘制好的图形保存成png,或者将动画保存成gif。

将静态输出保存成png

  1. const fs = require('fs')
  2. const {Scene, Label} = require('spritejs')
  3. const scene = new Scene('#test', 800, 600)
  4. const bglayer = scene.layer('bg', {handleEvent: false})
  5. const text = new Label('Hello Sprite!')
  6. text.attr({
  7. anchor: [0.5, 0.5],
  8. pos: [400, 300],
  9. font: '46px Arial',
  10. color: 'blue',
  11. bgcolor: 'white',
  12. textAlign: 'center',
  13. })
  14. bglayer.append(text)
  15. ;(async function () {
  16. const canvas = await scene.snapshot()
  17. fs.writeFileSync('snap.png', canvas.toBuffer())
  18. }())

将动画保存成gif,甚至可以通过dispatchEvent模拟点击事件。

  1. const fs = require('fs')
  2. const {Scene, Label} = require('../../lib')
  3. const scene = new Scene('#test', 800, 600)
  4. const bglayer = scene.layer('bg', {handleEvent: true})
  5. const text = new Label('Clicked: 0')
  6. text.attr({
  7. anchor: [0.5, 0.5],
  8. pos: [400, 300],
  9. font: '46px Arial',
  10. color: 'blue',
  11. bgcolor: 'white',
  12. textAlign: 'center',
  13. })
  14. bglayer.append(text)
  15. function sleep(t) {
  16. return new Promise((resolve) => {
  17. setTimeout(resolve, t)
  18. })
  19. }
  20. const GIFEncoder = require('gifencoder')
  21. const encoder = new GIFEncoder(scene.width, scene.height)
  22. // stream the results as they are available into myanimated.gif
  23. encoder.createReadStream().pipe(fs.createWriteStream('label_clicked.gif'))
  24. encoder.start()
  25. encoder.setRepeat(0) // 0 for repeat, -1 for no-repeat
  26. encoder.setDelay(500) // frame delay in ms
  27. encoder.setQuality(10) // image quality. 10 is default.
  28. let count = 0
  29. bglayer.on('click', async (e) => {
  30. const msg = `Clicked: ${++count}`
  31. text.text = msg
  32. const canvas = await scene.snapshot()
  33. const ctx = canvas.getContext('2d')
  34. encoder.addFrame(ctx)
  35. console.log(msg)
  36. })
  37. ;(async function () {
  38. // const canvas = await scene.snapshot()
  39. // fs.writeFileSync('snap.png', canvas.toBuffer())
  40. for(let i = 0; i < 10; i++) {
  41. scene.dispatchEvent('click', {x: 400, y: 300})
  42. await sleep(500)
  43. }
  44. console.log('done')
  45. }())

微信小程序

spritejs为微信小程序提供定制版本:sprite-wxapp

sprite-wxapp与spritejs标准版基于同一套底层,由于微信环境的不同,一些api上略有差别,另外微信小程序版不支持缓存,无法使用缓存策略。其他大部分功能二者是一致的。

  1. //index.js
  2. //获取应用实例
  3. const app = getApp()
  4. const spritejs = require('../../lib/spritejs')
  5. Page({
  6. data: {
  7. layers: ['fglayer'],
  8. },
  9. onTouchStart: function(event) {
  10. const {x, y} = event.touches[0]
  11. const [layerX, layerY] = this.scene.toLocalPos(x, y)
  12. // 派发 touchstart 事件
  13. this.scene.layer('fglayer').dispatchEvent('touchstart', {originEvent: event, layerX, layerY})
  14. },
  15. onReady: function() {
  16. const scene = new spritejs.Scene(1)
  17. this.scene = scene
  18. // 预加载资源
  19. scene.preload(['../../assets/img/birds.png', require('../../assets/img/birds.json.js')])
  20. const bird = new spritejs.Sprite('bird1.png')
  21. bird.attr({
  22. anchor: [0.5, 0.5],
  23. pos: [100, 200],
  24. })
  25. // 添加 ontouch 事件
  26. bird.on('touchstart', evt => {
  27. console.log(evt)
  28. })
  29. // 纹理动画
  30. let i = 0
  31. setInterval(() => {
  32. bird.textures = [`bird${i++%3+1}.png`]
  33. }, 100)
  34. // 添加文字
  35. const text = new spritejs.Label('Hello\n World!')
  36. text.attr({
  37. //anchor: [0.5, 0.5],
  38. font: '44px Arial',
  39. border: [2, 'red'],
  40. })
  41. const posFrom = [0, 0]
  42. const posTo = [100, 0]
  43. // 播放一个移位动画
  44. text.animate([
  45. {pos: posFrom},
  46. {pos: posTo},
  47. ], {
  48. duration: 2000
  49. })
  50. // 将两个精灵添加到 layer
  51. layer.append(bird, text)
  52. },
  53. })