# hxh-dev-docs **Repository Path**: yawntee/hxh-dev-docs ## Basic Information - **Project Name**: hxh-dev-docs - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-01-24 - **Last Updated**: 2025-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 彗星号创意工坊开发文档 创意工坊的每个插件均为一个静态网页,既可以使用原生静态网页技术进行开发,也可以使用任意可编译为静态网页的语言开发,网页之间通过`window.postMessage`进行跨域交互 [全屏特效示例](全屏特效.html) **若需使用彗星号内置字体,可在``中添加以下代码,然后根据option更新事件提供的`fontFamily`修改字体** ```html ``` ## 环境判断 ```javascript const query = new URLSearchParams(location.search) // 是否处于配置状态 const isSetup = query.get('env') === '1' if(isSetup) { //配置时使用模拟数据展示效果 } ``` ## 共用类型 * 彗星号事件 ```typescript export interface ApiMessage { category: string type: string args: any[] } ``` * 创意工坊插件事件 ```typescript export interface PlugMessage{ fun: string args: any[] } ``` ## API * ##### 控制插件 ```typescript export interface Attr{ x: number; //与左侧横向距离 y: number; //与顶部纵向距离 w: number; //宽度 h: number; //高度 } ``` ```javascript //全屏 const args = { x: 0, y: 0, w: 1920, h: 1080, } parent.postMessage({ fun: 'attr', args, }, '*') ``` * 更新配置 ```javascript /* 假设插件配置结构为 { a: { b: 1, c: 2, } } */ //只修改b的值 const newOptio = { a: { b: 111 } } parent.postMessage({ fun: 'option', args: newOption, }, '*') ``` > 每个插件的当前配置结构可通过上传index.html并使用console.log输出到控制台获取 ## 更新事件(update) **所有更新事件将于页面加载完成之后触发一次,以便初始化数据** > 用户信息(user) * 示例 ```typescript window.addEventListener('message', e => { const { category, type, args:[userInfoList] } = e.data if(category === 'update' && type === 'user'){ console.log('用户信息更新了', userInfoList) } }) ``` * 参数 ```typescript interface PlatformUserInfo { room_id: number; //房间号 name: string; //昵称 } type UserInfoList = PlatformUserInfo[] ``` > 插件配置(option) * 示例 ```typescript window.addEventListener('message', e => { const { category, type, args:[option] } = e.data if(category === 'update' && type === 'option'){ console.log('插件配置更新了', option) } }) ``` * 全屏特效 ```typescript export enum Guard { NOTHING = 0, //普通观众 GOVERNOR = 1, //总督 SUPERVISOR = 2, //提督 CAPTAIN = 3, //舰长 } export interface Option { // 蒙层颜色 maskColor: string, // 上舰特效 guard: { /* 感谢文案 { 1:"感谢老板开通总督", 2:"感谢老板开通提督", 3:"感谢老板开通舰长" } */ banner: { [T in Exclude]: string } // 是否启用 enable: boolean } // 送礼特效 gift: { // 最低显示价格(RMB) min: number // 感谢文案 banner: string // 是否启用 enable: boolean } // 醒目留言特效 superChat: { // 感谢文案 banner: string // 是否启用 enable: boolean } } ``` # 直播间事件('event') 插件可以通过此API获取直播间的各种事件,执行对应的变化: ```javascript //监听事件 window.addEventListener('message', e => { const { category, type, args:[dm] } = e.data if(category === 'event' && type === 'LIVE_OPEN_PLATFORM_DM') console.log(dm.message) }) // 订阅直播间事件 parent.postMessage({ fun: 'subscribe', args: 'LIVE_OPEN_PLATFORM_DM' //使用数组可同时订阅多个事件 }, '*') ``` **`type`请参考[哔哩哔哩直播开放文档 (bilibili.com)](https://open-live.bilibili.com/document/f9ce25be-312e-1f4a-85fd-fef21f1637f8)中的`CMD`字段** > 通用 | 字段名 | 类型 | 描述 | | -------- | ---- | ---------- | | isAnchor | bool | 是否为主播 | > 弹幕 | 字段名 | 类型 | 描述 | | ---------------------- | ------ | ---------------------------------- | | id | string | 消息唯一id | | type | string | 事件类型 | | uname | string | 用户昵称 | | uid | int64 | 用户UID | | face | string | 用户头像 | | timestamp | int64 | 弹幕发送时间秒级时间戳 | | message | string | 弹幕内容 | | fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 | | fansMedalName | string | 粉丝勋章名 | | fansMedalLevel | int64 | 对应房间勋章信息 | | gloryLevel | int | 直播荣耀等级 | | emojiImgUrl | string | 表情包图片地址 | | dmType | int64 | 弹幕类型 0:普通弹幕 1:表情包弹幕 | | isModerator | bool | 是否为房管 | > 礼物 | 字段名 | 类型 | 描述 | | ---------------------- | ---------------- | --------------------------------------- | | id | int64 | 消息唯一id | | type | string | 事件类型 | | uid | int64 | 送礼用户UID | | uname | string | 送礼用户昵称 | | face | string | 送礼用户头像 | | giftId | int64 | 道具id(盲盒:爆出道具id) | | giftName | string | 道具名(盲盒:爆出道具名) | | giftNum | int64 | 赠送道具数量 | | price | int64 | 礼物单价(单位:RMB),盲盒:爆出道具的价值 | | paid | bool | 是否是付费道具 | | fansMedalLevel | int64 | 实际送礼人的勋章信息 | | fansMedalName | string | 粉丝勋章名 | | fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 | | guardLevel | int64 | 大航海等级 | | timestamp | int64 | 收礼时间秒级时间戳 | | giftIcon | string | 道具图标 | | comboGift | bool | 是否是combo道具 | | comboInfo | combo_info结构体 | 连击信息 | | combo_info | 类型 | 描述 | | :------------- | :----- | :--------------------- | | combo_base_num | int64 | 每次连击赠送的道具数量 | | combo_count | int64 | 连击次数 | | combo_id | string | 连击id | | combo_timeout | int64 | 连击有效期秒 | > 付费留言 | 字段名 | 类型 | 描述 | | ---------------------- | ------ | ---------------------- | | id | string | 消息唯一id | | type | string | 事件类型 | | uid | int64 | 购买用户UID | | uname | string | 购买的用户昵称 | | face | string | 购买用户头像 | | message | string | 留言内容 | | rmb | int64 | 支付金额(元) | | timestamp | int64 | 赠送时间秒级 | | startTime | int64 | 生效开始时间 | | endTime | int64 | 生效结束时间 | | guardLevel | int64 | 对应房间大航海等级 | | fansMedalLevel | int64 | 对应房间勋章信息 | | fansMedalName | string | 对应房间勋章名字 | | fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 | > 大航海 | 字段名 | 类型 | 描述 | | ---------------------- | ------ | ---------------------- | | id | string | 消息唯一id | | type | string | 事件类型 | | uid | int64 | 购买用户UID | | uname | string | 购买的用户昵称 | | face | string | 购买用户头像 | | guardLevel | int64 | 大航海等级 | | guardNum | int64 | 大航海数量 | | guardUnit | string | 大航海单位 | | fansMedalLevel | int64 | 粉丝勋章等级 | | fansMedalName | string | 粉丝勋章名 | | fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 | | timestamp | int64 | 上舰时间秒级时间戳 | > 进房 | 字段名 | 类型 | 描述 | | --------- | ------ | ----------- | | uid | int64 | 送礼用户UID | | face | string | 用户头像 | | uname | string | 用户昵称 | | timestamp | int64 | 秒级时间戳 | > 点赞 | 字段名 | 类型 | 描述 | | ---------------------- | ------ | ---------------------- | | uid | int64 | 点赞用户UID | | face | string | 用户头像 | | uname | string | 用户昵称 | | likeText | string | 点赞文案 | | likeCount | int64 | 点赞次数 | | fansMedalLevel | int64 | 粉丝勋章等级 | | fansMedalName | string | 粉丝勋章名 | | fansMedalWearingStatus | bool | 该房间粉丝勋章佩戴情况 | | timestamp | int64 | 秒级时间戳 | > 重置插件 * 事件名:`CLEAR_DATA` * 作用:点击配置中的清空数据按钮后,通知直播间中的插件清空数据 * **收到此事件后,若此插件有数据,则应重置插件状态** # 自定义作品配置 如果作品有额外配置参数需求,可以通过指定的json格式,在画布右侧配置栏创建额外的选项 ## 基本格式 | 字段名 | 类型 | 必须 | 描述 | | ------ | ------------------------------------ | ---- | ------------------------ | | key | string | 是 | ID (不能重复) | | name | string | 是 | 标题 | | type | string | 是 | 类型 (输入框、下拉框...) | | value | string \| number \| boolean \| array | 是 | 默认值 | ```json { "settings": [ { "key": "foo", "name": "自定义颜色", "type": "color", "value": "#ffffff" } ] } ``` ## CSS中使用 变量格式:`--worshop-` ```css .foo{ color: var(--workshop-color) } ``` ## 模板中使用 ```javascript const handlers = { update: { option(newValue) { //控制台输出自定义配置color的值 console.log(newValue._.color) }, } } //监听事件 window.addEventListener('message', e => { const { category, type, args } = e.data handlers[category]?.[type]?.apply(e, args) }) // 订阅事件 parent.postMessage({ fun: 'subscribe', args: Object.keys(handlers.event) }, '*') ``` ## 组件库 * 输入框(text, textarea) | 字段 | 类型 | 必须 | 描述 | | ----------- | ------ | ---- | -------------------- | | placeholder | string | 否 | 无内容时的提示 | | prefix | string | 否 | 前缀文本 | | suffix | string | 否 | 后缀文本 | | maxlength | number | 否 | 限制内容最大字符长度 | | rows | number | 否 | 输入框展示行数 | ```json { "settings": [ { "key": "text", "name": "输入框", "type": "text", "value": "默认内容", "prefix": "前缀内容", "suffix": "后缀内容" }, { "key": "textarea", "name": "多行输入框", "type": "textarea", "value": "默认内容", "placeholder": "请输入xxx", "maxlength": 30, "rows": 5 } ] } ``` * 数字输入框(decimal) | 字段 | 类型 | 必须 | 描述 | | ---- | ------ | ---- | ------------ | | step | number | 否 | 每次加减的值 | | min | number | 否 | 最小值 | | max | number | 否 | 最大值 | ```json { "settings": [ { "key": "interger", "name": "整数输入框", "type": "decimal", "value": 0 }, { "key": "decimal", "name": "小数输入框", "type": "decimal", "value": 0, "placeholder": "请输入xxx", "prefix": "前缀内容", "suffix": "后缀内容", "precision": 2, "step": 0.01, "min": -999.99, "max": 999.99 } ] } ``` * 滑动选择(slider) | 字段 | 类型 | 必须 | 描述 | | ----------- | ------ | ---- | -------------- | | placeholder | string | 否 | 无内容时的提示 | | prefix | string | 否 | 前缀文本 | | suffix | string | 否 | 后缀文本 | | precision | number | 否 | 小数位数 | | step | number | 否 | 每次加减的值 | | min | number | 否 | 最小值 | | max | number | 否 | 最大值 | ```json { "settings": [ { "key": "interger", "name": "整数滑块", "type": "slider", "value": 0 }, { "key": "decimal", "name": "小数滑块", "type": "slider", "value": 0, "step": 0.01, "min": -1, "max": 1 } ] } ``` * 复选框(checkbox) | 字段 | 类型 | 必须 | 描述 | | ---- | ---- | ---- | ---- | | | | | | ```json { "settings": [ { "key": "checkbox", "name": "复选框", "type": "checkbox", "value": true } ] } ``` * 开关(switch) | 字段 | 类型 | 必须 | 描述 | | ---- | ---- | ---- | ---- | | | | | | ```json { "settings": [ { "key": "switch", "name": "开关", "type": "switch", "value": true } ] } ``` * 选择器(select) | 字段 | 类型 | 必须 | 描述 | | -------- | -------------------------------- | ---- | ---------- | | options | {label: string, value: string}[] | 是 | 选项组 | | multiple | boolean | 否 | 是否可多选 | ```json { "settings": [ { "key": "select", "name": "选择器", "type": "select", "options": [ { "label": "我选A", "value": "A" }, { "label": "我选B", "value": "B" } ], "value": "B" }, { "key": "multipleSelect", "name": "多项选择器", "type": "select", "multiple": true, "options": [ { "label": "我选A", "value": "A" }, { "label": "我选B", "value": "B" } ], "value": [ "A", "B" ] } ] } ``` * 颜色选择器(color) | 字段 | 类型 | 必须 | 描述 | | ---- | ---- | ---- | ---- | | | | | | ```json { "settings": [ { "key": "color", "name": "颜色选择", "type": "color", "value": "#ffffffff" } ] } ``` * 图片上传(image) | 字段 | 类型 | 必须 | 描述 | | ---- | ---- | ---- | ---- | | | | | | ```json { "settings": [ { "key": "background", "name": "背景图片", "type": "image", "value": "" } ] } ```