关系链数据

为了丰富游戏的社交玩法,我们为开发者提供 关系链数据 能力。通过关系链数据能力,可满足游戏内 排行榜、好友超越等使用场景。

每一个微信用户的关系链数据包括 3 部分:

  • 该用户好友的用户数据
  • 该用户所在的某个群的群成员的用户数据
  • 该用户的可能对该游戏感兴趣的好友列表(基础库 2.9.0 开始支持)

获取关系链数据的 API:

这三个 API 的返回结果都是一个对象数组,数组的每一个元素都是一个表示用户数据的对象,其结构如下:

属性类型说明
openIdstring用户的 openId
avatarUrlstring用户的微信头像 url
nickNamestring用户的微信昵称
dataObject用户的游戏数据

用户的 游戏数据 指的是用户的段位、战绩等游戏业务特有的数据,通过调用 wx.setUserCloudStorage() 可以将当前用户的游戏数据托管在微信后台。只有被托管过数据的用户,才会被视为 玩过 该小游戏的用户,才会出现在 wx.getFriendCloudStorage()wx.getGroupCloudStorage() 返回的对象数组中。

除此之外,我们还提供了以下 API:

wx.getUserCloudStoragewx.getFriendCloudStorage()wx.getGroupCloudStorage() 只能在 开放数据域 中调用。wx.setUserCloudStorage()wx.removeUserCloudStorage() 可以同时在 主域 和开放数据域中调用。

开放数据域

开放数据域 是一个封闭、独立的 JavaScript 作用域。要让代码运行在开放数据域,需要在 game.json 中添加配置项 openDataContext 指定开放数据域的代码目录。添加该配置项表示小游戏启用了开放数据域,这将会导致一些 限制

  1. {
  2. "deviceOrientation": "portrait",
  3. "openDataContext": "src/myOpenDataContext"
  4. }

同时还需要在该目录下创建 index.js 作为开放数据域的入口文件,其代码运行在开放数据域。game.js 是整个游戏的入口文件,其代码运行在 主域。对应以上配置,应该有如下的目录结构:

  1. ├── src
  2. | └── myOpenDataContext
  3. | ├── index.js
  4. | └── ...
  5. ├── game.js
  6. ├── game.json
  7. └── ...

src/myOpenDataContext 是 开放数据域的代码目录,除 src/myOpenDataContext 以外是 主域的代码目录

主域和开放数据域中的代码不能相互 require。以如下的目录结构为例:

  1. ├── src
  2. | └── myOpenDataContext
  3. | ├── index.js
  4. | ├── util.js
  5. | └── ...
  6. ├── lib
  7. | └── render.js
  8. └── game.js

在 game.js 中不能 require('src/myOpenDataContext/util')在 src/myOpenDataContext/index.js 中不能 require('../../lib/render.js')

主域和开放数据域的通信

开放数据域不能向主域发送消息。

主域可以向开放数据域发送消息。调用 wx.getOpenDataContext() 方法可以获取开放数据域实例,调用实例上的 OpenDataContext.postMessage() 方法可以向开放数据域发送消息。

  1. // game.js
  2. let openDataContext = wx.getOpenDataContext()
  3. openDataContext.postMessage({
  4. text: 'hello',
  5. year: (new Date()).getFullYear()
  6. })

在开放数据域中通过 wx.onMessage() 方法可以监听从主域发来的消息。

  1. // src/myOpenDataContext/index.js
  2. wx.onMessage(data => {
  3. console.log(data)
  4. /* {
  5. text: 'hello',
  6. year: 2018
  7. } */
  8. })

展示关系链数据

如果想要展示通过关系链 API 获取到的用户数据,如绘制排行榜等业务场景,需要将排行榜绘制到 sharedCanvas 上,再在主域将 sharedCanvas 渲染上屏。

关系链数据 - 图1

  1. // src/myOpenDataContext/index.js
  2. let sharedCanvas = wx.getSharedCanvas()
  3. function drawRankList (data) {
  4. data.forEach((item, index) => {
  5. // ...
  6. })
  7. }
  8. wx.getFriendCloudStorage({
  9. success: res => {
  10. let data = res.data
  11. drawRankList(data)
  12. }
  13. })

sharedCanvas 是主域和开放数据域都可以访问的一个离屏画布。在开放数据域调用 wx.getSharedCanvas() 将返回 sharedCanvas。

  1. // src/myOpenDataContext/index.js
  2. let sharedCanvas = wx.getSharedCanvas()
  3. let context = sharedCanvas.getContext('2d')
  4. context.fillStyle = 'red'
  5. context.fillRect(0, 0, 100, 100)

在主域中可以通过开放数据域实例访问 sharedCanvas,通过 drawImage() 方法可以将 sharedCanvas 绘制到上屏画布。

  1. // game.js
  2. let openDataContext = wx.getOpenDataContext()
  3. let sharedCanvas = openDataContext.canvas
  4. let canvas = wx.createCanvas()
  5. let context = canvas.getContext('2d')
  6. context.drawImage(sharedCanvas, 0, 0)

sharedCanvas 的宽高只能在主域设置,不能在开放数据域中设置。

  1. // game.js
  2. sharedCanvas.width = 400
  3. sharedCanvas.height = 200

sharedCanvas 本质上也是一个离屏 Canvas,而重设 Canvas 的宽高会清空 Canvas 上的内容。所以要通知开放数据域去重绘 sharedCanvas。

  1. // game.js
  2. openDataContext.postMessage({
  3. command: 'render'
  4. })
  1. // src/myOpenDataContext/index.js
  2. openDataContext.onMessage(data => {
  3. if (data.command === 'render') {
  4. // ... 重绘 sharedCanvas
  5. }
  6. })

限制

当小游戏启动开放数据域,即在 game.json 中添加 openDataContext 配置项时。小游戏环境会对主域和开放数据域应用一些限制。

主域

  • sharedCanvas 只能被绘制到上屏 canvas 上。
  • 上屏 canvas 不能调用 toDataURL,其 context 不能调用 getImageData、readPixels。
  • sharedCanvas 不能调用 toDataURL 和 getContext。
  • 不能将上屏 canvas 和 sharedCanvas 以任意形式绘制到其他 canvas 上,包括 drawImage、createPattern、texImage2D、texSubImage2D。
  • sharedCanvas 的宽高只能在主域设置关系链数据 - 图2

开放数据域

  • 不能设置 sharedCanvas 的宽高开放数据域只能调用有限的 API,如下所示:

帧率

Timer

触摸事件

画布

开放数据域的所有 canvas 只支持 2d 渲染模式

图片

开放数据域的 Image 只能使用本地或微信 CDN 的图片,不能使用开发者自己服务器上的图片。对于非本地或非微信 CDN 的图片,可以先从主域 wx.downloadFile() 下载图片文件,再通过 OpenDataContext.postMessage() 把文件路径传给开放数据域去使用。

开放数据

监听主域消息