Skip to content

Commit

Permalink
Add selector for heatmap
Browse files Browse the repository at this point in the history
  • Loading branch information
ramsayleung committed Sep 5, 2024
1 parent 729f4be commit b69b5e8
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 142 deletions.
2 changes: 1 addition & 1 deletion content/en/about_me.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ lastmod = 2022-02-23T17:23:37+08:00
draft = false
+++

{{< heatmap title_text="Article Calendar" >}}
{{< heatmap title_text="Article Activity" language="EN">}}

## About me {#about-me}

Expand Down
2 changes: 1 addition & 1 deletion content/zh/about_me_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ draft = false
toc = true
+++

{{< heatmap title_text="文章日历" >}}
{{< heatmap title_text="文章日历" language="ZH" >}}

## <span class="section-num">0x0</span> 自我认知 {#自我认知}
一个努力但平凡普通的人,希望做个有趣的人, work hard and be nice to people.
Expand Down
293 changes: 153 additions & 140 deletions layouts/shortcodes/heatmap.html
Original file line number Diff line number Diff line change
@@ -1,151 +1,164 @@
<!-- credit for https://blog.douchi.space/hugo-blog-heatmap/ -->
<div
id="heatmap"
<div>
<div style="display: flex; justify-content: center; align-items: center">
<p style="margin-right: 15px; margin-bottom: 0; color: #333; padding: 8px">
{{ .Get "title_text" }}
</p>
<select
id="yearSelector"
style="
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #fff;
cursor: pointer;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
"
>
<!-- Years will be dynamically added here -->
</select>
</div>
<div
id="heatmap"
style="
display: block;
height: 150px;
width: 75%;
padding: 2px;
text-align: center;"
></div>
display: block;
height: 150px;
width: 75%;
padding: 2px;
margin: 0 auto;
text-align: center;
"
></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
<script type="text/javascript">
var chartDom = document.getElementById('heatmap');
var myChart = echarts.init(chartDom);
window.onresize = function() {
myChart.resize();
};
var option;
var chartDom = document.getElementById('heatmap');
var myChart = echarts.init(chartDom);
var yearSelector = document.getElementById('yearSelector');
window.onresize = function() {
myChart.resize();
};
var option;
var postsByDate = new Map();
var years = new Set();

// get date range by number of months
function getDateRange(months){
var startDate = new Date();
var mill = startDate.setMonth((startDate.getMonth() - months));
var endDate = +new Date();
startDate = +new Date(mill);
{{ range ((where .Site.RegularPages "Type" "post")) }}
var date = {{ .Date.Format "2006-01-02" }};
var year = {{ .Date.Format "2006" }};
years.add(year);
var postObj = new Map();
postObj.set("title", {{ .Title }});
postObj.set("link", {{ .RelPermalink }});
var wordCount = {{ .WordCount }};
var data = postsByDate.get(date);
if (data === undefined) {
data = new Map();
data.set("posts", []);
data.set("totalWordCount", 0);
}
var posts = data.get("posts");
posts.push(postObj);
var totalWordCount = data.get("totalWordCount");
totalWordCount += wordCount;
data.set("totalWordCount", totalWordCount);
postsByDate.set(date, data);
{{- end -}}

endDate = echarts.format.formatTime('yyyy-MM-dd', endDate);
startDate = echarts.format.formatTime('yyyy-MM-dd', startDate);
// Populate year selector
years = Array.from(years).sort().reverse();
years.forEach(year => {
var option = document.createElement('option');
option.value = year;
option.text = year;
yearSelector.appendChild(option);
});

var dateRange = [];
dateRange.push([
startDate,
endDate
]);
return dateRange
};
function getHeatmapData(year) {
var heatmapData = [];
for (const [date, data] of postsByDate.entries()) {
if (date.startsWith(year)) {
heatmapData.push([date, data.get("totalWordCount")]);
}
}
return heatmapData;
}

// get number of months by window size
function getMonthCount(){
const windowWidth = window.innerWidth;
if (windowWidth >= 600) {
return 12;
}
if (windowWidth >= 400) {
return 9;
}
return 6;
}
function updateHeatmap(year) {
option.calendar.range = year;
option.series.data = getHeatmapData(year);
myChart.setOption(option);
}

var postsByDate = new Map();
{{ range ((where .Site.RegularPages "Type" "post")) }}
yearSelector.addEventListener('change', function() {
updateHeatmap(this.value);
});

var date = {{ .Date.Format "2006-01-02" }};
var postObj = new Map();
postObj.set("title", {{ .Title }});
postObj.set("link", {{ .RelPermalink }});
var wordCount = {{ .WordCount }};
option = {
title: {
show: false,
},
legend: {
show: false,
},
visualMap: {
show: false,
min: 0,
max: 10000,
type: 'piecewise',
showLable: false,
orient: 'horizontal',
left: 'center',
top: 0,
itemGap: 10,
inRange: {
color: ['#c6e48b', '#7bc96f', '#239a3b', '#196127'],
},
},
calendar: {
top: 30,
left: 30,
right: 30,
cellSize: ['auto', 'auto'],
range: years[0],
itemStyle: {
color: '#fff',
borderWidth: 0.5,
borderColor: '#eee',
},
yearLabel: { show: false },
dayLabel: {
firstDay: 1,
nameMap: {{ .Get "language" }}
},
monthLabel: {
nameMap: {{ .Get "language" }}
},
splitLine: {
show: false,
},
},
tooltip: {
hideDelay: 1000,
enterable: true,
formatter: function (params) {
const date = params.data[0];
const posts = postsByDate.get(date).get("posts");
var content = `${date}`;
for (const [i, post] of posts.entries()) {
content += "<br>";
var link = post.get("link");
var title = post.get("title");
content += `<a href="${link}" target="_blank">${title}</a>`
}
return content;
}
},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 0,
data: getHeatmapData(years[0])
}
};

var data = postsByDate.get(date);
if (data === undefined) {
data = new Map();
data.set("posts", []);
data.set("totalWordCount", 0);
}
var posts = data.get("posts");
posts.push(postObj);
var totalWordCount = data.get("totalWordCount");
totalWordCount += wordCount;
data.set("totalWordCount", totalWordCount);
postsByDate.set(date, data);
{{- end -}}

var heatmapData = [];
for (const [date, data] of postsByDate.entries()) {
heatmapData.push([date, data.get("totalWordCount")]);
}

option = {
title: {
show: true,
top: 0,
left: 'center',
text: '{{ .Get "title_text" }}'
},
legend: {
show: false,
},
visualMap: {
show: false,
min: 0,
max: 10000,
type: 'piecewise',
showLable: false,
orient: 'horizontal',
left: 'center',
top: 0,
itemGap: 10,
inRange: {
color: ['#c6e48b', '#7bc96f', '#239a3b', '#196127'],
},
},
calendar: {
top: 50,
left: 30,
right: 30,
cellSize: ['auto', 'auto'],
range: getDateRange(getMonthCount()),
itemStyle: {
color: '#fff',
borderWidth: 0.5,
borderColor: '#eee',
},
yearLabel: {
show: false,
},
dayLabel: {
align: 'center',
nameMap: 'ZH',
},
monthLabel: {
nameMap: 'EN',
},
splitLine: {
show: false,
},
},
tooltip: {
hideDelay: 1000,
enterable: true,
formatter: function(params) {
const date = params.data[0];
const posts = postsByDate.get(date).get("posts");
var content = `${date}`;
for (const [i, post] of posts.entries()) {
content += "<br>";
var link = post.get("link");
var title = post.get("title");
content += `<a href="${link}" target="_blank">${title}</a>`
}
return content;
}

},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
data: heatmapData
}
};
option && myChart.setOption(option);
option && myChart.setOption(option);
</script>

0 comments on commit b69b5e8

Please sign in to comment.