前言
你知道什麼是「熱力圖 (Heatmap)」嗎?這是一種視覺化技術,透過顏色來呈現數據的強度,例如 GitHub 貢獻日曆。
在 Notion 中,雖然沒有內建的熱力圖功能,但透過 Notion Formula 2.0 的進化,像是 lets()
、style()
,我們可以創造出類似的視覺化效果!
✅ 如何透過 Notion 公式創建打卡日誌。
✅ 結合自己常用的打卡模式,來視覺化顯示數據。
如果你對 習慣追蹤系統 有興趣,還可以參考這篇文章Notion § 習慣打卡的不同模板設計,現在,就讓我們開始吧!🚀
✨ 日誌 + 周檢視
有些朋友會使用「日曆」的方式做習慣打卡,例如每天都要看是否早起、是否運動、是否閱讀等,這種模式中,習慣項目就是欄位,每次新增日期做為新的資料,這種方式特別適合已經有在寫日誌的朋友使用的。
資料庫設置
建立以下的資料庫和欄位:
- 周看板:習慣打卡(Relation)、視圖(Formula)。
- 日誌:週(Relation)、日期(Date)、今天狀態(Formula)、習慣一、習慣二……(Checkbox)。
注意事項
- 每當新增習慣時,都需要手動修改公式,添加對應的打卡狀態和圖標。
公式 - 日誌視圖
將習慣紀錄轉換為每日的狀態檢視,提供直覺化的打卡紀錄。
lets(
周幾, prop("日期").formatDate("ddd"),
打卡狀態, [prop("學習"), prop("護理"), prop("早睡"), prop("運動"), prop("閱讀")],
周幾.style("c", "b", "green")
+ " "
+ 打卡狀態.map(if(current==true,"✅", "⬜")).join("")
)
平時可以使用日曆視圖,作為打卡的頁面,如果你想要有當天狀態的檢視,可以使用 Filter 篩選當天的資料即可。

公式 - 周看板視圖
使用圖標,並結合日誌的打卡狀態,做一個以周檢視的視圖。

lets(
圖標, ["🖊️", "💄", "💤", "🏈", "📖"],
打卡狀態, prop("習慣打卡").sort(current.prop("日期")).map(current.prop("今天狀態")),
/* 輸出結果 */
" ".style("c", "b", "green")
+ " "
+ 圖標.join("")
+ "\n"
+ 打卡狀態.join("\n")
)
✨ 日誌 + 月檢視
同上個範例,適合本來使用日曆的方式做習慣打卡的朋友。
這個公式有點像是「Notion Formula 2.0 § 迷你月曆 」的公式,只是簡單版本,讓我們來看一下怎麼設置欄位與公式。
資料庫設置
- 月份檢視:月份(Name)、日期區間(Date)、日誌(Relation)、習慣一視圖、習慣二視圖、習慣三視圖……(Formula)。
- 日誌:日期(Date)、月份檢視(Relation)、習慣一、習慣二、習慣三……(Checkbox)。
注意事項
- 每增加一個習慣紀錄,在視覺化的圖像欄位就要新增一個欄位,且要手動修改公式中的習慣名稱。

lets(
有打卡日, filter(prop("日誌"), current.prop("習慣一") == true) /* 有打卡的項目 */
.map(current.prop("日期").date()), /* 有打卡的日期 */
天數間隔, dateBetween(prop("日期區間").dateEnd(), prop("日期區間").dateStart(), "days"),
月份天數, repeat(",", 天數間隔).split(","), /* 與月份天數相同的格子數量的空列表 */
月份日期, 月份天數.map(index + 1), /* 與月份天數相同的數字列表*/
打卡視圖, 月份天數.map(if(includes(有打卡日, index + 1), "✅", "⬜")),
/* 將列表變成文字串 */
打卡視圖.join("")
)
※註:在上面的公式中,我有多保留了一行「月份日期」,那是為了讓不熟悉輸出結果的朋友,比較容易理解而編寫的,自己使用可以把那行刪除喔~~
✨ 月度習慣總檢視
若想要以「月份」的角度,檢視當月中「所有習慣」的打卡狀態,那麼可以參考這個設置。
資料庫設置
建立以下的資料庫和欄位:
- 月度統計:月份(Date)、習慣項目(Relation)、視圖(Formula)。
- 習慣項目:月度統計(Relation)、打卡按鈕、打卡紀錄(Relation)、打卡檢視(Formula)、顏色(Select)。
- 打卡紀錄:習慣項目(Relation)、打卡時間(Date)。
注意事項

- 每月需要新增習慣項目,例如:「喝水 2 公升」在三月與四月要分別建立不同的記錄,並關聯到對應的月份。
- 建議將關聯欄位設置為「僅關聯一個頁面」,避免數據錯亂。
- 原範例在判斷式的部分使用「三元判斷式」撰寫的,我使用自己比較常用的
if()
撰寫公式,大家可以根據喜好選擇。
以月為單位的習慣檢視
這段公式顯示整個月所有關聯的習慣打卡視圖,並自動計算當月天數。

/* 月度統計的熱力圖 */
lets(
本月, prop("月份"),
次月, dateAdd(本月, 1, "months"),
天數, dateBetween(次月, 本月, "days"),
天數列表, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31].slice(0, 天數),
/* 美化顯示結果 */
標題列, "打卡項".padEnd(6, " ").style("c", "gray"), /* 這裡的空格是全形 */
天數列表_美化, 天數列表.map(current.padStart(2, "0") /* 補齊兩位數 */
.style("c", "b", "gray")
)
.join(" "), /* 刪除逗號 */
/* 輸出結果 */
標題列
+ " "
+ 天數列表_美化
+ "\n"
+ prop("習慣項目").map(current.prop("打卡檢視")).join("\n")
)
單一習慣月度檢視圖
這裡在「今天是否打卡」的部分,我使用計算次數的方式編寫,之後若需要可以再進一步延伸。

/* 打卡檢視 */
lets(
本月, prop("月度統計").first().prop("月份"),
次月, dateAdd(本月, 1, "months"),
天數, dateBetween(次月, 本月, "days"),
天數列表, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31].slice(0, 天數),
顏色, if(prop("顏色").empty(), "green", prop("顏色")),
/* 習慣名稱美化,名稱最多顯示前六個字 */
習慣名稱, prop("習慣名稱").substring(0, 6).padEnd(6, " ") /* 這裡的空格是全形 */
.style("c", 顏色, 顏色 + "_background"),
/* 不顯示日期,只顯示方格與標記 */
打卡紀錄, 天數列表.map(
lets(
今天日期, current,
今天是否打卡, prop("打卡紀錄")
.filter(current
.prop("打卡時間").date() == 今天日期.toNumber()),
今天打卡次數, 今天是否打卡.length(),
if(今天打卡次數 == 0, " ", "■■").style("c")
)
.style("c", 顏色, 顏色 + "_background")
)
.join(" ") /* 刪除逗號 */,
/* 輸出結果 */
習慣名稱 + " " + 打卡紀錄
)
✨ 不同習慣的月曆檢視
如果你需要長期檢視自己的習慣狀態,且該習慣會一直進行,那麼需要一個會自動新增日期的公式,來減少設置資料的時間。
若要無使用期限的設置,不知道大家是否有想到我之前提供的模板「萬年曆」呢?!這裡就來個簡單的版本,若想要像日曆一樣的格式,可以參考萬年曆的公式喔~

資料庫設置
- 習慣項目:打卡紀錄(Relation)、顏色(Select)、打卡按鈕(Button)、視圖(Formula)。
- 打卡紀錄:習慣(Relation)、打卡時間(Date)。
注意事項
- 在資料庫打卡的按鈕中的設定,在「打卡時間」的部分,要選擇
Data triggered
,不然視圖的顯示可能會出現錯誤😏。

- 這個模式很適合在不同的視圖(View)顯示,我常使用的是
Gallery View
,只要顯示打卡按鈕、顏色、與視圖公式即可。
lets(
顏色, if(prop("顏色"), prop("顏色"), "green"),
背景色, "gray_background",
有打卡, style("●", 顏色),
未打卡, style(" ", 顏色),
今天已打卡, style("▲", 顏色),
今天未打卡, style("△", 顏色),
星期欄位, ["M", "T", "W", "T", "F", "S", "S"],
標題年月, today().year() + "-" + today().month().padStart(2,0),
本月第一天, parseDate(標題年月),
次月第一天, dateAdd(本月第一天, 1, "months"),
本月最後一天, dateSubtract(次月第一天, 1, "days"),
第一周周一日期, 本月第一天.dateSubtract(本月第一天.day() - 1, "days"),
最後一周周日日期, 本月最後一天.dateAdd(7 - 本月最後一天.day(), "days"),
區間天數間隔, dateBetween(最後一周周日日期, 第一周周一日期, "days"),
區間所有日期, repeat(" ", 區間天數間隔 + 1)
.split("")
.map(第一周周一日期.dateAdd(index, "days")),
區間所有週數, 區間所有日期.map(current.week()).unique(),
標題, repeat(" ", 7) + 標題年月.style("b", "c", 顏色, 背景色),
星期欄位輸出, repeat(" ", 4)
+ 星期欄位.map(current.style("b", "c", 顏色, 背景色)).join(" "),
/* 輸出結果 */
標題
+ "\n"
+ 星期欄位輸出
+ "\n"
+ 區間所有週數.map(
lets(
周, current,
周標籤, "W" + 周.format().padStart(2, "0"),
一周日期, 區間所有日期.slice(7 * index, 7 * index + 7),
周標籤輸出, 周標籤.style("b", "c", 顏色, 背景色),
周標籤輸出
+ " "
+ 一周日期.map(
lets(
日期, current,
今天日期, if(日期 == today(), true, false),
打卡紀錄列表, prop("打卡紀錄").some(current.prop("打卡時間")
.dateBetween(日期, "days") == 0),
有打卡紀錄, if(今天日期, 今天已打卡, 有打卡),
無打卡紀錄, if(今天日期, 今天未打卡, 未打卡),
if(打卡紀錄列表, 有打卡紀錄, 無打卡紀錄).style("b", "c", 背景色)
)
).join(" ")
)
).join("\n")
)
✨不同習慣視圖轉軸檢視
將上一個範例中,把星期的欄位轉個方向,另一個方向以月分顯示,可以理解這是轉軸之後的樣式,這個方向也是比較像 Github 貢獻日曆的樣式。

資料庫設置
- 習慣項目:打卡紀錄(Relation)、顏色(Select)、打卡按鈕(Button)、視圖(Formula)。
- 打卡紀錄:習慣(Relation)、打卡時間(Date)。
注意事項
- 在「時間區間」的部分,不建議使用「年區間」,因為呈現的結果會太長,建議可以使用「季」或「月」(這是個人偏好,大家可以自行選擇)。
lets(
周數, ifs(
prop("時間長度") == "月", 5,
prop("時間長度") == "季", 13,
prop("時間長度") == "年", 52,
52
),
時間格式, "MMMM D, Y",
打卡紀錄, prop("打卡紀錄").filter(current)
.map(formatDate(current.prop("打卡時間"), 時間格式)),
顏色, prop("顏色"),
周標籤, ["Sun","Mon","Tue","Wen","Thu","Fri","Sat","Sun"]
.map(current.style(顏色 + "_background","gray","c","b", 顏色)),
今天是周幾, today().day(),
本周周日日期, if(今天是周幾 == 7, today(), dateSubtract(today(), 今天是周幾, "days")),
區間周日日期, dateSubtract(本周周日日期, 周數, "weeks"),
佔位符, ["M","M","M"]
.map(" ".style(顏色.format() +"_background","gray","c","b"))
.join(""),
月份標籤, repeat(" ", 周數 + 1)
.split("")
.map(dateAdd(區間周日日期, index, "weeks"))
.map(
ifs(
date(current) <= 4, formatDate(current, "MMMM").split("").at(0),
date(current.dateAdd(3, "days")) <= 4, formatDate(current.dateAdd(3, "days"), "MMMM").split("").at(0),
"◌"
)
)
.map(current.style(顏色.format() +"_background","gray","c","b", 顏色))
.join(" "),
打卡方格, [0,1,2,3,4,5,6]
.map(
/* 做出矩陣方格[0,0,0,0,1,1,....,6,6,6,6] */
repeat(current, if(今天是周幾 >= current, 周數 + 1, 周數))
.split("")
/* 將日期填入方格中 */
.map(dateAdd(區間周日日期, index * 7 + toNumber(current), "days"))
.map(formatDate(current, 時間格式))
/* 匹配打卡紀錄 */
.map(
ifs(
includes(打卡紀錄, current), style("●", "c", 顏色),
current == formatDate(now(), 時間格式), "◌",
" "
)
)
/* 將方格填入顏色 */
.map(
ifs(
current == "◌", "◌".style(顏色.format() + "_background","default_color","c","b"),
current == " ", " ".style(顏色.format() + "_background","green","c","b"),
current
)
).join(" ")
)
/* 在打卡方格前加入周標籤 */
.map(
周標籤.at(index) + " " + current
).join("\n"),
/* 輸出結果 */
佔位符 + " " + 月份標籤 + "\n" + 打卡方格
)
範例頁面
請在 Notion 頁面中查看。
結語
我原本想要進一步練習寫一個能夠計算「次數」或「數量」的真熱力圖,但在思考實際應用場景時,想到多數人在做打卡記錄時,可能只是在意「有沒有完成」,而不是累積的次數,因此,這樣的設計或許並不那麼必要。不過,我仍然覺得這種方式適合用來追蹤像是「每日睡眠時數」或「喝水量」這類需要計算數據的習慣。未來如果有機會,再來嘗試進一步編寫這樣的功能!
本文介紹了幾種不同的 打卡檢視方式,希望能幫助你更直覺地追蹤習慣執行狀態,不知道你最喜歡哪種視圖方式呢?歡迎留言交流!😊 🚀
`*-.,.-*`♩`*-.,.-*`♪`*-.,.-*`♫`*-.,.-*`♬`*-.,.-*`♩`*-.,.-*`♪`*-.,.-*`♫`-.,.-*
如果你喜歡這邊筆記文章,歡迎點個 ❤ + 🔖
如果參觀後覺得我的小窩還不錯,歡迎加入 🎉 Chloe的小窩 🎉
如果你覺得這些資料、模板對你有幫助,歡迎使用 🎁 贊助功能 🎁
`*-.,.-*`♩`*-.,.-*`♪`*-.,.-*`♫`*-.,.-*`♬`*-.,.-*`♩`*-.,.-*`♪`*-.,.-*`♫*-.,.-*
參考資料
- 阿汪同学【Notion 教程】用这个月度打卡热力才发现原来打卡会上瘾!!!|个性化进阶教程vol.8_哔哩哔哩_bilibili
- 阿汪同学Notion 新手教程之打卡率_哔哩哔哩_bilibili
- 小红书Notion公式✔️热力图还不会?试试这个方法 - 小红书
- RedditFrom notionself's profile on Reddit: How to draw that magica…
- tangbuzhiAchieved a GitHub Profile-Style Tracker in Just 11 Lines of …
- notionselfCrafting a pure notion formula magic
- aNerdyNotioneeraNerdyNotioneer on Twitter / X
- あか | Aka | Notionヲタクあか | Aka | Notionヲタク on Twitter / X
- LeoaiHow to Build a GitHub-Styled Habit Tracker with Notion Formu…