Update heatmap with legend and extra color level
This commit is contained in:
parent
53084c4e6f
commit
d9784bdbd4
2 changed files with 75 additions and 11 deletions
|
|
@ -30,9 +30,10 @@ export function constructWeeks() {
|
||||||
|
|
||||||
function getColor(count) {
|
function getColor(count) {
|
||||||
if (count === 0) return "var(--color-empty)";
|
if (count === 0) return "var(--color-empty)";
|
||||||
if (count <= 3) return "var(--color-low)";
|
if (count <= 2) return "var(--color-l1)";
|
||||||
if (count <= 10) return "var(--color-mid)";
|
if (count <= 5) return "var(--color-l2)";
|
||||||
return "var(--color-high)";
|
if (count <= 10) return "var(--color-l3)";
|
||||||
|
return "var(--color-l4)";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function render(weeks, counts) {
|
export function render(weeks, counts) {
|
||||||
|
|
@ -85,6 +86,42 @@ export function render(weeks, counts) {
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function totalCount(counts) {
|
||||||
|
return Object.values(counts).reduce((s, v) => s + v, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderLegend() {
|
||||||
|
const CELL = 11;
|
||||||
|
const GAP = 3;
|
||||||
|
const SHIFT = CELL + GAP;
|
||||||
|
const svgNS = "http://www.w3.org/2000/svg";
|
||||||
|
const svg = document.createElementNS(svgNS, "svg");
|
||||||
|
svg.setAttribute("width", 5 * SHIFT - GAP);
|
||||||
|
svg.setAttribute("height", CELL);
|
||||||
|
svg.style.display = "inline-block";
|
||||||
|
svg.style.verticalAlign = "middle";
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
"var(--color-empty)",
|
||||||
|
"var(--color-l1)",
|
||||||
|
"var(--color-l2)",
|
||||||
|
"var(--color-l3)",
|
||||||
|
"var(--color-l4)",
|
||||||
|
];
|
||||||
|
colors.forEach((color, i) => {
|
||||||
|
const rect = document.createElementNS(svgNS, "rect");
|
||||||
|
rect.setAttribute("x", i * SHIFT);
|
||||||
|
rect.setAttribute("y", 0);
|
||||||
|
rect.setAttribute("width", CELL);
|
||||||
|
rect.setAttribute("height", CELL);
|
||||||
|
rect.setAttribute("fill", color);
|
||||||
|
rect.setAttribute("rx", 2);
|
||||||
|
svg.appendChild(rect);
|
||||||
|
});
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
}
|
||||||
|
|
||||||
export function setupTooltips(svg) {
|
export function setupTooltips(svg) {
|
||||||
const tooltip = document.getElementById("tooltip");
|
const tooltip = document.getElementById("tooltip");
|
||||||
document.body.appendChild(tooltip);
|
document.body.appendChild(tooltip);
|
||||||
|
|
@ -94,7 +131,7 @@ export function setupTooltips(svg) {
|
||||||
const date = e.target.dataset.date;
|
const date = e.target.dataset.date;
|
||||||
const count = e.target.dataset.count;
|
const count = e.target.dataset.count;
|
||||||
|
|
||||||
tooltip.textContent = `${date} - ${count} commit${count == 1 ? "" : "s"}`;
|
tooltip.textContent = `${date} - ${count} contribution${count == 1 ? "" : "s"}`;
|
||||||
tooltip.classList.remove("hidden");
|
tooltip.classList.remove("hidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,31 @@
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--color-empty: {{ $p.color_empty_dark }};
|
--color-empty: {{ $p.color_empty_dark }};
|
||||||
--color-low: {{ $p.color_low }};
|
--color-l1: {{ $p.color_max }};
|
||||||
--color-mid: {{ $p.color_mid }};
|
--color-l2: {{ $p.color_high }};
|
||||||
--color-high: {{ $p.color_high }};
|
--color-l3: {{ $p.color_mid }};
|
||||||
|
--color-l4: {{ $p.color_low }};
|
||||||
}
|
}
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
--color-empty: {{ $p.color_empty_light }};
|
--color-empty: {{ $p.color_empty_light }};
|
||||||
}
|
--color-l1: {{ $p.color_low }};
|
||||||
|
--color-l2: {{ $p.color_mid }};
|
||||||
|
--color-l3: {{ $p.color_high }};
|
||||||
|
--color-l4: {{ $p.color_max }};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#heatmap { overflow-x: auto; }
|
#heatmap { overflow-x: auto; }
|
||||||
#heatmap text { font-family: inherit; fill: currentColor; }
|
#heatmap text { font-family: inherit; fill: currentColor; }
|
||||||
#heatmap-caption {font-size: 0.8em; text-align: center; margin-top: 0px;}
|
#heatmap-caption {font-size: 0.8em; text-align: center; margin-top: 0px;}
|
||||||
|
#heatmap-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.75em;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
#heatmap-legend { display: flex; align-items: center; gap: 4px; }
|
||||||
#tooltip {
|
#tooltip {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background: #333;
|
background: #333;
|
||||||
|
|
@ -30,7 +43,7 @@
|
||||||
|
|
||||||
<div id="heatmap"></div>
|
<div id="heatmap"></div>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import {flattenData, constructWeeks, render, setupTooltips} from "{{ $js.RelPermalink }}"
|
import {flattenData, constructWeeks, render, setupTooltips, totalCount, renderLegend} from "{{ $js.RelPermalink }}"
|
||||||
|
|
||||||
const data = await fetch("/activity.json").then((r) => r.json());
|
const data = await fetch("/activity.json").then((r) => r.json());
|
||||||
const counts = flattenData(data);
|
const counts = flattenData(data);
|
||||||
|
|
@ -38,7 +51,21 @@
|
||||||
const svg = render(weeks, counts);
|
const svg = render(weeks, counts);
|
||||||
document.getElementById("heatmap").appendChild(svg);
|
document.getElementById("heatmap").appendChild(svg);
|
||||||
setupTooltips(svg);
|
setupTooltips(svg);
|
||||||
|
|
||||||
|
document.getElementById("contribution-count").textContent =
|
||||||
|
`${totalCount(counts)} contributions in the last year`;
|
||||||
|
|
||||||
|
const legendEl = document.getElementById("heatmap-legend");
|
||||||
|
legendEl.appendChild(document.createTextNode("Less"));
|
||||||
|
legendEl.appendChild(renderLegend());
|
||||||
|
legendEl.appendChild(document.createTextNode("More"));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div id="heatmap-footer">
|
||||||
|
<span id="contribution-count"></span>
|
||||||
|
<span id="heatmap-legend"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ with $p.caption }}
|
{{ with $p.caption }}
|
||||||
<p id="heatmap-caption"> {{ . | safeHTML }} </p>
|
<p id="heatmap-caption"> {{ . | safeHTML }} </p>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue