对于 Obsidian 记录的状态一直有一个不痛不痒的需求:看看最近一段时间记录的统计数据。之所以不是强诉求是因为原生的状态栏(status bar)有相关统计展示,之前折腾过一个 Python 写的工具只实现了核心功能,显示部分没有做,最近在浏览 Obsidian 社区的时候发现了一个叫做 Better Word Count 的插件,这个插件对 Vault 有详细的数字统计,我打算利用目前已有的能力完成这个 Vault 状态显示的需求。
受到 Alfred Usage 的启发我打算用 Obsidian Chart 来完成图表的渲染,同时利用 Obsidian Dataview 数据处理能力来处理图表渲染需要的数据。
根据上面的思路,在完成工具开发之前 Obsidian 需要有几个前置依赖:
better word count 插件安装完成之后打开统计数据收集开关。
安装并使能 obsidian chart 插件,同时准备好 chartjs 文档以备后续使用。
安装并使能 dataview 插件,同时在配置中打开 dataviewjs。
在完成准备工作之后就可以进行 Vault 状态展示工具的开发了,欢迎动手能力强的同学直接拿着 gist code 去自定义修改,最后欢迎在评论区附上自己的效果图。
在 Obsidian 中新建(或直接嵌入到已有 note 的合适位置)note,在 note 中插入 dataviewjs(dataviewjs 的使用可以参考 dataview 文档),如下图所示:
根据 better word count 插件的描述,统计数据会以 JSON 的格式保存在文件 .obsidian/vault-stats.json
中。因此我们只需要读取和解析出需要渲染的数据即可,具体操作如下所示:
const staticsDataDir = this.app.vault.configDir + "/vault-stats.json";
const data = await this.app.vault.adapter.read(staticsDataDir);
const statics = JSON.parse(data);
let wordsData = [];
let filesData = [];
let pagesData = [];
const history = Object.keys(statics.history);
for (const date of history) {
wordsData.push({ x: date, y: statics.history[date].words });
filesData.push({ x: date, y: statics.history[date].files });
pagesData.push({ x: date, y: statics.history[date].totalPages });
}
根据 obsidian chart 文档来配置需要展示的图表,obsidian chart 底层使用的是 chartjs 所以很多图表配置项需要去 chartjs 文档中查找,如果你选者的是折线图显示可以直接参考下面这段代码:
const chartData = {
type: "line",
data: {
datasets: [
{
label: "Daily Words",
data: wordsData,
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1.2,
},
{
label: "Total Files",
data: filesData,
backgroundColor: ['rgba(75, 192, 192, 0.2)'],
borderColor: ['rgba(75, 192, 192, 1)'],
borderWidth: 1.2,
},
{
label: "Total Pages",
data: pagesData,
backgroundColor: ['rgba(54, 162, 235, 0.2)'],
borderColor: ['rgba(54, 162, 235, 1)'],
borderWidth: 1.2,
}
],
},
options: {
pointHoverBorderWidth: 6,
interaction: {
mode: 'index',
axis: 'y',
},
plugins: {
title: {
display: true,
text: 'Statistics of Obsidian Vault',
font: { weight: 'bold italic', size: '16px', family: 'Barlow' },
},
subtitle: {
display: true,
text: this.app.vault.getName(),
font: { size: '14px', style: 'italic', family: 'sans-serif' }
}
},
animations: {
tension: {
duration: 1000,
easing: 'easeInOutSine',
from: 0.5,
to: 0,
loop: true
}
},
scales: {
y: {
stacked: true,
border: {
display: true,
width: 0.8,
},
grid: {
display: true,
drawOnChartArea: true,
drawTicks: true,
color: 'rgba(239, 239, 239, 0.2)',
},
},
x: {
border: {
display: false,
width: 0.8,
},
grid: {
color: 'rgba(239, 239, 239, 0.2)',
},
},
},
},
};
在 dataviewjs 的最后加上如下的绘制代码即可:
// 调用 obsidian chart API
window.renderChart(chartData, this.container);
// P.S.
// renderChart 可以多次调用即绘制多张图表
chartjs 有很多进阶的配置可以去文档按图索骥,我的做法是直接搜索关键字,例如我想设置图表网格线的颜色,我在 chartjs 文档中搜索了一下 “grid” 就会发现对应的内容:
为了让图表看上去美观一点,我加了一点动画主要配置是这一段:
animations: {
tension: {
duration: 1000,
easing: 'easeInOutSine',
from: 0.5,
to: 0,
loop: true
}
},
看一下效果图:
图表支持悬停效果,我主要配置了数据展示:
pointHoverBorderWidth: 6,
interaction: {
mode: 'index',
axis: 'y',
},
chartjs 自定义能力非常强,后续我打算在交互做点文章,主要是很多配置支持 javascript 编程,如下图 dataset 参数所示,backgroundColor 是 scriptable 的就意味着可以通过编程实现 hover 改变背景颜色,深浅主题自动切换等等。这里有非常多的想象空间,欢迎愿意折腾的同学在评论区分享你的案例。