关系链数据使用指南
一个B站用户的关系链数据包括两部分:
- 该用户好友的用户数据
- 该用户所在的某个群的群成员的用户数据。
为了丰富游戏的社交玩法,我们提供了获取关系链数据的 API:
- bl.getFollowingCloudStorage() 获取当前用户也玩该小游戏的已关注的用户数据
- bl.getAllCloudStorage() 获取也玩该小游戏的所有用户数据排序
用户的 游戏数据
指的是用户的段位、战绩等游戏业务特有的数据,通过调用 bl.setUserCloudStorage() 可以将当前用户的游戏数据托管在后台。只有被托管过数据的用户,才会被视为 玩过
该小游戏的用户,才会出现在 bl.getFollowingCloudStorage() 和 bl.getAllCloudStorage() 返回的对象数组中。
除此之外,我们还提供了以下 API:
- bl.removeUserCloudStorage() 删除用户托管数据中指定字段的数据
- bl.getUserCloudStorage() 获取当前用户的托管数据
bl.getUserCloudStorage、bl.getFollowingCloudStorage() 和 bl.getAllCloudStorage() 只能在 开放数据域
中调用。
bl.setUserCloudStorage() 和 bl.removeUserCloudStorage() 可以同时在 主域
和开放数据域中调用。
开放数据域
开放数据域
是一个封闭、独立的 JavaScript 作用域。要让代码运行在开放数据域,需要在 game.json 中添加配置项 openDataContext
指定开放数据域的代码目录。添加该配置项表示小游戏启用了开放数据域,这将会导致一些 限制。
{
"deviceOrientation": "portrait",
"openDataContext": "src/myOpenDataContext"
}
同时还需要在该目录下创建 index.js 作为开放数据域的入口文件,其代码运行在开放数据域。game.js 是整个游戏的入口文件,其代码运行在 主域
。对应以上配置,应该有如下的目录结构:
├── src
| └── myOpenDataContext
| ├── index.js
| └── ...
├── game.js
├── game.json
└── ...
src/myOpenDataContext 是 开放数据域的代码目录
,除 src/myOpenDataContext 以外是 主域的代码目录
。
主域和开放数据域中的代码不能相互 require。以如下的目录结构为例:
├── src
| └── myOpenDataContext
| ├── index.js
| ├── util.js
| └── ...
├── lib
| └── render.js
└── game.js
在 game.js 中不能 require('src/myOpenDataContext/util')
在 src/myOpenDataContext/index.js 中不能 require('../../lib/render.js')
主域和开放数据域的通信
开放数据域不能向主域发送消息。
主域可以向开放数据域发送消息。调用 bl.getOpenDataContext() 方法可以获取开放数据域实例,调用实例上的 OpenDataContext.postMessage() 方法可以向开放数据域发送消息。
// game.js
const openDataContext = bl.getOpenDataContext()
openDataContext.postMessage({
text: 'hello',
year: (new Date()).getFullYear()
})
在开放数据域中通过 bl.onMessage() 方法可以监听从主域发来的消息。
// src/myOpenDataContext/index.js
bl.onMessage(data => {
console.log(data)
/* {
text: 'hello',
year: 2018
} */
})
展示关系链数据
如果想要展示通过关系链 API 获取到的用户数据,如绘制排行榜等业务场景,需要将排行榜绘制到 sharedCanvas
上,再在主域将 sharedCanvas 渲染上屏。
// src/myOpenDataContext/index.js
const sharedCanvas = bl.getSharedCanvas()
function drawRankList(data) {
data.forEach((item, index) => {
// ...
})
}
bl.getFollowingCloudStorage({
success: res => {
const data = res.data
drawRankList(data)
}
})
sharedCanvas 是主域和开放数据域都可以访问的一个离屏画布。在开放数据域调用 bl.getSharedCanvas() 将返回 sharedCanvas。
// src/myOpenDataContext/index.js
const sharedCanvas = bl.getSharedCanvas()
const context = sharedCanvas.getContext('2d')
context.fillStyle = 'red'
context.fillRect(0, 0, 100, 100)
在主域中可以通过开放数据域实例访问 sharedCanvas,通过 drawImage() 方法可以将 sharedCanvas 绘制到上屏画布。
// game.js
const openDataContext = bl.getOpenDataContext()
const sharedCanvas = openDataContext.canvas
const canvas = bl.createCanvas()
const context = canvas.getContext('2d')
context.drawImage(sharedCanvas, 0, 0)
sharedCanvas 的宽高只能在主域设置,不能在开放数据域中设置。
// game.js
sharedCanvas.width = 400
sharedCanvas.height = 200
sharedCanvas 本质上也是一个离屏 Canvas,而重设 Canvas 的宽高会清空 Canvas 上的内容。所以要通知开放数据域去重绘 sharedCanvas。
// game.js
openDataContext.postMessage({
command: 'render'
})
// src/myOpenDataContext/index.js
openDataContext.onMessage(data => {
if (data.command === 'render') {
// ... 重绘 sharedCanvas
}
})
限制
当小游戏启动开放数据域,即在 game.json 中添加 openDataContext 配置项时。小游戏环境会对主域和开放数据域应用一些限制。
主域
- sharedCanvas 只能被绘制到上屏 canvas 上。
- 上屏 canvas 不能调用 toDataURL,其 context 不能调用 getImageData。
- sharedCanvas 不能调用 toDataURL 和 getContext。
- 不能将上屏 canvas 和 sharedCanvas 以任意形式绘制到其他 canvas 上,包括 drawImage、createPattern、texImage2D、texSubImage2D。
- sharedCanvas 的宽高只能在主域设置
基础库 3.10.0 主域限制修改如下
当开放域的 canvas 未绘制到主域上屏 canvas 时:
- 允许调用 canvas 的
toDataURL
, - 其
2d context
可以调用getImageData
, webgl Context
可以调用readPixels
如何定义开放域的 Canvas 是否绘制到主域?
- 2d 情况下调用
drawImage
、createPattern
并传递的为开放域 Canvas - webgl 情况下调用
blBindCanvasTexture
、texImage2D
并传递的为开放域 Canvas
- 不满足以上两条中的任意一条,则认为 未绘制
- 在未开启
preserveDrawingBuffer
配置的情况下,每次present/swap
后,都认为 未绘制
开放数据域
- 不能设置 sharedCanvas 的宽高
开放数据域只能调用有限的 API,如下所示:
帧率
Timer
触摸事件
- bl.onTouchStart()
- bl.onTouchMove()
- bl.onTouchEnd()
- bl.onTouchCancel()
- bl.offTouchStart()
- bl.offTouchMove()
- bl.offTouchEnd()
- bl.offTouchCancel()
画布
开放数据域的所有 canvas 只支持 2d
渲染模式
图片
开放数据域的 Image 只能使用本地或B站 CDN 的图片,不能使用开发者自己服务器上的图片。对于非本地或非B站 CDN 的图片,可以先从主域 bl.downloadFile() 下载图片文件,再通过 OpenDataContext.postMessage() 把文件路径传给开放数据域去使用。
开放数据
- bl.getFollowingCloudStorage()
- bl.getAllCloudStorage()
- bl.getUserCloudStorage()
- bl.setUserCloudStorage()
- bl.removeUserCloudStorage()
监听主域消息