- 前端
- 数据可视化
【免费下载链接】TimelineJS
TimelineJS: A Storytelling Timeline built in JavaScript.
本篇指南以 TimelineJS(Knight Lab 出品的 JavaScript 时间线故事库)为对象,系统讲解如何在站点中嵌入时间线、全部可用的配置项(语言、地图样式、字体、书签与调试等)、四种数据来源格式(JSON / JSONP / Google 表格 / Storify)以及媒体自动识别机制,并对照本仓库源码给出底层实现依据。读完本文,你将能够从零搭建一个带多媒体、多语言、可自定义外观的时间线页面,并理解其加载与数据解析的工作流程。
版本状态提示:本仓库对应 TimelineJS 的 2.x 一代实现。README 顶部明确声明该版本已停止开发(GitHub issues 与 pull requests 均已关闭),Knight Lab 已推出新一代 TimelineJS3。新一代兼容旧版 Google 表格数据,但不兼容旧版 JSON 文件(JSON 格式有变更且无直接转换工具)。因此本文所述能力以当前仓库源码为准,适用于维护旧项目或学习该库的设计,接入新项目时应优先评估新版本。
为什么用 TimelineJS
网络上的时间线工具很多,但几乎都"难看得要命"或者"难用得要命"(README 原话:hard on the eyes or hard to use)。TimelineJS 的定位是同时做到美观与直观,并且擅长聚合来自不同来源的媒体——只需粘贴一条 Twitter、YouTube、Flickr、Vimeo、Google Maps 或 SoundCloud 链接,它就会自动拉取内容并格式化排版。
制作一条时间线也非常灵活:简单到填一张 Google 表格,精细到手写 JSON。仓库中 examples 目录提供了完整的可直接运行的示例(example_json.html、example_json.json、example_googlespreadsheet.html、example_storify.html 等),是学习接入的最佳起点。
嵌入到你的站点
方式一:内联配置(最简单)
在页面<body>中放置一个空 div,然后定义全局对象timeline_config,最后引入storyjs-embed.js即可:
<div id="timeline-embed"></div> <script type="text/javascript"> var timeline_config = { width: '100%', height: '600', source: 'path_to_json/or_link_to_googlespreadsheet', embed_id: 'timeline-embed', // 可选:使用不同的 DIV ID start_at_end: false, // 可选:从最新日期开始 start_at_slide: '4', // 可选:从指定幻灯片开始 start_zoom_adjust: '3', // 可选:微调默认缩放级别 hash_bookmark: true, // 可选:在地址栏写入 hash 书签 font: 'Bevan-PotanoSans', // 可选:字体组合 debug: true, // 可选:向控制台输出调试信息 lang: 'fr', // 可选:语言 maptype: 'watercolor', // 可选:地图样式 css: 'path_to_css/timeline.css', // 可选:自定义 CSS 路径 js: 'path_to_js/timeline-min.js' // 可选:自定义 JS 路径 } </script> <script type="text/javascript" src="path_to/storyjs-embed.js"></script>这里storyjs-embed.js可以从你本地构建产物加载(参照 examples/example_json.html 中的../build/js/storyjs-embed.js),也可以按 README 所述从 KnightLab CDN 加载。
内联方式之所以"最简单",是因为嵌入脚本会自动探测全局配置。查看 source/js/Core/Embed/Embed.js 可以发现它按固定优先级检查四个全局变量:url_config、timeline_config、storyjs_config、config,一旦发现其中某个是对象就立即调用createStoryJS完成初始化。
方式二:调用 createStoryJS 方法(进阶)
在storyjs-embed.js加载完成后,也可以手动调用createStoryJS函数初始化时间线:
createStoryJS({ type: 'timeline', width: '800', height: '600', source: 'path_to_json/or_link_to_googlespreadsheet', embed_id: 'my-timeline' // 目标 DIV 的 ID });结合 jQuery 的完整页面示例如下:
<head> <!-- jQuery --> <script type="text/javascript" src="path_to/jquery.min.js"></script> <!-- BEGIN TimelineJS --> <script type="text/javascript" src="path_to/storyjs-embed.js"></script> <script> $(document).ready(function() { createStoryJS({ type: 'timeline', width: '800', height: '600', source: 'path_to_json/or_link_to_googlespreadsheet', embed_id: 'my-timeline' }); }); </script> <!-- END TimelineJS --> </head> <body> <div id="my-timeline"></div> </body>加载文件:CDN 与本地两种路径
最省事的方式是只加载storyjs-embed.js,它内部会自动完成其余资源(jQuery、核心 JS、CSS、语言包、字体)的按需加载。如果你需要更细粒度的控制,可以分开加载 CSS 与 JS:
<!-- 始终加载 CSS --> <link rel="stylesheet" type="text/css" href="path_to/css/timeline.css"> <!-- 二选一 --> <script type="text/javascript" src="path_to/js/timeline.js"></script> <!-- 或 --> <script type="text/javascript" src="path_to/js/timeline-min.js"></script> <!-- 不要两个都加载 -->需要自建托管时,可把构建产物(build目录)整个搬到自己服务器,本地storyjs-embed.js会自动推导同源路径加载其余资源。这一机制在 source/js/Core/Embed/Embed.js 中有体现:脚本通过扫描<script>标签找到storyjs-embed.js的 URL,并据此推导embed_path(base / css / js / locale 路径)。
加载流程源码级解析
从 source/js/Core/Embed/Embed.js 可以看到完整的加载编排:
- 创建嵌入 div(
createEmbedDiv,处理宽高为百分比或像素两种情况); - 并行加载 CSS 与字体 CSS;
- 校验页面中已有的 jQuery 版本(要求 ≥ 1.7.1,不满足则从 CDN 拉取);
- 依次加载核心 JS、语言包(非
en时通过LazyLoad.js加载locale/xx.js); - 每完成一项回调
onloaded_check,累计 40 次轮询上限(每次间隔 250ms),全部就绪后调用buildEmbed实例化VMM.Timeline并init(config)。
字体方面内置了font_presets数组(Embed.js),每个预设对应一组 Google Fonts 族,命中后通过 WebFont 加载器异步加载。
配置选项(Config Options)
除上述示例外,README 还列出了以下配置项。下表汇总了所有选项、默认值与说明:
| 配置项 | 默认值 | 说明 |
|---|---|---|
source | (必填) | JSON 资源路径、JS 数据对象,或可自动识别的服务地址 |
lang | en | 界面本地化语言 |
start_at_end | false | 设为true从最后一个日期开始 |
start_at_slide | 0 | 从指定幻灯片编号开始 |
start_zoom_adjust | 0 | 微调时间轴缩放级别,正数放大、负数缩小 |
hash_bookmark | false | 允许用地址栏 hash 书签定位幻灯片 |
debug | false | 向控制台输出事件日志 |
gmap_key | (使用 maptype 时必须) | Google Maps API Key |
maptype | 空 | 地图样式(Stamen / Google / OpenStreetMap) |
font | default | 字体组合预设 |
type | timeline | 组件类型 |
width/height | 依嵌入方式 | 时间线尺寸,支持像素或百分比 |
embed_id | timeline-embed | 目标容器 DIV 的 ID |
source:四种输入形态
source既可以是 JSON 资源的路径,也可以直接传入一个符合 Timeline 模型的 JavaScript 对象:
var dataObject = {timeline: {headline: "Headline", type: ...}} createStoryJS({ type: 'timeline', width: '800', height: '600', source: dataObject, embed_id: 'my-timeline' });当source是字符串时,加载器会自动识别资源类型。底层识别逻辑在 source/js/VMM.Timeline.DataObj.js 的getData中:包含%23视为 Twitter 搜索;包含spreadsheet视为 Google 表格;包含storify.com视为 Storify 故事;以.jsonp结尾视为 JSONP;其余一律当作 JSON,并自动拼接?callback=onJSONP_Data回调参数请求。
Language 语言
lang默认是en(English)。README 列出的可用语言与仓库 source/js/Core/Language/locale 目录一一对应,共 50 余种,包括:af(南非荷兰语)、ar(阿拉伯语)、hy(亚美尼亚语)、eu(巴斯克语)、be(白俄罗斯语)、bg(保加利亚语)、ca(加泰罗尼亚语)、zh-cn(中文)、hr(克罗地亚语)、cz(捷克语)、da(丹麦语)、nl(荷兰语)、en(英语)、en-24hr(英语 24 小时制)、eo(世界语)、et(爱沙尼亚语)、fo(法罗语)、fa(波斯语)、fi(芬兰语)、fr(法语)、fy(弗里西语)、gl(加利西亚语)、ka(格鲁吉亚语)、de(德语)、el(希腊语)、he(希伯来语)、hi(印地语)、hu(匈牙利语)、is(冰岛语)、id(印度尼西亚语)、ga(爱尔兰语)、it(意大利语)、ja(日语)、ko(韩语)、lv(拉脱维亚语)、lt(立陶宛语)、lb(卢森堡语)、ms(马来语)、ne(尼泊尔语)、no(挪威语)、pl(波兰语)、pt(葡萄牙语)、pt-br(巴西葡萄牙语)、ro(罗马尼亚语)、rm(罗曼什语)、ru(俄语)、sr-cy(塞尔维亚语-西里尔)、sr(塞尔维亚语-拉丁)、si(僧伽罗语)、sk(斯洛伐克语)、sl(斯洛文尼亚语)、es(西班牙语)、sv(瑞典语)、tl(他加禄语)、ta(泰米尔语)、zh-tw(繁体中文)、te(泰卢固语)、th(泰语)、tr(土耳其语)、uk(乌克兰语)等。
语言文件结构可参考 en.js,包含lang代码、date的月份/星期名、dateformats的日期格式模板和messages的界面文案。渲染时 VMM.Date.js 的setLanguage会用语言文件覆盖默认的月份名、缩写与日期格式。若想新增语言,可按 DEVELOPER.md 的指引在 locale 目录添加以 ISO-639 代码命名的文件。
其他行为类选项
- start_at_end:
true时时间线从最后一个日期开始。实现位于 VMM.Timeline.js 的build函数:当config.start_at_end && config.current_slide == 0时,把当前幻灯片设置为_dates.length - 1。 - start_at_slide:从指定编号的幻灯片开始。对应 VMM.Timeline.js:
parseInt(config.start_at_slide) > 0时直接覆盖当前幻灯片。 - start_zoom_adjust:微调时间轴缩放级别,相当于按下指定次数的放大/缩小按钮,负数缩小。在
createConfig中被转换为config.nav.zoom.adjust(见 VMM.Timeline.js),时间轴导航组件据此调整缩放。 - hash_bookmark:
true时允许通过#哈希定位幻灯片。setHash会在滑动时将#编号写入地址栏(VMM.Timeline.js),同时window.onhashchange监听哈希变化驱动goToEvent跳转(VMM.Timeline.js)。 - debug:
true时向控制台输出事件日志。createStoryJS的buildEmbed会设置VMM.debug = storyjs_e_config.debug(Embed.js),随后各处trace()调用即受其控制;同时debug还决定加载未压缩版timeline.js还是压缩版timeline-min.js(Embed.js)。
Map Style Types 地图样式
由于 Google Maps API 的变更,使用自定义地图类型需要先提供 API Key。gmap_key是使用maptype的前提;其值会在createConfig中被写入config.api_keys.google(VMM.Timeline.js),供VMM.ExternalAPI.setKeys使用。
maptype可选值:
- Stamen Maps:
toner、toner-lines、toner-labels、watercolor、sterrain - Google Maps:
ROADMAP、TERRAIN、HYBRID、SATELLITE - OpenStreetMap:
osm
Font Options 字体组合
font用于切换标题与正文的字体组合,预设包括:
| 配置值 | 字体组合 |
|---|---|
AbrilFatface-Average | Abril Fatface & Average |
Arvo-PTSans | Arvo & PT Sans |
Bevan-PotanoSans | Bevan & Potano Sans |
BreeSerif-OpenSans | Bree Serif & Open Sans |
DroidSerif-DroidSans | Droid Serif & Droid Sans |
Georgia-Helvetica | Georgia & Helvetica Neue |
Lekton-Molengo | Lekton & Molengo |
Merriweather-NewsCycle | Merriweather & News Cycle |
NewsCycle-Merriweather | News Cycle & Merriweather |
NixieOne-Ledger | Nixie One & Ledger |
Pacifico-Arimo | Pacifico & Arimo |
PlayfairDisplay-Muli | Playfair Display & Muli |
PoiretOne-Molengo | Poiret One & Molengo |
PTSerif-PTSans | PT Serif & PT Sans |
PT | PT Sans & PT Narrow & PT Serif |
Rancho-Gudea | Rancho & Gudea |
SansitaOne-Kameron | Sansita One & Kameron |
也可以自行定制("Or make your own")。每个预设的 Google Fonts 定义与font_presets一一对应(Embed.js),同时对应 source/less/Core/Font 目录下的 LESS 主题文件(如Bevan-PotanoSans.less),构建时由 config.json 的lessc步骤编译为build/css/themes/font/*.css。各组合效果预览图见仓库本地副本:
文件格式(File Formats)
JSON:原生数据格式
JSON 是 TimelineJS 的原生数据格式。README 特别提醒:JSON 非常挑剔,一个放错的逗号或引号都可能导致时间线加载失败。以下是完整模型(同时可对照 examples/example_json.json 的真实数据):
{ "timeline": { "headline":"The Main Timeline Headline Goes here", "type":"default", "text":"<p>Intro body text goes here, some HTML is ok</p>", "asset": { "media":"http://yourdomain_or_socialmedialink_goes_here.jpg", "credit":"Credit Name Goes Here", "caption":"Caption text goes here" }, "date": [ { "startDate":"2011,12,10,07,02,10", "endDate":"2011,12,11,08,11", "headline":"Headline Goes Here", "text":"<p>Body text goes here, some HTML is OK</p>", "tag":"This is Optional", "classname":"optionaluniqueclassnamecanbeaddedhere", "asset": { "media":"http://twitter.com/ArjunaSoriano/status/164181156147900416", "thumbnail":"optional-32x32px.jpg", "credit":"Credit Name Goes Here", "caption":"Caption text goes here" } } ], "era": [ { "startDate":"2011,12,10", "endDate":"2011,12,11", "headline":"Headline Goes Here", "text":"<p>Body text goes here, some HTML is OK</p>", "tag":"This is Optional" } ] } }各字段含义:顶层headline/type/text/asset构成封面幻灯片(title slide);date数组为事件幻灯片,startDate/endDate为起止日期,headline/text为标题与正文(支持 HTML),tag为标签,classname可加自定义类名,asset中的media为媒体链接、thumbnail为缩略图、credit为署名、caption为说明文字;era数组用于时间轴上方的时代区间条。
日期格式支持逗号分隔的年、月、日、时、分、秒、毫秒(如"2011,12,10,07,02,10"),也支持斜杠格式(如"12/10/2011")。解析逻辑在 VMM.Date.js 的parse中:逗号分隔按位setFullYear / setMonth / setDate / setHours / setMinutes / setSeconds,并记录各部分精度(年/月/日/时/分/秒),用于决定日期显示粒度。事件在 VMM.Timeline.js 的buildDates中被逐一解析为内部日期对象,并按时间排序;若某条startDate为空会被跳过,且当有效日期数与原始条数不一致时会提示"Check for invalid date formats"。
JSONP:跨域加载
时间线支持 JSONP 变体以方便跨域加载数据。要点:文件必须以.jsonp结尾,且数据要赋给全局变量storyjs_jsonp_data:
storyjs_jsonp_data = { "timeline": { "headline":"The Main Timeline Headline Goes here", "type":"default", "text":"<p>Intro body text goes here, some HTML is ok</p>", "asset": { "media":"http://yourdomain_or_socialmedialink_goes_here.jpg", "credit":"Credit Name Goes Here", "caption":"Caption text goes here" }, "date": [ { "startDate":"2011,12,10", "endDate":"2011,12,11", "headline":"Headline Goes Here", "text":"<p>Body text goes here, some HTML is OK</p>", "tag":"This is Optional", "classname":"optionaluniqueclassnamecanbeaddedhere", "asset": { "media":"http://twitter.com/ArjunaSoriano/status/164181156147900416", "thumbnail":"optional-32x32px.jpg", "credit":"Credit Name Goes Here", "caption":"Caption text goes here" } } ], "era": [ { "startDate":"2011,12,10", "endDate":"2011,12,11", "headline":"Headline Goes Here", "tag":"This is Optional" } ] } }加载时 VMM.Timeline.DataObj.js 识别.jsonp后缀后用LoadLib.js动态注入该脚本,脚本执行完毕后触发onJSONPLoaded读取全局storyjs_jsonp_data并派发data_ready事件。仓库提供了 examples/example_jsonp.html 与 examples/model.jsonp 可直接对照使用。
Google Docs(Google 表格)
不想手写 JSON 的话,可以直接用 Google 表格构建时间线:把日期、文本、链接填入 TimelineJS 模板的对应列即可。创建步骤如下:
- 将表格设为公开:Google Docs 默认私有,但时间线读取要求表格公开。点击右上角蓝色 "Share" 按钮,在 "Share settings" 窗口中点击 "Change...",在 Visibility options 中选择 "Public on the Web" 并保存。
- 发布到 Web:在 File 菜单选择 "Publish to the Web",勾选 "Automatically republish when changes are made",取消其余勾选,点击 "start publishing",得到可嵌入 HTML 的 URL。
- 把 URL 粘贴进 HTML:选择 Web Page 选项的链接(而非 PDF、HTML、XLS 等),粘贴到时间线 HTML 的
source配置中。
底层实现方面,VMM.Timeline.DataObj.js 的extractSpreadsheetKey会从 URL 中解析表格 key(兼容key=参数与/spreadsheets/d/新版路径),然后请求https://spreadsheets.google.com/feeds/list/{key}/{worksheet}/public/values?alt=json解析数据;16 秒超时且最多重试 3 次。数据行中type列为start/title时作为封面幻灯片,为era时作为时代条,其余作为事件幻灯片。若feed.entry缺失,会提示检查是否有空行或表头是否被改动,并降级尝试 cells 接口。示例页面见 examples/example_googlespreadsheet.html。
Storify
Storify 支持仍处于早期阶段,但可用:直接把 Storify 故事链接作为source传入即可。底层 VMM.Timeline.DataObj.js 会调用 Storify API(//api.storify.com/v1/stories/{user}/{slug}),并把故事中的 image / quote / link / text / video 元素转换为事件幻灯片,媒体链接与作者信息一并格式化。
媒体(Media)
仓库 zip 中附带一个 kitchen sink(全功能演示)示例,展示如何整合 Twitter、YouTube、Flickr、Instagram、TwitPic、Wikipedia、Dailymotion、SoundCloud、Vimeo 等不同服务的媒体。用法极其简单:把浏览器地址栏中的媒体 URL 复制粘贴到media参数即可,TimelineJS 会通过各服务 API 自动拉取并格式化。媒体类型识别与渲染由 source/js/Core/Media/VMM.Media.js 与 VMM.MediaType.js 负责,外部 API 封装集中在 VMM.ExternalAPI.js。
最佳实践(Best practices)
README 给出了四条实战建议:
- 保持轻量:不要被过量的文字或其他元素拖累;
- 选择有强时间线叙事的题材:不适用于需要反复跳跃的时间线故事;
- 包含通向重大事件的过程性事件:不要只放重大事件本身;
- 不要淹没用户:几百个事件的时间线大概率不是该格式的最佳用法。
源码结构与构建(进阶阅读)
若需在本地构建或参与维护,可参考 DEVELOPER.md 与 config.json:
source目录为部署到 CDN 的资源源文件,website目录为官方文档站点,config.json 控制构建、暂存与部署。- 构建链路由 config.json 的
build段落定义,依次执行:copy(复制source下 CSS 图片与source/embed)、lessc(将 source/less/VMM.Timeline.less、source/less/Theme/Dark.less 与 source/less/Core/Font 编译为build/css/下的 CSS)、process(把 source/js/VMM.Timeline.js、source/js/VMM.Timeline.Min.js 及各 Embed 文件处理到build/js/)、minify(用 UglifyJS 压缩 locale 与核心 JS)、usemin、banner(写入版本与版权头)。 - 开发时可用
fab serve在本地起服务预览,fab build重新编译,fab stage/fab stage_latest暂存到 CDN 仓库,fab deploy部署文档站到 S3。注意环境要求 Python 2.7.x、Node.js、LESS 与 UglifyJS。
许可证
本项目采用 Mozilla Public License, v. 2.0(MPL-2.0)。完整声明见仓库根目录 LICENSE 文件。
- 前端
- 数据可视化
【免费下载链接】TimelineJS
TimelineJS: A Storytelling Timeline built in JavaScript.
相关推荐
SkyWalking OAP 动态配置接入 Nacos 2.x 完全指南:配置项、存储模型与源码解析
SkyWalking OAP 动态配置接入 Nacos 2.x 完全指南:配置项、存储模型与源码解析 Nacos 2.x 可以作为 SkyWalking OAP
可观测性APM链路追踪指标监控日志分析微服务Apache DolphinScheduler Oracle 数据源接入指南:参数配置、ServiceName/SID 连接模式与源码实现解析
Apache DolphinScheduler Oracle 数据源接入指南:参数配置、ServiceName/SID 连接模式与源码实现解析 本指南以 Apa
任务调度大数据后端前端ToolJet 接入 RethinkDB 数据源完整指南:连接配置、13 种操作与源码实现解析
ToolJet 接入 RethinkDB 数据源完整指南:连接配置、13 种操作与源码实现解析 ToolJet 原生提供 RethinkDB 数据源连接器,可让
低代码后端前端AI 应用MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考