Cirkeldiagram met legenda en hover New
SVG pie chart that sweeps in when in view, with a legend of buttons beside it. Hovering a slice or legend row highlights both, nudges the slice outwards and shows count and percentage in a live line; clicking pins the choice. The legend works with tab and arrow keys. For lead sources, revenue split and survey results with up to six parts.
Waar komen aanvragen vandaan? Kozijnen Bosman, Apeldoorn · jan t/m sep
How to use it
- Paste the HTML where the numbers & charts should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Cirkeldiagram met legenda en hover · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="cdg">
<p class="cdg__t">Waar komen aanvragen vandaan?<span> Kozijnen Bosman, Apeldoorn · jan t/m sep</span></p>
<div class="cdg__main"><svg class="cdg__pie" viewBox="-60 -60 120 120" role="img" aria-label="Cirkeldiagram met de herkomst van 384 aanvragen. De legenda ernaast geeft de aantallen."></svg>
<div class="cdg__side"><ul class="cdg__lg"></ul><p class="cdg__det" aria-live="polite"></p></div></div>
</div>
</div>/* Cirkeldiagram met legenda en hover · NedDev · eigen werk. */
.cdg{position:absolute;inset:0;box-sizing:border-box;padding:12px 14px;background:#fff;color:#0a0a0a;font-family:'Switzer',sans-serif;display:flex;flex-direction:column;gap:6px;container-type:size}
.cdg p{margin:0}
.cdg__t{font-size:13px;font-weight:600;line-height:1.3}
.cdg__t span{display:block;font-size:12px;font-weight:400;color:#5f5e5a}
.cdg__main{flex:1;min-height:0;display:flex;align-items:center;gap:14px}
.cdg__pie{width:min(150px,40cqw,calc(100cqh - 56px));height:auto;aspect-ratio:1;flex:none;overflow:visible}
.cdg__sl{stroke:#fff;stroke-width:1.2;cursor:pointer;transition:transform .25s cubic-bezier(.3,1.3,.5,1),opacity .2s}
.cdg.is-hover .cdg__sl:not(.is-on){opacity:.3}
.cdg__side{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
.cdg__lg{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.cdg__it{width:100%;min-height:24px;display:flex;align-items:center;gap:7px;padding:0 6px;border:0;border-radius:4px;background:none;color:#0a0a0a;font:400 12px 'Switzer',sans-serif;text-align:left;cursor:pointer;transition:background-color .15s,opacity .2s}
.cdg__it:hover,.cdg__it.is-on{background:#f4f3f1}
.cdg__it[aria-pressed="true"]{font-weight:600}
.cdg__it:focus-visible{outline:2px solid #F5480F;outline-offset:0}
.cdg.is-hover .cdg__it:not(.is-on){opacity:.5}
.cdg__sw{width:10px;height:10px;border-radius:2px;flex:none}
.cdg__nm{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cdg__pc{font-weight:600;font-variant-numeric:tabular-nums}
.cdg__det{font-size:12px;color:#3d3c39;padding:0 6px;min-height:16px}
@container (max-width:380px){.cdg__t span{display:none}.cdg__main{gap:10px}}
@media(prefers-reduced-motion:reduce){.cdg__sl,.cdg__it{transition:none}}// Cirkeldiagram met legenda en hover · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.cdg');if(!w)return;var NS='http://www.w3.org/2000/svg';
var D=[['Google zoeken',177,'#F5480F'],['Doorverwijzing',84,'#0a0a0a'],['Werkspot',54,'#8a8883'],['Instagram',38,'#f7a07c'],['Overig',31,'#d6d3ce']];
var tot=D.reduce(function(a,d){return a+d[1];},0),svg=w.querySelector('.cdg__pie'),ul=w.querySelector('.cdg__lg'),det=w.querySelector('.cdg__det'),pin=-1;
function pc(v){return Math.round(v/tot*100);}
var base='Totaal '+tot+' aanvragen';det.textContent=base;
var sl=D.map(function(d){var p=document.createElementNS(NS,'path');p.setAttribute('class','cdg__sl');p.setAttribute('fill',d[2]);svg.appendChild(p);return p;});
ul.innerHTML=D.map(function(d,i){return '<li><button type="button" class="cdg__it" aria-pressed="false" data-i="'+i+'"><i class="cdg__sw" style="background:'+d[2]+'"></i><span class="cdg__nm">'+d[0]+'</span><span class="cdg__pc">'+pc(d[1])+'%</span></button></li>';}).join('');
var its=[].slice.call(ul.querySelectorAll('.cdg__it')),mids=[];
function arc(a0,a1){var r=52,x0=Math.cos(a0)*r,y0=Math.sin(a0)*r,x1=Math.cos(a1)*r,y1=Math.sin(a1)*r;if(a1-a0>=Math.PI*2-1e-4)return 'M0,-52A52,52 0 1 1 0,52A52,52 0 1 1 0,-52Z';return 'M0,0L'+x0.toFixed(2)+','+y0.toFixed(2)+'A'+r+','+r+' 0 '+(a1-a0>Math.PI?1:0)+' 1 '+x1.toFixed(2)+','+y1.toFixed(2)+'Z';}
function draw(f){var a=-Math.PI/2;D.forEach(function(d,i){var s=d[1]/tot*Math.PI*2*f;sl[i].setAttribute('d',s>0?arc(a,a+s):'');mids[i]=a+s/2;a+=s;});}
function hl(k){if(k<0){w.classList.remove('is-hover');sl.forEach(function(p){p.classList.remove('is-on');p.style.transform='';});its.forEach(function(b){b.classList.remove('is-on');});det.textContent=base;return;}
w.classList.add('is-hover');sl.forEach(function(p,i){var on=i===k;p.classList.toggle('is-on',on);p.style.transform=on?'translate('+(Math.cos(mids[i])*5).toFixed(2)+'px,'+(Math.sin(mids[i])*5).toFixed(2)+'px)':'';});its.forEach(function(b,i){b.classList.toggle('is-on',i===k);});det.textContent=D[k][0]+': '+D[k][1]+' aanvragen ('+pc(D[k][1])+'%)';}
function rest(){hl(pin);}
its.forEach(function(b,i){b.addEventListener('pointerenter',function(){hl(i);});b.addEventListener('pointerleave',rest);b.addEventListener('focus',function(){hl(i);});b.addEventListener('blur',rest);
b.addEventListener('click',function(){pin=pin===i?-1:i;its.forEach(function(x,j){x.setAttribute('aria-pressed',j===pin?'true':'false');});hl(pin<0?i:pin);});
b.addEventListener('keydown',function(e){var j=e.key==='ArrowDown'?i+1:e.key==='ArrowUp'?i-1:null;if(j===null)return;e.preventDefault();its[(j+its.length)%its.length].focus();});});
sl.forEach(function(p,i){p.addEventListener('pointerenter',function(){hl(i);});p.addEventListener('pointerleave',rest);p.addEventListener('click',function(){its[i].click();});});
if(matchMedia('(prefers-reduced-motion:reduce)').matches||!('IntersectionObserver' in window)){draw(1);return;}
draw(0.0001);var io=new IntersectionObserver(function(es){if(!es[0].isIntersecting)return;io.disconnect();var t0=performance.now();requestAnimationFrame(function f(t){var q=Math.min(1,(t-t0)/900);draw(1-Math.pow(1-q,3));if(q<1)requestAnimationFrame(f);});},{threshold:.4});io.observe(w);
}
init(document.querySelector('.jouw-container'));
More numbers & charts
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →