@ 3d source/ angular- unreal- 模块
非真实引擎像素流化的独立角集成 。 包裹 提供场景组件,WebRTC和信号生命周期,NgRx状态, 命令/调回API、再连接、文件传输和遥测.
所需资源
- 角、角 CDK 和角形式
>=19.0.0 <23.0.0 - NgRx 存储和效果
>=19.0.0 <23.0.0 - RxJS 软件
>=7.8.0 <8.0.0 @3dsource/types-unreal >=0.0.14 <0.1.0provideHttpClient()在主机应用程序中
安装
pnpm add @3dsource/angular-unreal-module @3dsource/types-unreal
软件包是独立的,不会暴露出一个NgModule.
入境点
| 入境点 | 包含 |
|---|---|
@3dsource/angular-unreal-module | 一切——场景组件,服务,NgRx状态,提供者,助手 |
@3dsource/angular-unreal-module/config | UNREAL_CONFIG, (中文(简体) ), UnrealInitialConfig, (中文(简体) ), UnrealMode 仅无发动机,266B型密克罗尼西亚 |
从 /config 在应用程序根中保留其他
在懒惰的路径后导入 设置 为什么.
样式
包装自有样式并不需要UI库. 画的一切 视频上方通过三个级别可以定制 这解决了你的案子.
| 需求 | 职等 | 费用 |
|---|---|---|
| 不同颜色/ 半径/ 字体 | 设计符号 | 3行CSS线 |
| 整个街区的外观 | 类钩 | 全球风格的一个类 |
| 内部的一组不同的元素 | 插槽 | 一个模板 |
三个级别组成: 符号再现留下的颜色, 级钩再现一个 块,一个插槽取代里面的东西。 插槽可以让班钩 同一部分无关紧要 里面的标记就全是你的了.
可以自定义的东西
这些是场景从录像上画出来的街区. 没有别的东西是他们的—— 视频本身, 和仅以德文为主的封面, 是超出范围.
| 块 | 当用户看到时 | 仅收件 | 类钩子部件 | 槽 |
|---|---|---|---|---|
| 装入状态 | 连接时显示百分比 | ✓ | statusCard, (中文(简体) ), statusMessage | unrealStatusSlot |
| 恢复/ 开始 | 已暂停或尚未启动 | ✓ | resumeCard, (中文(简体) ), resumeText, (中文(简体) ), resumeButton | unrealResumeSlot |
| AFK 超时 | 下降前倒计时 | ✓ | afkScrim, (中文(简体) ), afkCard, (中文(简体) ), afkButton | unrealAfkSlot |
错误对话框( E)unreal-error-modal, (中文(简体) ), webrtc-error-modal已经 没有 部分内容
这个合同: 他们没有级钩,没有插槽, 他们读到
@3dsource/source-ui-native 指针( a)--src-*)而不是(a) --unreal-*他们
还在场外渲染出 DOM ——见"设计代号"下注.
1. 设计标志
设定 --unreal-* 变量在 app-unreal-scene ——自定义属性继承
穿过DOM,到达里面每个街区.
app-unreal-scene {
--unreal-surface-card: #101014;
--unreal-text-main: #f5f5f7;
--unreal-radius-card: 16px;
}
| 脚本 | 默认 |
|---|---|
--unreal-surface-card | #fff |
--unreal-surface-screen | #fff |
--unreal-surface-scrim | rgba(100, 100, 100, .7) |
--unreal-text-main | #1f2937 |
--unreal-text-secondary | #6b7280 |
--unreal-font-family | system-ui, sans-serif |
--unreal-radius-card | 8px |
--unreal-radius-pill | 9999px |
--unreal-shadow-card | 0 26px 80px 0 rgba(0,0,0,.2), 0 0 1px 0 rgba(0,0,0,.2) |
--unreal-accent | #017bff |
--unreal-accent-hover | #016fe6 |
--unreal-accent-text | #fff |
若为 @3dsource/source-ui-native 自动使用
在你没有设置的地方 --unreal-* 数值.
通过 CDK Dialog 打开的任何东西都无法达到 . 错误对话框 在现场DOM外的单独的上盖容器中渲染,所以变量 设置于
app-unreal-scene永远无法到达他们:root说明 这些对话框读取--src-*没有--unreal-*。 。 。 .
2. 级钩
自己提供一部分课程 替换 室内装饰课. 定位等级会留下来,因此场景布局无法被打破.
<app-unreal-scene [uiClasses]="{ resumeCard: 'my-card', statusCard: 'my-pill' }" />
部件 : resumeCard, (中文(简体) ), resumeText, (中文(简体) ), resumeButton, (中文(简体) ), afkScrim, (中文(简体) ), afkCard, (中文(简体) ),
afkButton, (中文(简体) ), statusCard, (中文(简体) ), statusMessage。 。 。 .
你们的课必须用全球风格 (单位:千美元)
styles.scss) (中文(简体) ). 已宣布为a 组件自己的SCSS,Angular瞄准它们,它们从未到达现场.
两个按钮部分的表现不同.
resumeButton财务报告和审定财务报表afkButton把你的课放在<app-unreal-button>主持人,但<button>内部是 图书馆部分,其风格有范围——和范围.unreal-button选择器( 0, 2, 0) 大于全局.my-cta button(0, 1, 1) (中文(简体) ). 钩子是 对按钮有好处 外部 框中(宽、边距、对齐);修改 按钮本身,使用--unreal-accent*符号,或者一个槽,如果您想要 完全不同标记.
afkScrim财务报告和审定财务报表--unreal-surface-scrim有一个提醒. 套装也 将留下一部分遗产,src/lib/styles/unreal.scss,则不属于 已公布的捆绑,且不准备导入。 它包含.frame #videoPlayOverlay { background-color: … }- 一个id选择器 超过任何等级。 如果你导入了部分, 它胜过两个 类钩子和 AFK 覆盖背景的符号.
3. 槽数
将块的内容替换为您自己的标记 。 模块保存 包和能见度逻辑;通过模板上下文获取数据.
<app-unreal-scene>
<ng-template unrealResumeSlot let-ctx>
<button (click)="ctx.start()" class="my-cta">{{ ctx.isSecondStart() ? 'Resume' : 'Start' }}</button>
</ng-template>
<ng-template unrealStatusSlot let-ctx>
<my-progress [value]="ctx.percents()" />
</ng-template>
</app-unreal-scene>
| 指令 | A. 背景情况 |
|---|---|
unrealResumeSlot | isSecondStart, (中文(简体) ), isAfkDisconnect, (中文(简体) ), start() |
unrealAfkSlot | countdown (左边秒), reset() |
unrealStatusSlot | percents, (中文(简体) ), message |
除方法外,所有上下文值都是信号-在模板中调用.
percents 实值 undefined 直到第一个值到达 —— 完成时守护它
它生动.
上下文对象被创建一次,从未被替换;什么是变化
里面有信号 这么说吧 let-ctx 是稳定的,你可以通过 ctx 在自由的周围.
插槽内的标记属于你,不是图书馆的. 角范围 a 模板到宣布该模板的组件,并宣布您的槽模板 内 组件。 有两个后果:
- 图书馆的自有课 在那里什么都不做。 写入
class="resume-box__text"在一个插槽内将无法取回模块的造型——该类的范围是: 模块.- 样式槽中包含您对任意标记的样式:您的组件 常设委员会通常适用(否)
::ng-deep,不需要全局样式表——与 阶级钩子.这个
--unreal-*符号 对 到达内部, 因为 CSS 自定义属性 通过 DOM 继承。 如果你想要你的标记也照做就读 主题:.my-cta { background: var(--unreal-accent, #017bff); border-radius: var(--unreal-radius-card, 8px); }
食谱
黑暗主题,没有别的. 一条规则, 无类型脚本 :
app-unreal-scene {
--unreal-surface-card: #101014;
--unreal-surface-screen: #0b0b0f;
--unreal-text-main: #f5f5f7;
--unreal-text-secondary: #a1a1aa;
--unreal-shadow-card: 0 20px 60px 0 rgb(0 0 0 / 60%);
}
你的口音在按钮上. 扣子是用标志来重现的,不是 带有分级钩子——参见上注:
app-unreal-scene {
--unreal-accent: #ff5f6d;
--unreal-accent-hover: #f0454f;
--unreal-accent-text: #fff;
}
如果您需要一个不同形状的按钮, 而不仅仅是重排, 替换
整个街区 unrealResumeSlot 并让自己的控制.
一个完全不同的装入状态. 结构,不仅仅是皮肤——所以 一个插槽。 可见度仍由模块决定:
<app-unreal-scene>
<ng-template unrealStatusSlot let-ctx>
<my-brand-progress [value]="ctx.percents() ?? 0" />
</ng-template>
</app-unreal-scene>
你无法改变的东西
- 当一个街区出现. 可见度留在模块上——条件 非三角( 连接状态、 重连接旗、 AFK 计时器) 和复制 在主机应用程序中它们是一个可靠的bug源.
- 街上有个街区. 每个自定义元素都保留一个 一个主机级从未替换的定位类,所以场景布局不能 从外面断开。 移走这个街区 换来是重新安装容器.
- 视频元素和 Dev 覆盖 (单位:千美元)
video-stats, (中文(简体) ),stat-graph) (中文(简体) ).
设置
1. 登记册状态和配置一次
在应用程序中添加不真实特性状态、 HTTP 客户端和配置
树根. UNREAL_CONFIG 需要,尽管其所有领域都是可选的.
import { provideHttpClient } from '@angular/common/http';
import type { ApplicationConfig } from '@angular/core';
import { provideStore } from '@ngrx/store';
import { provideUnrealState } from '@3dsource/angular-unreal-module';
import {
UNREAL_CONFIG,
type UnrealInitialConfig,
} from '@3dsource/angular-unreal-module/config';
const unrealConfig = {
regionsPingUrl: 'https://datacenter.3dsource.com/regions/',
dataChannelConnectionTimeout: 8000,
fpsMonitor: false,
} satisfies UnrealInitialConfig;
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideStore(),
provideUnrealState(),
{ provide: UNREAL_CONFIG, useValue: unrealConfig },
],
};
奥米 provideStore() 当 root NgRx 存储已配置时.
UNREAL_CONFIG 从 /config 有意进入 信物必须
可在 根号 注射器,因为模块的服务是
providedIn: 'root' 单通且无法看到路由级提供者。 包裹
自己作为密克罗尼西亚的船 建造在共同祖先的地块中放置一个模块
因此从包根中导入符使
整个引擎进入应用程序的急切捆绑。 在一个元盒生产建筑上
这是180 kB (49 kB gzip) 的原始 main 花在从未流出过的页面上.
这才有回报 没有别的了 在急切的图中导入软件包
树根。 遵循上述例子实际上没有资格——
provideUnrealState() 将密克罗尼西亚带回来。 一个想要的应用程序
引擎的初始捆绑动作 provideUnrealState() 对懒惰的人
路径并列 provideUnrealModule() (步骤2)
UNREAL_CONFIG 供养于根.
可用的配置字段 :
| 外地 | 目的 |
|---|---|
regionsPingUrl | 区域延迟终点 |
dataChannelConnectionTimeout | 数据频道连接超时( ms) |
customErrorsEndpoint | 自定义错误报告终点 |
streamTelemetryV2Url | 流出生命周期遥测终点 |
screenLockerContainerId | 屏幕上挂的容器 |
mode | 'metabox' (default) – 完整的Metabox命令协议; 'default' —— sock Pixel Streaming app, 该模块不会发送自己的Metabox命令 |
fpsMonitor | 启用 FPS 监控( 目前关闭 —— 服务不即时) |
disableFovRecalculation | 发送 payloadVersion: disableFovRecalculation 每一个分辨率变化,所以不真实保留相机FOV(工作室场景总是发送) |
playwright | 启用测试特定服务行为 |
使用 { provide: UNREAL_CONFIG, useValue: {} } 用于最小配置.
2. 在懒惰的路线上启动引擎
从应用程序路由器上轻松地装入路由文件 :
import type { Routes } from '@angular/router';
export const APP_ROUTES: Routes = [
{
path: 'stream',
loadChildren: () =>
import('./stream/stream.routes').then((module) => module.STREAM_ROUTES),
},
];
登记册 provideUnrealModule() 在懒惰路线文件中:
import type { Routes } from '@angular/router';
import { provideUnrealModule } from '@3dsource/angular-unreal-module';
import { StreamComponent } from './stream.component';
export const STREAM_ROUTES: Routes = [
{
path: '',
component: StreamComponent,
providers: [provideUnrealModule()],
},
];
保留 provideUnrealState() 财务报告和审定财务报表 UNREAL_CONFIG 在应用程序根.
这个 loadChildren() 边界使流出引擎脱离初始
捆绑 路线界定 provideUnrealModule() 撕下它的效果 当
路线是左边的.
UNREAL_CONFIG在路线上providers已经 没有 工作:引擎 服务是:providedIn: 'root',因此它们是由根注入器创建的 并读从那里得到的标志。 他们看不到路由级别值inject(UNREAL_CONFIG, { optional: true })决定:null例如 连接后区域从不运行(空)regionsPingUrl因此,没有 ưμ㼯a 没有一个。 只导入根上的符号不会将模块拖入 初始捆绑( 包是sideEffects: false) (中文(简体) ).
3. 现场介绍
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { UnrealSceneComponent } from '@3dsource/angular-unreal-module';
@Component({
selector: 'app-stream',
imports: [UnrealSceneComponent],
template: `<app-unreal-scene />`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StreamComponent {}
UnrealSceneComponent 还接受 isStudio, (中文(简体) ),
useContainerAsSizeProvider 财务报告和审定财务报表 resolutionSize 输入和输出
changeMouseOverScene。 。 。 .
主要 API
provideUnrealState()登记unrealFeatureNGRx州.provideUnrealModule()登记效应和靴子流服务.UnrealSceneComponent——制作并管理像素流出场景.UnrealCommunicatorService——发送指令和UI交互.UnrealCallbackService——观察不真实的回调和命令响应.unrealFeature,导出选择器和行动——显示连接和场景 生命周期状态.
命令包类型由 @3dsource/types-unreal。 。 。 .
那包装了两种轮廓 轮廓和QA 还有你的应用
此软件包必须解决 不变 一,选择是 tsconfig
路径在光谱上覆盖,从不导入。 一个无视的捆绑者
tsconfig 路径( 不匹配的平面维特或网络包) resolve.alias(中文(简体) )
从一个轮廓取出类型,从另一个轮廓取出激发值,其中
运行时而非编译时失败 。 参见"两个轮廓:活出和QA"
输入 @3dsource/types-unreal 读取.
运行 pnpm demo:start 从寄存器根查看场景组件
演示应用程序.
可选预选脚本
软件包发布两个无依赖脚本,供文档使用
<head> 角开始前 :
region-ping-prefetch.js提前测量区域,缓存全部结果 发布其活的答案。 连接从不等待: 请求 取了缓存区域, 否则预选者的答案, 如果它已经确定, 否则根本没有区域(由地理学IP来选择). 先装好 内<head>;没有它,缓存会在第一次连接后被填充.stream-prefetch.js打开并停放一个符合条件的 WebRTC 连接, 这样 Angular 可以在靴子后通过.
<script
src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/region-ping-prefetch.js"
async
></script>
<script
src="https://cdn.jsdelivr.net/npm/@3dsource/angular-unreal-module/js/stream-prefetch.js"
async
></script>
stream-prefetch.js 只运行 metabox-configurator/modular/{configuratorId}
路由 — 配置符 id 来自于路由, 没有属性 :
提供一,因此无法为任意的页面启用脚本.
读作同源 assets/config.json 财务报告和审定财务报表 assets/features.json,则
配置器的缓存记录 {cdn}/cache/configurator/{id}.json - 那个
与主机应用程序读取的文件相同
使用而不是发明一个。 这个 newOrchestration 特性旗选择
运输: signalling (HTTP投票)或 newSignalling (控制接头+)
requestStream) (中文(简体) ). 编剧: streamRequestId 已转发至
WebSocket URL 上的 Cirrus (会话) connectionId)并停放以供通过.
window.__stream 既是已停放的溪流, 又是锁: 任意一个脚本
和角模块首先写它拥有连接,所以一个页面永远不会
建设二. 从同一版本加载脚本和软件包——一个更古老的
脚本不知道锁.
可选 data-*数字 : data-config-url, (中文(简体) ), data-features-url, (中文(简体) ), data-ws-timeout, (中文(简体) ),
data-poll-timeout。 。 。 .
当确定性CDN资产是时, 将精确的软件包版本刻入生产中 所需经费.
仓库开发
从寄存器根运行命令 :
pnpm unreal-module:build
pnpm unreal-module:build:watch
pnpm unreal-module:lint
pnpm unreal-module:test
pnpm unreal-module:test:watch
pnpm unreal-module:test:signalling
pnpm unreal-module:test:signalling:leaks
unreal-module:build 建立本地 types-unreal 在此软件包之前依赖 .
发布命令只发布此软件包 :
pnpm unreal-module:release:patch
pnpm unreal-module:release:dev
成功发布后, 发行会自动清除匹配 jsDelivr标签. 重试失败的清理而不重运行发行 :
pnpm unreal-module:purge-cdn -- latest
pnpm unreal-module:purge-cdn -- dev
Repository工具化需要Node.js 24.16.0或更新和pnpm上版本.