@fu-css/fu-player 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -81
- package/dist/fu-player.es.js +428 -348
- package/dist/fu-player.umd.cjs +2 -2
- package/dist/types/components/types.d.ts +13 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/playerConfigDto.d.ts +65 -0
- package/dist/types/playerOptions.d.ts +24 -0
- package/package.json +14 -1
package/README.md
CHANGED
|
@@ -79,6 +79,8 @@ const head = applyFuPlayerSeoHead(videoSeo, {
|
|
|
79
79
|
twitterPlayerHeight: 720 // SEO:Twitter 播放器高度
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
const contactPhoneHref = "tel:+861380013****";
|
|
83
|
+
|
|
82
84
|
const player = createFuPlayer("#player", {
|
|
83
85
|
sources: [{ src: videoUrl, type: "video/mp4" }], // 播放器:视频源
|
|
84
86
|
poster: posterUrl, // 播放器:封面
|
|
@@ -97,13 +99,15 @@ const player = createFuPlayer("#player", {
|
|
|
97
99
|
transcript: videoSeo.transcript // GEO:转写语义文本
|
|
98
100
|
},
|
|
99
101
|
renderGeoText: true, // GEO:渲染语义文本层;设为 false 可关闭
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
display: {
|
|
103
|
+
share: { targets: ["copy", "x", "facebook"] }, // 播放器:分享入口
|
|
104
|
+
rightMenu: {
|
|
105
|
+
actions: [
|
|
106
|
+
{ kind: "phone", href: contactPhoneHref, label: "电话" },
|
|
107
|
+
{ kind: "email", href: "mailto:hello@example.com", label: "邮箱" }
|
|
108
|
+
]
|
|
109
|
+
} // 播放器:右侧快捷入口
|
|
110
|
+
}
|
|
107
111
|
});
|
|
108
112
|
|
|
109
113
|
// 后续可更新或销毁
|
|
@@ -126,6 +130,66 @@ HTML 只需要一个容器:
|
|
|
126
130
|
- `player.play()` / `player.pause()`:控制播放。
|
|
127
131
|
- `player.destroy()`:移除 DOM、监听器、adapter 和内部计时器。
|
|
128
132
|
- `applyFuPlayerSeoHead(seo, options)`:写入页面级 title、meta、canonical 等 head 标签,并返回可销毁句柄。
|
|
133
|
+
- `mergeFuPlayerOptions(...configs)`:合并通用配置和个性化配置;对象递归合并,数组和基础值由后面的配置覆盖。
|
|
134
|
+
- `buildFuPlayerOptionsFromDto(dto)`:把后端返回的 `commonOptions` / `personalizedOptions` DTO 转成播放器配置。
|
|
135
|
+
|
|
136
|
+
## 配置分层
|
|
137
|
+
|
|
138
|
+
通用配置放站点、客户或场景级默认值;个性化配置只放当前视频或页面自己的内容。最终在调用 `createFuPlayer` 前合并一次。
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { createFuPlayer, mergeFuPlayerOptions, type FuPlayerSimpleOptions } from "@fu-css/fu-player";
|
|
142
|
+
|
|
143
|
+
function createCommonPlayerConfig(phoneHref: string): FuPlayerSimpleOptions {
|
|
144
|
+
if (!phoneHref) {
|
|
145
|
+
throw new Error("Missing required phoneHref for the default quick action.");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
aspectRatio: "16 / 9",
|
|
150
|
+
controls: true,
|
|
151
|
+
pauseOtherPlayers: true,
|
|
152
|
+
display: {
|
|
153
|
+
share: {
|
|
154
|
+
targets: ["copy", "x", "facebook"],
|
|
155
|
+
buttonLabel: "Share"
|
|
156
|
+
},
|
|
157
|
+
rightMenu: {
|
|
158
|
+
ariaLabel: "Quick actions",
|
|
159
|
+
actions: [
|
|
160
|
+
{ kind: "phone", href: phoneHref, label: "Phone" },
|
|
161
|
+
{ kind: "email", href: "mailto:hello@example.com", label: "Email" }
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const options = mergeFuPlayerOptions(createCommonPlayerConfig("tel:+861380013****"), {
|
|
169
|
+
sources: [{ src: "https://example.com/video.mp4", type: "video/mp4" }],
|
|
170
|
+
poster: "https://example.com/poster.webp",
|
|
171
|
+
seo: videoSeo,
|
|
172
|
+
display: {
|
|
173
|
+
share: {
|
|
174
|
+
title: videoSeo.name,
|
|
175
|
+
text: videoSeo.description
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
createFuPlayer("#player", options);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
需要关闭通用显示配置里的对象能力时,传 `display: { share: false }` 或 `display: { rightMenu: false }` 显式覆盖。数组字段默认整体替换,例如 `display.share.targets` 和 `display.rightMenu.actions`。
|
|
184
|
+
|
|
185
|
+
后端已经按 profile 返回 DTO 时,可以直接转换;DTO 的 `player` 只放可序列化播放行为,分享、右侧菜单等显示项统一放 `display`。DTO 显示配置使用 `actionKey` / `actionPayload` 表达自定义行为,前端运行态再绑定 `onClick`。
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { buildFuPlayerOptionsFromDto, createFuPlayer } from "@fu-css/fu-player";
|
|
189
|
+
|
|
190
|
+
const options = buildFuPlayerOptionsFromDto(playerConfigDto);
|
|
191
|
+
createFuPlayer("#player", options);
|
|
192
|
+
```
|
|
129
193
|
|
|
130
194
|
## 常用配置
|
|
131
195
|
|
|
@@ -136,16 +200,16 @@ HTML 只需要一个容器:
|
|
|
136
200
|
- `src` / `sources`:视频地址,`sources` 优先。
|
|
137
201
|
- `poster`:视频封面;短调用可省略。
|
|
138
202
|
- `seoMode`:`indexable` 默认直接创建 `<video>`;`lazy` 可先显示封面,播放或进入视口后创建视频元素。
|
|
139
|
-
- `share`:`false` 关闭分享菜单;对象形式可配置分享目标、文案和 URL。
|
|
140
|
-
- `rightMenu`:`false` 关闭右侧快捷入口;数组或对象形式可配置电话、邮箱、WhatsApp 或自定义入口。
|
|
203
|
+
- `display.share`:`false` 关闭分享菜单;对象形式可配置分享目标、文案和 URL。
|
|
204
|
+
- `display.rightMenu`:`false` 关闭右侧快捷入口;数组或对象形式可配置电话、邮箱、WhatsApp 或自定义入口。
|
|
141
205
|
- `autoPlay`:开启后初始静音,以匹配浏览器自动播放策略。
|
|
142
|
-
- `hideMenu` / `hideControls`:分别隐藏菜单入口和底部控制栏。
|
|
206
|
+
- `display.hideMenu` / `display.hideControls`:分别隐藏菜单入口和底部控制栏。
|
|
143
207
|
- `sourceAdapters`:接入 HLS、DASH 等非原生播放源。
|
|
144
208
|
- `pauseOtherPlayers`:设为 `true` 时,当前实例开始播放会自动暂停页面上的其他 FuPlayer 实例。
|
|
145
209
|
|
|
146
210
|
## 自定义分享
|
|
147
211
|
|
|
148
|
-
`share.targets` 支持三种写法:
|
|
212
|
+
`display.share.targets` 支持三种写法:
|
|
149
213
|
|
|
150
214
|
- 内置字符串:`"copy"`、`"x"`、`"facebook"`、`"linkedin"`、`"whatsapp"`。
|
|
151
215
|
- 内置覆盖:使用 `{ preset: "x", ... }` 保留内置目标,同时覆盖图标、文案、链接或行为。
|
|
@@ -154,45 +218,47 @@ HTML 只需要一个容器:
|
|
|
154
218
|
```ts
|
|
155
219
|
createFuPlayer("#player", "https://example.com/video.mp4", {
|
|
156
220
|
title: "安装演示",
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
event
|
|
184
|
-
|
|
221
|
+
display: {
|
|
222
|
+
share: {
|
|
223
|
+
url: "https://example.com/video-page",
|
|
224
|
+
title: "安装演示",
|
|
225
|
+
text: "播放器安装和配置流程。",
|
|
226
|
+
buttonLabel: "分享视频",
|
|
227
|
+
buttonIcon: "享",
|
|
228
|
+
buttonClassName: "my-share-trigger",
|
|
229
|
+
menuLabel: "选择分享方式",
|
|
230
|
+
menuClassName: "my-share-menu",
|
|
231
|
+
targets: [
|
|
232
|
+
"copy",
|
|
233
|
+
{
|
|
234
|
+
preset: "x",
|
|
235
|
+
label: "发到 X",
|
|
236
|
+
iconPath: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",
|
|
237
|
+
href: ({ url, title }) =>
|
|
238
|
+
`https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: "wechat",
|
|
242
|
+
label: "微信",
|
|
243
|
+
ariaLabel: "分享到微信",
|
|
244
|
+
icon: "微",
|
|
245
|
+
className: "my-share-option",
|
|
246
|
+
iconClassName: "my-share-icon",
|
|
247
|
+
onClick: async (payload, event) => {
|
|
248
|
+
event.preventDefault();
|
|
249
|
+
window.dispatchEvent(new CustomEvent("wechat-share", { detail: payload }));
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: "download",
|
|
254
|
+
label: "下载",
|
|
255
|
+
icon: "↓",
|
|
256
|
+
href: "https://example.com/video.mp4",
|
|
257
|
+
target: "_blank",
|
|
258
|
+
rel: "noopener"
|
|
185
259
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
id: "download",
|
|
189
|
-
label: "下载",
|
|
190
|
-
icon: "↓",
|
|
191
|
-
href: "https://example.com/video.mp4",
|
|
192
|
-
target: "_blank",
|
|
193
|
-
rel: "noopener"
|
|
194
|
-
}
|
|
195
|
-
]
|
|
260
|
+
]
|
|
261
|
+
}
|
|
196
262
|
}
|
|
197
263
|
});
|
|
198
264
|
```
|
|
@@ -209,42 +275,44 @@ createFuPlayer("#player", "https://example.com/video.mp4", {
|
|
|
209
275
|
|
|
210
276
|
## 自定义右侧菜单
|
|
211
277
|
|
|
212
|
-
右侧菜单通过 `rightMenu.actions` 配置。每个 action 既可以是链接,也可以是纯行为按钮;`iconPath` 优先于 `icon`,`icon` 会覆盖内置图标。
|
|
278
|
+
右侧菜单通过 `display.rightMenu.actions` 配置。每个 action 既可以是链接,也可以是纯行为按钮;`iconPath` 优先于 `icon`,`icon` 会覆盖内置图标。
|
|
213
279
|
|
|
214
280
|
```ts
|
|
215
281
|
createFuPlayer("#player", "https://example.com/video.mp4", {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
event
|
|
236
|
-
|
|
282
|
+
display: {
|
|
283
|
+
rightMenu: {
|
|
284
|
+
ariaLabel: "快捷操作",
|
|
285
|
+
actions: [
|
|
286
|
+
{
|
|
287
|
+
kind: "phone",
|
|
288
|
+
href: "tel:+861380013****",
|
|
289
|
+
label: "电话",
|
|
290
|
+
iconPath: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1C10.61 21 3 13.39 3 4c0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.24.2 2.45.57 3.57.11.35.03.74-.25 1.02z",
|
|
291
|
+
className: "my-menu-phone"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
kind: "help",
|
|
295
|
+
label: "帮助",
|
|
296
|
+
ariaLabel: "打开帮助面板",
|
|
297
|
+
icon: "?",
|
|
298
|
+
className: "my-menu-help",
|
|
299
|
+
style: { background: "#111827" },
|
|
300
|
+
iconStyle: { color: "#fff" },
|
|
301
|
+
onClick: (event) => {
|
|
302
|
+
event.preventDefault();
|
|
303
|
+
window.dispatchEvent(new CustomEvent("fu-player-help"));
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
kind: "docs",
|
|
308
|
+
href: "https://example.com/docs",
|
|
309
|
+
label: "文档",
|
|
310
|
+
icon: "D",
|
|
311
|
+
target: "_blank",
|
|
312
|
+
rel: "noopener noreferrer"
|
|
237
313
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
kind: "docs",
|
|
241
|
-
href: "https://example.com/docs",
|
|
242
|
-
label: "文档",
|
|
243
|
-
icon: "D",
|
|
244
|
-
target: "_blank",
|
|
245
|
-
rel: "noopener noreferrer"
|
|
246
|
-
}
|
|
247
|
-
]
|
|
314
|
+
]
|
|
315
|
+
}
|
|
248
316
|
}
|
|
249
317
|
});
|
|
250
318
|
```
|