You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

d3pie.min.js 7.1KB

12345
  1. /*!
  2. * rspamd-D3Pie 1.1.0 (https://github.com/moisseev/rspamd-D3Pie)
  3. * Copyright (c) 2022, Alexander Moisseev, BSD 2-Clause
  4. */
  5. function D3Pie(v,t){"use strict";const A=$.extend(!0,{canvasPadding:5,cornerRadius:3,duration:1250,gradient:{enabled:!0,percentage:100},labels:{inner:{hideWhenLessThanPercentage:4,offset:.15},outer:{collideHeight:13,format:"label",pieDistance:30}},padAngle:.01,pieCenterOffset:{x:0,y:0},size:{canvasHeight:400,canvasWidth:600,pieInnerRadius:"20%",pieOuterRadius:"85%"},title:"",total:{enabled:!1}},t),e=(this.destroy=function(){d3.selectAll("#"+v+" svg, #"+v+"-tooltip").remove()},this.destroy(),d3.select("#"+v).append("svg").attr("class","d3pie").attr("width",A.size.canvasWidth).attr("height",A.size.canvasHeight));let l=0;if(""!==A.title){const a=e.append("svg:text").attr("class","chart-title").attr("x",A.size.canvasWidth/2);a.append("tspan").text(A.title+" "),l=a.node().getBBox().height,a.attr("y",l+A.canvasPadding)}const x=e.append("g").attr("transform","translate("+(A.size.canvasWidth/2+A.pieCenterOffset.x)+","+(A.size.canvasHeight/2+l/2+A.pieCenterOffset.y)+")"),y={},m={},{outerRadius:M,innerRadius:R}=function(){function t(t,e){var a;return/%/u.test(t)?(a=Math.max(0,Math.min(99,parseInt(t.replace(/[\D]/u,""),10)))/100,Math.floor(e*a)):parseInt(t,10)}var e=A.size.canvasWidth-2*A.canvasPadding,a=A.size.canvasHeight-2*A.canvasPadding-l;let n=Math.min(e,a)/2;"none"!==A.labels.outer.format&&(e=parseInt(A.labels.outer.pieDistance,10),n>e&&(n-=e));a=t(A.size.pieOuterRadius,n);return{outerRadius:a,innerRadius:t(A.size.pieInnerRadius,a)}}(),w=M+A.labels.outer.pieDistance,z=d3.line().curve(d3.curveCatmullRomOpen),P=d3.select("body").append("div").attr("id",v+"-tooltip").attr("class","d3pie-tooltip"),r=P.append("span").attr("id",v+"-tooltip-text");function I(t){t.on("mouseover",function(t,e){var a=P.datum().total,n=a?Math.round(100*e.data.value/a):NaN;e.data.value?(P.transition().duration(300).style("opacity",1),r.text(e.data.label+(a?": "+e.data.value+" ("+n+"%)":""))):P.transition().duration(300).style("opacity",0),P.each(function(t){t.height=this.getBoundingClientRect().height})}).on("mouseout",function(){P.transition().duration(300).style("opacity",0)}).on("mousemove",t=>{const{pageX:e,pageY:a}=t;P.style("left",e+"px").style("top",function(t){return a-t.height-2+"px"})})}const H=x.append("g");if(I(H),H.append("circle").attr("r",R).style("opacity",0),A.total.enabled){const n=H.append("text").attr("class","total-text");n.append("tspan").attr("class","total-value").style("font-size",.6*R+"px"),n.append("tspan").attr("x","0").attr("dy",.5*R).text(void 0!==A.total.label?A.total.label:"Total")}const O=e.append("defs");this.data=function(t){let l=$.extend(!0,[],t);const d=[],e=l.reduce(function(t,e){return t+(e.value||0)},0),a=(P.datum({total:e}),H.datum({data:{label:void 0!==A.total.label?A.total.label:"Total",value:e}}),A.total.enabled&&H.select(".total-value").text(d3.format(".3~s")(e)),l.unshift({label:"undefined",color:A.gradient.enabled?"steelblue":"#ecf1f5",value:0===e?1:0}),d3.scaleOrdinal(d3.schemeSet1));function n(t,e){return void 0!==t&&void 0!==t.color?t.color:a(e)}function s(t,e,a=e){return d3.arc().innerRadius(e).outerRadius(a).centroid(t)}function c(t){return d3.interpolate(y[t.data.label],t)}function u(t){var e=w-.1;return Math.max(-e,Math.min(e,t))}function r(r,i){m[r.data.label].newAngle=function(){var t=u(d[i].y);let e=Math.sqrt(Math.pow(w,2)-Math.pow(t,2)),a=((r.endAngle+r.startAngle)/2>Math.PI&&(e*=-1),Math.PI/2-Math.atan2(-t,e));return a<0&&(a+=2*Math.PI),{startAngle:a,endAngle:a}}();const o=d3.interpolate(m[r.data.label].currentAngle,m[r.data.label].newAngle);return function(t){var e=s(o(t),w),[a,n]=e,l=0<a?{dx:5,textAnchor:"start"}:{dx:-5,textAnchor:"end"};return d3.select(x.selectAll(".link").nodes()[i]).datum([s(c(r)(t),M),s(c(r)(t),M+5),[a,n],[a+l.dx,n]]).attr("d",z),d3.select(x.selectAll(".outer-label").nodes()[i]).attr("dx",l.dx).style("text-anchor",l.textAnchor),"translate("+e+")"}}t=d3.transition().duration(A.duration);if(A.gradient.enabled){const g=O.selectAll("radialGradient").data(l,function(t){return t.label}),h=g.enter().append("radialGradient").attr("gradientUnits","userSpaceOnUse").attr("cx",0).attr("cy",0).attr("r","120%").attr("id",function(t,e){return v+"-grad"+e});h.append("stop").attr("class","grad-stop-0").style("stop-color",n),h.append("stop").attr("class","grad-stop-1").attr("offset",A.gradient.percentage+"%"),O.selectAll("radialGradient").select(".grad-stop-0").transition(t).style("stop-color",n)}function i(t){return t.data.label}const o=d3.pie().sort(null).value(function(t){return t.value}),p=x.selectAll(".slice-g").data(o(l),i),f=p.enter().append("g").attr("class","slice-g");if(I(f),f.append("path").attr("id",function(t,e){return v+"-slice"+e}).attr("class","slice").attr("fill",function(t,e){return A.gradient.enabled?"url(#"+v+"-grad"+e+")":n(t.data,e)}),p.exit().each(function(t,e){l[e]={value:0,label:t.data.label}}),o(l).forEach(function(t,e){void 0===y[t.data.label]&&(e=e?y[o(l)[e-1].data.label].endAngle:0,y[t.data.label]={startAngle:e,endAngle:e})}),x.selectAll(".slice").data(o(l),i).transition(t).attrTween("d",function(e){return function(t){return d3.arc().padAngle(A.padAngle).cornerRadius(A.cornerRadius).innerRadius(R).outerRadius(M)(c(e)(t))}}).end().then(function(){l=l.filter(function(t,e){return 0===e||t.value}),O.selectAll("radialGradient").data(l,function(t){return t.label}).exit().remove(),x.selectAll(".slice-g").data(o(l),i).exit().each(function(t){delete y[t.data.label],delete m[t.data.label]}).remove();for(const t of o(l))y[t.data.label]=t,"none"!==A.labels.outer.format&&(m[t.data.label].currentAngle=m[t.data.label].newAngle)}).catch(function(t){console.warn(t)}),f.append("text").attr("class","inner-label").attr("dy",".35em"),x.selectAll(".inner-label").data(o(l),i).text(function(t){return"undefined"===t.data.label?"undefined":Math.round(100*t.data.value/e)+"%"}).transition(t).attrTween("opacity",function(e){return e.data.value?function(t){t=c(e)(t);return 100*(t.endAngle-t.startAngle)/(2*Math.PI)<A.labels.inner.hideWhenLessThanPercentage?0:1}:function(){return 0}}).attrTween("transform",function(e){return function(t){return"translate("+s(c(e)(t),R*(1-A.labels.inner.offset),M*(1+A.labels.inner.offset))+")"}}),"none"!==A.labels.outer.format){o(l).forEach(function(t,e){void 0===m[t.data.label]&&(e=e?y[o(l)[e-1].data.label].endAngle:0,m[t.data.label]={currentAngle:{startAngle:e,endAngle:e},newAngle:{startAngle:e,endAngle:e}});let a=0;var[e,n]=s(t,w);t.data.value&&(a=0<=e?A.labels.outer.collideHeight:-A.labels.outer.collideHeight),d.push({fx:a,y:n})}),d3.forceSimulation(d).alphaMin(.5).force("collide",d3.forceCollide(A.labels.outer.collideHeight/2)).force("boundY",function(){for(const t of d)t.y=u(t.y)}).tick(30);const b=f.append("g").attr("class","outer-label-g");b.append("text").attr("class","outer-label").attr("dy",".35em").text(i),b.append("path").attr("class","link"),x.selectAll(".outer-label-g").data(o(l),i).transition(t).style("opacity",function(t,e){return e&&t.value?1:0}).each(function(t,e){$(this).children(".link").attr("stroke",n(t.data,e))}),x.selectAll(".outer-label").data(o(l),i).transition(t).attrTween("transform",r)}}}