/* Information used: /* Google.bg: /* free pie chart svg javascript /* - http://www.jqueryscript.net/tags.php?/pie%20chart/ /* /* Google.bg: /* svg draw pie /* http://www.smashingmagazine.com/2015/07/designing-simple-pie-charts-with-css/ /* /* Google.bg: /* html5 canvas interactivity /* - http://simonsarris.com/blog/510-making-html5-canvas-useful /* /* About labels in a pie chart: /* http://www.scriptol.com/html5/canvas/circle.php /* -------------------------------------------------------------------------------------- */ /* Class definition /* ----------------- */ var ChartPie = function( container, options, callback ) { this.$container = $( container ); this.$canvas = $( container ).find( 'canvas' ); this.context = this.$canvas[ 0 ].getContext( '2d' ); this.options = $.extend( {}, options || {} ); this.callback = callback || null; this._values = this.$container.data( 'values' ); this._labels = this.$container.data( 'labels' ); this._colors = this.$container.data( 'colors' ); this.init(); }; /* Object structure definition /* ---------------------------- */ ChartPie.prototype = { constructor: ChartPie, init: function() { // Basic calculation this.options.width = this.$container.parent().width(); this.options.height = this.options.height || 400; this.options.diameter = Math.min( this.options.width, this.options.height ); this.options.radius = this.options.diameter / 3; this.options.rationAngle = 360 / this.arrayToSum( this._values ); this.options.initAngle = 1.5 * Math.PI; // Prepare container this.$container.css({ position: "relative", width: this.options.diameter, height: this.options.diameter, borderRadius: this.options.diameter / 2 }) .find( ".pie-canvas-legend" ).remove(); // Prepare canvas this.$canvas.attr({ width: this.options.diameter, height: this.options.diameter }); // Clear canvas this.context.clearRect( 0, 0, this.options.diameter, this.options.diameter ); for ( var i in this._values ) { this.drawSegment( i ); } if ( typeof this.callback === 'function' ) { var _this = this; var _event = !! ( 'ontouchstart' in window ) ? 'touchstart' : 'mousemove'; this.$container .off( _event ) .on( _event, function( event ) { event.preventDefault(); var e = event; if ( event.originalEvent.touches ) { e = event.originalEvent.touches[ 0 ] || event.originalEvent.changedTouches[ 0 ]; } var x = e.pageX - $( this ).offset().left; var y = e.pageY - $( this ).offset().top; var p = _this.getCanvasData( x, y ); for ( var i in _this._colors ) { if ( _this.hexToRgb( _this._colors[ i ] ) === p ) { _this.callback({ value: _this._values[ i ], label: _this._labels[ i ] || '', color: _this._colors[ i ] }); } } }); } }, drawSegment: function( index ) { var cX = Math.floor( this.options.diameter / 2 ); var cY = Math.floor( this.options.diameter / 2 ); var cR = this.options.radius; var cIA = this.options.initAngle; var angle = this.degreesToRadians( this._values[ index ] * this.options.rationAngle ); this.context.save(); this.context.beginPath(); this.context.moveTo( cX, cY ); this.context.arc( cX, cY, cR, cIA, cIA + angle, false ); this.context.closePath(); this.context.fillStyle = this._colors[ index ]; this.context.fill(); this.context.restore(); this.context.save(); this.context.beginPath(); this.context.arc( cX, cY, cR, cIA, cIA + angle, false ); this.context.lineWidth = 2; this.context.strokeStyle = this._colors[ index ]; this.context.shadowColor = 'black'; this.context.shadowBlur = 10; this.context.shadowOffsetX = 0; this.context.shadowOffsetY = 0; this.context.stroke(); this.context.restore(); var labelSector = cIA + angle / 2; var dx = cX + ( cR * 3 / 4 ) * Math.cos( labelSector ); var dy = cY + ( cR * 3 / 4 ) * Math.sin( labelSector ); // this.context.save(); // this.context.textAlign = 'center'; // this.context.font = "10pt Arial"; // this.context.fillStyle = 'white'; // this.context.fillText( this._values[ index ] + '%', dx, dy ); // this.context.restore(); // ! Update this.options.initAngle += angle; }, getCanvasData: function( x, y ) { var p = this.context.getImageData( x, y, 1, 1 ); if ( p.data[ 3 ] > 0 ) { return p.data[ 0 ] + ',' + p.data[ 1 ] + ',' + p.data[ 2 ]; } return null; }, degreesToRadians: function( degrees ) { return ( degrees * Math.PI ) / 180; }, arrayToSum: function( array ) { var sum = 0; for ( var i in array ) { sum += array[ i ]; } return sum; }, hexToRgb: function( hex ) { if ( hex.substring( 0, 1 ) == '#' ) { hex = hex.replace( '#', '' ); } var bigint = parseInt( hex, 16 ); var r = ( bigint >> 16 ) & 255; var g = ( bigint >> 8 ) & 255; var b = bigint & 255; return r + "," + g + "," + b; } };