JAVASCRIPT   23

Chart.Doughnut.js

Guest on 5th June 2021 05:36:20 PM

  1. (function(){
  2.       "use strict";
  3.  
  4.       var root = this,
  5.             Chart = root.Chart,
  6.             //Cache a local reference to Chart.helpers
  7.             helpers = Chart.helpers;
  8.  
  9.       var defaultConfig = {
  10.             //Boolean - Whether we should show a stroke on each segment
  11.             segmentShowStroke : true,
  12.  
  13.             //String - The colour of each segment stroke
  14.             segmentStrokeColor : "#fff",
  15.  
  16.             //Number - The width of each segment stroke
  17.             segmentStrokeWidth : 2,
  18.  
  19.             //The percentage of the chart that we cut out of the middle.
  20.             percentageInnerCutout : 50,
  21.  
  22.             //Number - Amount of animation steps
  23.             animationSteps : 100,
  24.  
  25.             //String - Animation easing effect
  26.             animationEasing : "easeOutBounce",
  27.  
  28.             //Boolean - Whether we animate the rotation of the Doughnut
  29.             animateRotate : true,
  30.  
  31.             //Boolean - Whether we animate scaling the Doughnut from the centre
  32.             animateScale : false,
  33.  
  34.             //String - A legend template
  35.             legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
  36.  
  37.       };
  38.  
  39.  
  40.       Chart.Type.extend({
  41.             //Passing in a name registers this chart in the Chart namespace
  42.             name: "Doughnut",
  43.             //Providing a defaults will also register the deafults in the chart namespace
  44.             defaults : defaultConfig,
  45.             //Initialize is fired when the chart is initialized - Data is passed in as a parameter
  46.             //Config is automatically merged by the core of Chart.js, and is available at this.options
  47.             initialize:  function(data){
  48.  
  49.                   //Declare segments as a static property to prevent inheriting across the Chart type prototype
  50.                   this.segments = [];
  51.                   this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
  52.  
  53.                   this.SegmentArc = Chart.Arc.extend({
  54.                         ctx : this.chart.ctx,
  55.                         x : this.chart.width/2,
  56.                         y : this.chart.height/2
  57.                   });
  58.  
  59.                   //Set up tooltip events on the chart
  60.                   if (this.options.showTooltips){
  61.                         helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
  62.                               var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
  63.  
  64.                               helpers.each(this.segments,function(segment){
  65.                                     segment.restore(["fillColor"]);
  66.                               });
  67.                               helpers.each(activeSegments,function(activeSegment){
  68.                                     activeSegment.fillColor = activeSegment.highlightColor;
  69.                               });
  70.                               this.showTooltip(activeSegments);
  71.                         });
  72.                   }
  73.                   this.calculateTotal(data);
  74.  
  75.                   helpers.each(data,function(datapoint, index){
  76.                         this.addData(datapoint, index, true);
  77.                   },this);
  78.  
  79.                   this.render();
  80.             },
  81.             getSegmentsAtEvent : function(e){
  82.                   var segmentsArray = [];
  83.  
  84.                   var location = helpers.getRelativePosition(e);
  85.  
  86.                   helpers.each(this.segments,function(segment){
  87.                         if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
  88.                   },this);
  89.                   return segmentsArray;
  90.             },
  91.             addData : function(segment, atIndex, silent){
  92.                   var index = atIndex || this.segments.length;
  93.                   this.segments.splice(index, 0, new this.SegmentArc({
  94.                         value : segment.value,
  95.                         outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
  96.                         innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
  97.                         fillColor : segment.color,
  98.                         highlightColor : segment.highlight || segment.color,
  99.                         showStroke : this.options.segmentShowStroke,
  100.                         strokeWidth : this.options.segmentStrokeWidth,
  101.                         strokeColor : this.options.segmentStrokeColor,
  102.                         startAngle : Math.PI * 1.5,
  103.                         circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
  104.                         label : segment.label
  105.                   }));
  106.                   if (!silent){
  107.                         this.reflow();
  108.                         this.update();
  109.                   }
  110.             },
  111.             calculateCircumference : function(value){
  112.                   return (Math.PI*2)*(Math.abs(value) / this.total);
  113.             },
  114.             calculateTotal : function(data){
  115.                   this.total = 0;
  116.                   helpers.each(data,function(segment){
  117.                         this.total += Math.abs(segment.value);
  118.                   },this);
  119.             },
  120.             update : function(){
  121.                   this.calculateTotal(this.segments);
  122.  
  123.                   // Reset any highlight colours before updating.
  124.                   helpers.each(this.activeElements, function(activeElement){
  125.                         activeElement.restore(['fillColor']);
  126.                   });
  127.  
  128.                   helpers.each(this.segments,function(segment){
  129.                         segment.save();
  130.                   });
  131.                   this.render();
  132.             },
  133.  
  134.             removeData: function(atIndex){
  135.                   var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
  136.                   this.segments.splice(indexToDelete, 1);
  137.                   this.reflow();
  138.                   this.update();
  139.             },
  140.  
  141.             reflow : function(){
  142.                   helpers.extend(this.SegmentArc.prototype,{
  143.                         x : this.chart.width/2,
  144.                         y : this.chart.height/2
  145.                   });
  146.                   this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
  147.                   helpers.each(this.segments, function(segment){
  148.                         segment.update({
  149.                               outerRadius : this.outerRadius,
  150.                               innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
  151.                         });
  152.                   }, this);
  153.             },
  154.             draw : function(easeDecimal){
  155.                   var animDecimal = (easeDecimal) ? easeDecimal : 1;
  156.                   this.clear();
  157.                   helpers.each(this.segments,function(segment,index){
  158.                         segment.transition({
  159.                               circumference : this.calculateCircumference(segment.value),
  160.                               outerRadius : this.outerRadius,
  161.                               innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
  162.                         },animDecimal);
  163.  
  164.                         segment.endAngle = segment.startAngle + segment.circumference;
  165.  
  166.                         segment.draw();
  167.                         if (index === 0){
  168.                               segment.startAngle = Math.PI * 1.5;
  169.                         }
  170.                         //Check to see if it's the last segment, if not get the next and update the start angle
  171.                         if (index < this.segments.length-1){
  172.                               this.segments[index+1].startAngle = segment.endAngle;
  173.                         }
  174.                   },this);
  175.  
  176.             }
  177.       });
  178.  
  179.       Chart.types.Doughnut.extend({
  180.             name : "Pie",
  181.             defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
  182.       });
  183.  
  184. }).call(this);

Raw Paste


Login or Register to edit or fork this paste. It's free.