-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
729f4be
commit b69b5e8
Showing
3 changed files
with
155 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |