80 lines
3.3 KiB
JavaScript
80 lines
3.3 KiB
JavaScript
// Generated, do not edit. sha256:2b462247335f4413d5ae4038e57da8d4d3e70b4fb676fc84dcbba876e90e1c18
|
|||
|
|
import { loadCharting, readPalette } from '../ui/chart-setup.js';
|
||
|
|
import { t } from '../i18n/index.js';
|
||
|
|
import { fmtBase } from '../ui/format.js';
|
||
|
|
|
||
|
|
let tipEl = null;
|
||
|
|
const verberg = () => tipEl?.classList.remove('is-visible');
|
||
|
|
|
||
|
|
function tip({ chart, tooltip }, rijen) {
|
||
|
|
if (!tipEl) {
|
||
|
|
tipEl = document.createElement('div');
|
||
|
|
tipEl.className = 'ring-tip';
|
||
|
|
document.body.appendChild(tipEl);
|
||
|
|
window.addEventListener('scroll', verberg, { capture: true, passive: true });
|
||
|
|
}
|
||
|
|
if (!tooltip.opacity || !tooltip.dataPoints?.length) { verberg(); return; }
|
||
|
|
const r = rijen[tooltip.dataPoints[0].dataIndex];
|
||
|
|
const regel = (label, bedrag) => {
|
||
|
|
const rij = document.createElement('span');
|
||
|
|
rij.className = 'ring-tip-row';
|
||
|
|
const naam = document.createElement('span');
|
||
|
|
naam.className = 'ring-tip-pct';
|
||
|
|
naam.textContent = label;
|
||
|
|
const val = document.createElement('span');
|
||
|
|
val.className = 'val';
|
||
|
|
val.textContent = fmtBase(bedrag || 0);
|
||
|
|
rij.append(naam, val);
|
||
|
|
return rij;
|
||
|
|
};
|
||
|
|
const kop = document.createElement('span');
|
||
|
|
kop.className = 'ring-tip-label';
|
||
|
|
kop.textContent = r.label;
|
||
|
|
tipEl.replaceChildren(kop,
|
||
|
|
regel(t('wealth.valueEnd'), r.waarde),
|
||
|
|
regel(t('wealth.investedNet'), r.inleg),
|
||
|
|
regel(t('wealth.result'), r.resultaat));
|
||
|
|
const box = chart.canvas.getBoundingClientRect();
|
||
|
|
tipEl.style.left = `${Math.round(box.left + tooltip.caretX)}px`;
|
||
|
|
tipEl.style.top = `${Math.round(box.top + tooltip.caretY)}px`;
|
||
|
|
tipEl.classList.add('is-visible');
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function tekenJaarGrafiek(canvas, rijen) {
|
||
|
|
const Chart = await loadCharting();
|
||
|
|
const pal = readPalette();
|
||
|
|
const resultaat = rijen.map(r => r.resultaat || 0);
|
||
|
|
const grafiek = new Chart(canvas, {
|
||
|
|
data: {
|
||
|
|
labels: rijen.map(r => r.label),
|
||
|
|
datasets: [
|
||
|
|
{ type: 'bar', label: t('wealth.investedNet'), data: rijen.map(r => r.inleg || 0),
|
||
|
|
backgroundColor: pal.accentFaint, order: 2, yAxisID: 'y' },
|
||
|
|
{ type: 'bar', label: t('wealth.result'), data: resultaat,
|
||
|
|
backgroundColor: resultaat.map(v => (v >= 0 ? pal.sigGreen : pal.sigRed)), order: 2, yAxisID: 'y' },
|
||
|
|
{ type: 'line', label: t('wealth.valueEnd'), data: rijen.map(r => r.waarde || 0),
|
||
|
|
borderColor: pal.accent, backgroundColor: pal.accent, borderWidth: 2, pointRadius: 3,
|
||
|
|
cubicInterpolationMode: 'monotone', order: 1, yAxisID: 'waarde' },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
options: {
|
||
|
|
responsive: true,
|
||
|
|
maintainAspectRatio: false,
|
||
|
|
animation: false,
|
||
|
|
interaction: { mode: 'index', intersect: false },
|
||
|
|
scales: {
|
||
|
|
x: { grid: { display: false }, ticks: { color: pal.textSec } },
|
||
|
|
y: { ticks: { display: false }, grid: { color: pal.grid }, border: { display: false } },
|
||
|
|
waarde: { position: 'right', display: false, beginAtZero: true },
|
||
|
|
},
|
||
|
|
plugins: {
|
||
|
|
legend: { display: true, position: 'bottom', labels: { color: pal.textSec, boxWidth: 10, boxHeight: 10 } },
|
||
|
|
tooltip: { enabled: false, external: ctx => tip(ctx, rijen) },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
canvas.addEventListener('mouseleave', verberg);
|
||
|
|
const destroy = grafiek.destroy.bind(grafiek);
|
||
|
|
grafiek.destroy = () => { verberg(); destroy(); };
|
||
|
|
return grafiek;
|
||
|
|
}
|