文档 / Web Component
嵌入计时器
播放器与编辑器都是标准 Web Component。无需任何框架即可把播放器嵌入任意页面。
- 无需构建
- 不发送数据
- 用 CSS 变量定制主题
运行一个流程
复制完整 HTML 示例即可使用。托管的浏览器模块已包含依赖,无需安装包或构建工具。设置 sequence 属性,由用户点击“开始”,以便浏览器允许播放声音。
播放器底部默认显示一行“由时序计时器提供支持”的小链接,在新标签页打开本站。它是普通链接,点击前不发出任何请求。给元素加上 no-attribution 属性即可隐藏。
<!doctype html>
<html lang="zh-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<title>我的计时器</title>
<style>
body { margin: 0 auto; padding: 1rem; max-width: 48rem; font: 16px system-ui, sans-serif; }
sequence-timer-player, sequence-timer-builder { display: block; margin: 1rem 0; }
</style>
</head>
<body>
<h1>我的计时器</h1>
<sequence-timer-player locale="zh-CN"></sequence-timer-player>
<p data-status role="status"></p>
<script type="module">
import 'https://timer.eigentime.org/embed/v1/player.js';
const sequence = {
schemaVersion: 1,
id: 'my-timer',
metadata: { name: { 'zh-CN': '我的计时器' } },
children: [
{ type: 'phase', id: 'prepare', role: 'prepare', durationMs: 5000 },
{
type: 'group', id: 'round', repeat: 4,
children: [
{
type: 'phase', id: 'work', role: 'work', durationMs: 30000,
cues: { start: 'beep', countdownSeconds: 3 },
},
{ type: 'phase', id: 'rest', role: 'rest', durationMs: 10000 },
],
},
],
};
const player = document.querySelector('sequence-timer-player');
player.sequence = sequence;
player.addEventListener('complete', () => {
document.querySelector('[data-status]').textContent = '流程已完成。';
});
// Playback starts only when the visitor presses Start.
</script>
</body>
</html>编辑器与播放器
编辑器和播放器分别加载。编辑器的 start 事件提供已通过校验的流程,示例将其交给同一个播放器执行。
<!doctype html>
<html lang="zh-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<title>我的计时器</title>
<style>
body { margin: 0 auto; padding: 1rem; max-width: 48rem; font: 16px system-ui, sans-serif; }
sequence-timer-player, sequence-timer-builder { display: block; margin: 1rem 0; }
</style>
</head>
<body>
<h1>我的计时器</h1>
<sequence-timer-builder locale="zh-CN"></sequence-timer-builder>
<sequence-timer-player locale="zh-CN"></sequence-timer-player>
<p data-status role="status"></p>
<script type="module">
import 'https://timer.eigentime.org/embed/v1/player.js';
import 'https://timer.eigentime.org/embed/v1/builder.js';
const sequence = {
schemaVersion: 1,
id: 'my-timer',
metadata: { name: { 'zh-CN': '我的计时器' } },
children: [
{ type: 'phase', id: 'prepare', role: 'prepare', durationMs: 5000 },
{
type: 'group', id: 'round', repeat: 4,
children: [
{
type: 'phase', id: 'work', role: 'work', durationMs: 30000,
cues: { start: 'beep', countdownSeconds: 3 },
},
{ type: 'phase', id: 'rest', role: 'rest', durationMs: 10000 },
],
},
],
};
const player = document.querySelector('sequence-timer-player');
player.sequence = sequence;
player.addEventListener('complete', () => {
document.querySelector('[data-status]').textContent = '流程已完成。';
});
const builder = document.querySelector('sequence-timer-builder');
builder.sequence = sequence;
builder.addEventListener('start', async (event) => {
player.sequence = event.detail.sequence;
await player.updateComplete;
player.start();
player.scrollIntoView({ block: 'start' });
});
// Playback starts only when the visitor presses Start.
</script>
</body>
</html>事件
监听 statechange、phasechange、cue 与 complete 事件来驱动你自己的界面或统计——组件本身不会向任何地方发送数据。
const player = document.querySelector('sequence-timer-player');
player.addEventListener('statechange', (event) => {
// 'idle' | 'running' | 'paused' | 'completed'
console.log(event.detail.state);
});
player.addEventListener('phasechange', (event) => {
const { step } = event.detail;
console.log(step.phase.role, step.durationMs);
});
player.addEventListener('cue', (event) => {
console.log(event.detail.sound, event.detail.secondsRemaining);
});
player.addEventListener('complete', () => {
console.log('done');
});主题
颜色与尺寸通过 CSS 自定义属性暴露(--sequence-primary、--sequence-work 等),无需触碰 Shadow DOM 即可定制主题。--sequence-primary 与 --sequence-on-primary 请成对设置,以保证按钮文字清晰可读。
sequence-timer-player {
color-scheme: dark; /* light, dark, or inherit the page's */
--sequence-primary: #60a5fa;
--sequence-on-primary: #0b1220;
--sequence-work: #60a5fa;
--sequence-rest: #2dd4bf;
}交付与自托管
浏览器模块位于 /embed/v1/,使用标准 JavaScript 模块,并允许跨站加载。只导入 player.js 不会加载编辑器。自托管时,将构建产物 apps/web/dist/embed/v1/ 整个目录复制到自己的 HTTPS 站点,保留共享模块文件并修改 import 地址。v1 地址提供兼容更新,请勿混用不同版本的文件。
仓库中的 @sequence-timer/* 目前是私有工作区包,尚未发布到公共 npm。外部网站请使用这里的浏览器模块。
嵌入组件不安装离线缓存、不读取本站偏好、不自动保存流程,也不发送统计事件。保存和分享由宿主页面决定;站点的安装与离线功能仅属于在线工具。