【Obsidian】Dataview+自定义CSS实现热力图

由于Obsidian没有文件历史记录功能,就只做了文件创建时间和修改时间的检测,需要安装Dataview插件 做好了效果就像这样,可以点击箭头切换年份,鼠标悬停的时候也会显示修改和创建的笔记的数量

QQ20250523-143409

由于Obsidian对于过长的行数不会一次性加载全部,如果全部都用js代码的话就会导致点进笔记的时候不能加载出来,得滑动到下面才能加载

  • 所以这里我们采用自定义CSS的方式来减少笔记的行数

dataviewjs

function renderHeatmap(targetYear) {
  const container = dv.container;
  container.innerHTML = "";

  const createdMap = new Map();
  const modifiedMap = new Map();

  for (let page of dv.pages()) {
    const c = page.file.ctime;
    const m = page.file.mtime;

    if (c.year === targetYear) {
      const d = c.toISODate();
      createdMap.set(d, (createdMap.get(d) || 0) + 1);
    }

    if (m.year === targetYear) {
      const d = m.toISODate();
      modifiedMap.set(d, (modifiedMap.get(d) || 0) + 1);
    }
  }

  let start = dv.date(`${targetYear}-01-01`);
  while (start.weekday !== 7) start = start.minus({ days: 1 });
  let end = dv.date(`${targetYear}-12-31`);
  while (end.weekday !== 6) end = end.plus({ days: 1 });

  const dates = [];
  let current = start;
  while (current <= end) {
    dates.push(current);
    current = current.plus({ days: 1 });
  }

  const weeks = [];
  for (let i = 0; i < dates.length; i += 7) {
    weeks.push(dates.slice(i, i + 7));
  }

  // ==== 动态列数匹配样式 ====
const style = document.createElement("style");
style.textContent = `
  .grid {
    display: grid;
    grid-template-columns: repeat(${weeks.length}, 10px);
    gap: 1px;
  }
  .month-labels {
    display: grid;
    grid-template-columns: 12px repeat(${weeks.length}, 11px);
  }
`;
document.head.appendChild(style);

  function getLevel(n) {
    if (!n) return "level-0";
    if (n === 1) return "level-1";
    if (n <= 3) return "level-2";
    if (n <= 6) return "level-3";
    return "level-4";
  }

  const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  const monthStartCols = {};
  weeks.forEach((week, weekIdx) => {
    for (let day of week) {
      if (day.day === 1 && monthStartCols[day.month - 1] === undefined) {
        monthStartCols[day.month - 1] = weekIdx;
      }
    }
  });

  let monthHTML = `<div class="month-labels"><div></div>`;
  for (let i = 0; i < 12; i++) {
    if (monthStartCols[i] !== undefined) {
      const left = 11 + monthStartCols[i] * 11;
      monthHTML += `<div class="month-label" style="left: ${left}px;">${monthNames[i]}</div>`;
    }
  }
  monthHTML += `</div>`;

  const weekdayHTML = `
    <div class="weekday-labels">
      <span>S</span>
      <span>M</span>
      <span>T</span>
      <span>W</span>
      <span>T</span>
      <span>F</span>
      <span>S</span>
    </div>
  `;

  let gridHTML = `<div class="grid">`;
  for (let week of weeks) {
    gridHTML += `<div class="week">`;
    for (let d of week) {
      const dateStr = d.toISODate();
      const cCount = createdMap.get(dateStr) || 0;
      const mCount = modifiedMap.get(dateStr) || 0;

      let levelClass = "";
      if (cCount > 0) {
        levelClass = getLevel(cCount);
      } else if (mCount > 0) {
        levelClass = `mod-${getLevel(mCount)}`;
      } else {
        levelClass = "level-0";
      }

      const tooltipText = [
        `${dateStr}`,
        cCount > 0 ? `Created: ${cCount} notes` : "",
        mCount > 0 ? `Modified: ${mCount} notes` : ""
      ].filter(Boolean).join("<br>");

      gridHTML += `
        <div class="day ${levelClass} tooltip-wrapper">
          ${tooltipText ? `<div class="tooltip-text">${tooltipText}</div>` : ""}
        </div>`;
    }
    gridHTML += `</div>`;
  }
  gridHTML += `</div>`;

  container.innerHTML += `
    <div class="github-calendar-wrapper">
      <div class="github-calendar">
        <div class="calendar-header">
          <button onclick="__render(${targetYear - 1})">⬅️</button>
          <div class="year-label" onclick="__render(${new Date().getFullYear()})">${targetYear}</div>
          <button onclick="__render(${targetYear + 1})">➡️</button>
        </div>
        ${monthHTML}
        <div class="grid-area">
          ${weekdayHTML}
          ${gridHTML}
        </div>
      </div>
    </div>
  `;
}

window.__render = renderHeatmap;
renderHeatmap(dv.date("today").year);

heatmapcalendar.css

文件资源管理器中导航至Vault\.obsidian\snippets,将css文件放在里面 然后在Obsidian中设置-外观-自定义CSS代码启用相关css代码

heatmapcalendar
分享内容:heatmapcalendar.css 分享链接:http://ug.link/RSEGordon-NAS/filemgr/share-download/?id=0a1dba64781741afab8879b43c19d427

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇