前言
最近想在博客引入waketime的编码热力图,就研究了一下,
效果是这样的:

首先你已经使用过wakatime,
如果没有起前往如下教程,
引用站外链接
WakaTime的使用(vscode,idea,hbuilder)
WakaTime
教程
第一步
接下来前往WakaTime的API文档
引用站外链接
按照如下操作会得到json的接口

第二步
在source -> _data -> aside.yml (没有就新建)
下增加如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| - name: code title: 编码时长 class: card-code id: icon: fas fa-calendar-days content_id: code-info # content_css: 'height:160px;overflow:hidden' content_html: '<div class="codeTime"><div class="code" id="code"></div></div> <div class="legend"> <div class="legend-item"><div class="legend-color" style="background: #ebedf0;"></div>无数据</div> <div class="legend-item"><div class="legend-color" style="background: #9be9a8;"></div>0-2小时</div> <div class="legend-item"><div class="legend-color" style="background: #40c463;"></div>2-4小时</div> <div class="legend-item"><div class="legend-color" style="background: #30a14e;"></div>4-6小时</div> <div class="legend-item"><div class="legend-color" style="background: #216e39;"></div>6+小时</div> </div>'
|
然后在你的自定义入口 js 下输入
在source -> js -> 你的js (没有就新建)
在const response = await fetch(‘’)引入你在wakatime得到的接口
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| async function fetchData() { try { const response = await fetch(`https://wakatime.com/xxx.json`); const data = await response.json(); if (data) { console.log('成功获取数据,天数:', data.days.length); return data.days; } else { console.warn('数据格式不符合预期:', data); return []; } } catch (error) { console.error('获取数据失败:', error); return []; } }
function getColor(hours) { if (!hours || hours === 0) return '#ebedf0'; if (hours < 2) return '#9be9a8'; if (hours < 4) return '#40c463'; if (hours < 6) return '#30a14e'; return '#216e39'; }
function renderCalendar(days) { const calendarEl = document.getElementById('code'); const today = new Date(); const startDate = new Date(); startDate.setMonth(today.getMonth() - 11);
let currentDate = new Date(startDate); let currentMonth = currentDate.getMonth();
const firstDayOfWeek = currentDate.getDay(); for (let i = 0; i < firstDayOfWeek; i++) { const emptyDay = document.createElement('div'); emptyDay.className = 'day'; emptyDay.style.visibility = 'hidden'; calendarEl.appendChild(emptyDay); }
while (currentDate <= today) { if (currentDate.getMonth() !== currentMonth) { currentMonth = currentDate.getMonth(); }
const dateStr = currentDate.toISOString().split('T')[0]; const dayData = days.find(d => d.date === dateStr); const hours = dayData ? dayData.total / 3600 : 0;
const dayEl = document.createElement('div'); dayEl.className = 'day'; dayEl.style.backgroundColor = getColor(hours); dayEl.setAttribute('data-date', dateStr); dayEl.setAttribute('data-hours', hours.toFixed(1));
calendarEl.appendChild(dayEl);
currentDate.setDate(currentDate.getDate() + 1); } }
(async function () {
const data = await fetchData(); renderCalendar(data); })();
async function codeTime(){ const data = await fetchData(); renderCalendar(data); } function handlePjaxComplete() { if (isHomePage()) { codeTime() } }
function isHomePage() { return window.location.pathname === '/' || window.location.pathname === '/index.html'; }
window.onload = function () { document.addEventListener("pjax:complete", handlePjaxComplete); }
|
接下来在你的自定义入口 css 下输入
在source -> css -> 你的css (没有就新建)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| .code { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 7px; }
.day { width: 10px; height: 10px; border-radius: 2px; background: #ebedf0; position: relative; }
.day:hover::after { content: attr(data-date) " - " attr(data-hours) "小时"; position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 3px 6px; border-radius: 3px; font-size: 12px; white-space: nowrap; z-index: 100000; }
.month-label { width: 100%; margin-top: 10px; font-size: 12px; color: #666; }
.legend { margin-top: 5px; margin-bottom: 7px; display: flex; justify-content: space-between; }
.legend-item { display: flex; align-items: center; font-size: 9px; }
.legend-color { width: 12px; height: 12px; border-radius: 2px; margin-right: 5px; }
|
最后修改你的 _config.solitude.yml 中的aside
下的home新增code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| aside: # Values: about (info card), newestPost (latest article), allInfo (website information), newest_comment (latest comment) # 值: about(信息卡), newestPost(最新文章), allInfo(网站信息), newest_comment(最新评论)
# Sticky: Fixed position / noSticky: Not fixed position # Sticky: 固定位置 / noSticky: 不固定位置 home: # on the homepage noSticky: "about" Sticky: "code,allInfo" post: # on the article page noSticky: "about" Sticky: "newestPost" page: # on the page noSticky: "about" Sticky: "newestPost,allInfo" # 菜单栏位置(0: 左 1: 右) position: 1 # Sidebar positioning(0: left 1: right)
|
以及在extends
下的head
引入你的 js 和 css
示例:
1 2 3 4 5 6
| extends: # Insert in head # 插入到 head head: - <link rel="stylesheet" href="/css/customize.css"> - <script src="/js/custom.js"></script>
|
最后在首页就出现效果啦!
konoXIN
技术博客与生活分享 | 前端开发实战经验 | Vue.js 最佳实践
赞赏作者
😿😿😿 !特别感谢!😿😿😿
微信

支付宝
赞赏名单