]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Polar Area deep data
authorTanner Linsley <tannerlinsley@gmail.com>
Wed, 27 May 2015 04:02:41 +0000 (22:02 -0600)
committerTanner Linsley <tannerlinsley@gmail.com>
Wed, 27 May 2015 04:02:41 +0000 (22:02 -0600)
samples/polar-area.html
src/Chart.Core.js
src/Chart.Doughnut.js
src/Chart.PolarArea.js

index 51682e65b9de88eb9fb366a8aca6e5761166b58b..c52dad5777104c6957dd71ca56ca482763070504 100644 (file)
@@ -1,76 +1,67 @@
 <!doctype html>
 <html>
-       <head>
-               <title>Polar Area Chart</title>
-               <script src="../Chart.js"></script>
-               <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
-       </head>
-       <body>
-               <div id="canvas-holder" style="width:30%">
-                       <canvas id="chart-area" width="300" height="300"/>
-               </div>
-               <button id="randomizeData">Randomize Data</button>
 
+<head>
+    <title>Polar Area Chart</title>
+    <script src="../Chart.js"></script>
+    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+</head>
 
-       <script>
+<body>
+    <div id="canvas-holder" style="width:100%">
+        <canvas id="chart-area" width="300" height="300" />
+    </div>
+    <button id="randomizeData">Randomize Data</button>
+    <script>
+    var randomScalingFactor = function() {
+        return Math.round(Math.random() * 100);
+    };
+    var randomColorFactor = function() {
+        return Math.round(Math.random() * 255);
+    };
 
-               var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
-               var randomColorFactor = function(){ return Math.round(Math.random()*255)};
+    var config = {
+        data: {
+            data: [{
+                value: randomScalingFactor(),
+                backgroundColor: "#F7464A",
+                label: "Red"
+            }, {
+                value: randomScalingFactor(),
+                backgroundColor: "#46BFBD",
+                label: "Green"
+            }, {
+                value: randomScalingFactor(),
+                backgroundColor: "#FDB45C",
+                label: "Yellow"
+            }, {
+                value: randomScalingFactor(),
+                backgroundColor: "#949FB1",
+                label: "Grey"
+            }, {
+                value: randomScalingFactor(),
+                backgroundColor: "#4D5360",
+                label: "Dark Grey"
+            }]
+        },
+        options: {
+            responsive: true
+        }
+    };
 
-               var polarData = [
-                               {
-                                       value: randomScalingFactor(),
-                                       color:"#F7464A",
-                                       highlight: "#FF5A5E",
-                                       label: "Red"
-                               },
-                               {
-                                       value: randomScalingFactor(),
-                                       color: "#46BFBD",
-                                       highlight: "#5AD3D1",
-                                       label: "Green"
-                               },
-                               {
-                                       value: randomScalingFactor(),
-                                       color: "#FDB45C",
-                                       highlight: "#FFC870",
-                                       label: "Yellow"
-                               },
-                               {
-                                       value: randomScalingFactor(),
-                                       color: "#949FB1",
-                                       highlight: "#A8B3C5",
-                                       label: "Grey"
-                               },
-                               {
-                                       value: randomScalingFactor(),
-                                       color: "#4D5360",
-                                       highlight: "#616774",
-                                       label: "Dark Grey"
-                               }
+    window.onload = function() {
+        var ctx = document.getElementById("chart-area").getContext("2d");
+        window.myPolarArea = new Chart(ctx).PolarArea(config);
+    };
 
-                       ];
+    $('#randomizeData').click(function() {
+        $.each(polarData, function(i, piece) {
+            polarData[i].value = randomScalingFactor();
+            polarData[i].color = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
+        });
+        window.myPolarArea.update();
+    });
+    </script>
+</body>
 
-                       window.onload = function(){
-                               var ctx = document.getElementById("chart-area").getContext("2d");
-                               window.myPolarArea = new Chart(ctx).PolarArea({
-                                       data: polarData, 
-                                       options: {
-                                               responsive:true
-                                       }
-                               });
-                       };
-
-                       $('#randomizeData').click(function(){
-                               $.each(polarData, function(i, piece){
-                                       polarData[i].value = randomScalingFactor();
-                               polarData[i].color = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
-                               });
-                       window.myPolarArea.update();
-                   });
-
-
-
-       </script>
-       </body>
 </html>
index 7fc57ac932493f4c4ef315e0b56d81e1aaf63880..9d02389e6ab14002fb922d15167418bc31e34fb8 100755 (executable)
         },
         draw: function() {
 
-            var ctx = this.ctx;
+            var ctx = this._chart.ctx;
             var vm = this._vm;
 
             ctx.beginPath();
index b25f48f47b65a9aa1e64fe2efa1afba705e2a6f3..820217a3d5df059396b5adfca43df694f0dacc02 100644 (file)
@@ -74,7 +74,7 @@
                     innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
                 });
                 if (!metaSlice.backgroundColor) {
-                    slice.backgroundColor = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
+                    slice.backgroundColor = 'hsl(' + (360 * index / this.data.data.length) + ', 100%, 50%)';
                 }
                 metaSlice.save();
                 this.data.metaData.push(metaSlice);
index 49fe2424e16617eb1015b1177c10e2a36a11a0eb..ae8e45d68113161f0f82849ef65777cd90fc2b31 100644 (file)
@@ -1,30 +1,30 @@
-(function(){
-       "use strict";
+(function() {
+    "use strict";
 
-       var root = this,
-               Chart = root.Chart,
-               //Cache a local reference to Chart.helpers
-               helpers = Chart.helpers;
+    var root = this,
+        Chart = root.Chart,
+        //Cache a local reference to Chart.helpers
+        helpers = Chart.helpers;
 
-       var defaultConfig = {
-               //Boolean - Stroke a line around each segment in the chart
-               segmentShowStroke : true,
+    var defaultConfig = {
 
-               //String - The colour of the stroke on each segment.
-               segmentStrokeColor : "#fff",
+        segment: {
+            //String - The colour of the border on each segment.
+            borderColor: "#fff",
 
-               //Number - The width of the stroke value in pixels
-               segmentStrokeWidth : 2,
+            //Number - The width of the border value in pixels
+            borderWidth: 2,
+        },
 
-               scale: {
-                       scaleType: "radialLinear",
-                       display: true,
-                       
-                       //Boolean - Whether to animate scaling the chart from the centre
-                       animate : false,
+        scale: {
+            scaleType: "radialLinear",
+            display: true,
+
+            //Boolean - Whether to animate scaling the chart from the centre
+            animate: false,
+
+            lineArc: true,
 
-                       lineArc: true,
-    
             // grid line settings
             gridLines: {
                 show: true,
                 fontColor: "#666",
                 fontFamily: "Helvetica Neue",
 
-                               //Boolean - Show a backdrop to the scale label
-                               showLabelBackdrop : true,
+                //Boolean - Show a backdrop to the scale label
+                showLabelBackdrop: true,
 
-                               //String - The colour of the label backdrop
-                               backdropColor : "rgba(255,255,255,0.75)",
+                //String - The colour of the label backdrop
+                backdropColor: "rgba(255,255,255,0.75)",
 
-                               //Number - The backdrop padding above & below the label in pixels
-                               backdropPaddingY : 2,
+                //Number - The backdrop padding above & below the label in pixels
+                backdropPaddingY: 2,
 
-                               //Number - The backdrop padding to the side of the label in pixels
-                               backdropPaddingX : 2,
+                //Number - The backdrop padding to the side of the label in pixels
+                backdropPaddingX: 2,
             }
-               },
-
-               //Number - Amount of animation steps
-               animationSteps : 100,
-
-               //String - Animation easing effect.
-               animationEasing : "easeOutBounce",
-
-               //Boolean - Whether to animate the rotation of the chart
-               animateRotate : true,
-
-               //String - A legend template
-               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>"
-       };
-
-
-       Chart.Type.extend({
-               //Passing in a name registers this chart in the Chart namespace
-               name: "PolarArea",
-               //Providing a defaults will also register the deafults in the chart namespace
-               defaults : defaultConfig,
-               //Initialize is fired when the chart is initialized - Data is passed in as a parameter
-               //Config is automatically merged by the core of Chart.js, and is available at this.options
-               initialize:  function(){
-                       this.segments = [];
-                       //Declare segment class as a chart instance specific class, so it can share props for this instance
-                       this.SegmentArc = Chart.Arc.extend({
-                               showStroke : this.options.segmentShowStroke,
-                               strokeWidth : this.options.segmentStrokeWidth,
-                               strokeColor : this.options.segmentStrokeColor,
-                               ctx : this.chart.ctx,
-                               innerRadius : 0,
-                               x : this.chart.width/2,
-                               y : this.chart.height/2
-                       });
-
-                       var self = this;
-                       var ScaleClass = Chart.scales.getScaleConstructor(this.options.scale.scaleType);
-                       this.scale = new ScaleClass({
-                               options: this.options.scale,
-                               lineArc: true,
-                               width: this.chart.width,
-                               height: this.chart.height,
-                               xCenter: this.chart.width/2,
-                               yCenter: this.chart.height/2,
-                               ctx : this.chart.ctx,
-                               valuesCount: this.data.length,
-                               calculateRange: function() {
-                                       this.min = null;
-                                       this.max = null;
-
-                                       helpers.each(self.data, function(data) {
+        },
+
+        //Boolean - Whether to animate the rotation of the chart
+        animateRotate: true,
+
+        //String - A legend template
+        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>"
+    };
+
+
+    Chart.Type.extend({
+        //Passing in a name registers this chart in the Chart namespace
+        name: "PolarArea",
+        //Providing a defaults will also register the deafults in the chart namespace
+        defaults: defaultConfig,
+        //Initialize is fired when the chart is initialized - Data is passed in as a parameter
+        //Config is automatically merged by the core of Chart.js, and is available at this.options
+        initialize: function() {
+
+            // Scale setup
+            var self = this;
+            var ScaleClass = Chart.scales.getScaleConstructor(this.options.scale.scaleType);
+            this.scale = new ScaleClass({
+                options: this.options.scale,
+                lineArc: true,
+                width: this.chart.width,
+                height: this.chart.height,
+                xCenter: this.chart.width / 2,
+                yCenter: this.chart.height / 2,
+                ctx: this.chart.ctx,
+                valuesCount: this.data.length,
+                calculateRange: function() {
+                    this.min = null;
+                    this.max = null;
+
+                    helpers.each(self.data.data, function(data) {
                         if (this.min === null) {
                             this.min = data.value;
                         } else if (data.value < this.min) {
                             this.min = data.value;
                         }
-                        
+
                         if (this.max === null) {
                             this.max = data.value;
                         } else if (data.value > this.max) {
                             this.max = data.value;
                         }
                     }, this);
-                               }
-                       });
-
-                       this.updateScaleRange();
-                       this.scale.calculateRange();
-                       this.scale.generateTicks();
-                       this.scale.buildYLabels();
-
-                       helpers.each(this.data,function(segment,index){
-                               this.addData(segment,index,true);
-                       },this);
-
-                       //Set up tooltip events on the chart
-                       if (this.options.showTooltips){
-                               helpers.bindEvents(this, this.options.events, function(evt){
-                                       var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
-                                       helpers.each(this.segments,function(segment){
-                                               segment.restore(["fillColor"]);
-                                       });
-
-                                       helpers.each(activeSegments,function(activeSegment){
-                                               activeSegment.fillColor = activeSegment.highlightColor;
-                                       });
-
-                                       this.showTooltip(activeSegments);
-                               });
-                       }
-
-                       this.render();
-               },
-               getSegmentsAtEvent : function(e){
-                       var segmentsArray = [];
-                       var location = helpers.getRelativePosition(e);
-
-                       helpers.each(this.segments,function(segment){
-                               if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
-                       },this);
-
-                       return segmentsArray;
-               },
-               addData : function(segment, atIndex, silent){
-                       var index = atIndex || this.segments.length;
-
-                       this.segments.splice(index, 0, new this.SegmentArc({
-                               fillColor: segment.color,
-                               highlightColor: segment.highlight || segment.color,
-                               label: segment.label,
-                               value: segment.value,
-                               outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
-                               circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
-                               startAngle: Math.PI * 1.5
-                       }));
-                       if (!silent){
-                               this.reflow();
-                               this.update();
-                       }
-               },
-               removeData: function(atIndex){
-                       var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
-                       this.segments.splice(indexToDelete, 1);
-                       this.reflow();
-                       this.update();
-               },
-               calculateTotal: function(data){
-                       this.total = 0;
-                       helpers.each(data,function(segment){
-                               this.total += segment.value;
-                       },this);
-                       this.scale.valuesCount = this.segments.length;
-               },
-               updateScaleRange: function(){
-                       helpers.extend(this.scale, {
-                               size: helpers.min([this.chart.width, this.chart.height]),
-                               xCenter: this.chart.width/2,
-                               yCenter: this.chart.height/2
-                       });
-
-               },
-               update : function(){
-
-                       // Map new data to data points
-                       if(this.data.length == this.segments.length){
-                               helpers.each(this.data, function(segment, i){
-                                       helpers.extend(this.segments[i], {
-                                               fillColor: segment.color,
-                                               highlightColor: segment.highlight || segment.color,
-                                               label: segment.label,
-                                               value: segment.value,
-                                       });
-                               },this);
-                       } else{
-                               // Data size changed without properly inserting, just redraw the chart
-                               this.initialize(this.data);
-                       }
-
-                       this.calculateTotal(this.segments);
-
-                       helpers.each(this.segments,function(segment){
-                               segment.save();
-                       });
-                       
-                       this.reflow();
-                       this.render();
-               },
-               reflow : function(){
-                       helpers.extend(this.SegmentArc.prototype,{
-                               x : this.chart.width/2,
-                               y : this.chart.height/2
-                       });
-                       
-                       this.updateScaleRange();
-                       this.scale.calculateRange();
-                       this.scale.generateTicks();
-                       this.scale.buildYLabels();
-
-                       helpers.extend(this.scale,{
-                               xCenter: this.chart.width/2,
-                               yCenter: this.chart.height/2
-                       });
-
-                       helpers.each(this.segments, function(segment){
-                               //segment.update({
-                               //      outerRadius : this.scale.calculateCenterOffset(segment.value)
-                               //});
-                               helpers.extend(segment, {
-                                       outerRadius: this.scale.calculateCenterOffset(segment.value)
-                               });
-                       }, this);
-
-               },
-               draw : function(ease){
-                       var easingDecimal = ease || 1;
-                       //Clear & draw the canvas
-                       this.clear();
-                       helpers.each(this.segments,function(segment, index){
-                               segment.transition({
-                                       circumference : this.scale.getCircumference(),
-                                       outerRadius : this.scale.calculateCenterOffset(segment.value)
-                               },easingDecimal);
-
-                               segment.endAngle = segment.startAngle + segment.circumference;
-
-                               // If we've removed the first segment we need to set the first one to
-                               // start at the top.
-                               if (index === 0){
-                                       segment.startAngle = Math.PI * 1.5;
-                               }
-
-                               //Check to see if it's the last segment, if not get the next and update the start angle
-                               if (index < this.segments.length - 1){
-                                       this.segments[index+1].startAngle = segment.endAngle;
-                               }
-                               segment.draw();
-                       }, this);
-                       this.scale.draw();
-               }
-       });
+                }
+            });
+
+            //Declare segment class as a chart instance specific class, so it can share props for this instance
+            this.Slice = Chart.Arc.extend();
+
+            //Set up tooltip events on the chart
+            if (this.options.showTooltips) {
+                helpers.bindEvents(this, this.options.events, this.onHover);
+            }
+
+            // Create new slice for each piece of data
+            this.data.metaData = [];
+            helpers.each(this.data.data, function(slice, index) {
+                var metaSlice = new this.Slice({
+                    _chart: this.chart,
+                    innerRadius: 0,
+                    startAngle: Math.PI * 1.5,
+                    endAngle: Math.PI * 1.5,
+                    x: this.chart.width / 2,
+                    y: this.chart.height / 2
+                });
+                if (typeof slice == 'number') {
+                    helpers.extend(metaSlice, {
+                        value: slice
+                    });
+                } else {
+                    helpers.extend(metaSlice, slice);
+                }
+                if (!metaSlice.backgroundColor) {
+                    slice.backgroundColor = 'hsl(' + (360 * index / this.data.data.length) + ', 100%, 50%)';
+                }
+                metaSlice.save();
+                this.data.metaData.push(metaSlice);
+            }, this);
+
+
+            // Create tooltip instance exclusively for this chart with some defaults.
+            this.tooltip = new Chart.Tooltip({
+                _chart: this.chart,
+                _data: this.data,
+                _options: this.options,
+            }, this);
+
+            this.update();
+
+        },
+        updateScaleRange: function() {
+            helpers.extend(this.scale, {
+                size: helpers.min([this.chart.width, this.chart.height]),
+                xCenter: this.chart.width / 2,
+                yCenter: this.chart.height / 2
+            });
+        },
+        update: function() {
+
+            this.updateScaleRange();
+            this.scale.calculateRange();
+            this.scale.generateTicks();
+            this.scale.buildYLabels();
+
+            this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.segment.borderWidth / 2) / 2;
+
+            var circumference = 1 / this.data.data.length * 2;
+
+            // Map new data to data points
+            helpers.each(this.data.metaData, function(slice, index) {
+
+                var datapoint = this.data.data[index];
+
+                var startAngle = Math.PI * 1.5 + (Math.PI * circumference) * index;
+                var endAngle = startAngle + (circumference * Math.PI);
+
+                helpers.extend(slice, {
+                    _index: index,
+                    x: this.chart.width / 2,
+                    y: this.chart.height / 2,
+                    value: datapoint.value,
+                    label: datapoint.label,
+                    innerRadius: 0,
+                    outerRadius: this.scale.calculateCenterOffset(slice.value),
+                    startAngle: startAngle,
+                    endAngle: endAngle,
+
+                    backgroundColor: datapoint.backgroundColor,
+                    hoverBackgroundColor: datapoint.hoverBackgroundColor || datapoint.backgroundColor,
+                    borderWidth: this.options.borderWidth,
+                    borderColor: this.options.segmentStrokeColor,
+                });
+                slice.pivot();
+
+            }, this);
+
+            this.render();
+        },
+        draw: function(ease) {
+            var easingDecimal = ease || 1;
+
+            this.clear();
+
+            helpers.each(this.data.metaData, function(segment, index) {
+                segment.transition(easingDecimal).draw();
+            }, this);
+
+            this.scale.draw();
+        }
+    });
 
 }).call(this);