| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | 
							- /**
 
-  * @license 
 
-  * Highcharts funnel module, Beta
 
-  *
 
-  * (c) 2010-2012 Torstein Hønsi
 
-  *
 
-  * License: www.highcharts.com/license
 
-  */
 
- /*global Highcharts */
 
- (function (Highcharts) {
 
- 	
 
- 'use strict';
 
- // create shortcuts
 
- var defaultOptions = Highcharts.getOptions(),
 
- 	defaultPlotOptions = defaultOptions.plotOptions,
 
- 	seriesTypes = Highcharts.seriesTypes,
 
- 	merge = Highcharts.merge,
 
- 	noop = function () {},
 
- 	each = Highcharts.each;
 
- // set default options
 
- defaultPlotOptions.funnel = merge(defaultPlotOptions.pie, {
 
- 	center: ['50%', '50%'],
 
- 	width: '90%',
 
- 	neckWidth: '30%',
 
- 	height: '100%',
 
- 	neckHeight: '25%',
 
- 	dataLabels: {
 
- 		//position: 'right',
 
- 		connectorWidth: 1,
 
- 		connectorColor: '#606060'
 
- 	},
 
- 	size: true, // to avoid adapting to data label size in Pie.drawDataLabels
 
- 	states: {
 
- 		select: {
 
- 			color: '#C0C0C0',
 
- 			borderColor: '#000000',
 
- 			shadow: false
 
- 		}
 
- 	}	
 
- });
 
- seriesTypes.funnel = Highcharts.extendClass(seriesTypes.pie, {
 
- 	
 
- 	type: 'funnel',
 
- 	animate: noop,
 
- 	/**
 
- 	 * Overrides the pie translate method
 
- 	 */
 
- 	translate: function () {
 
- 		
 
- 		var 
 
- 			// Get positions - either an integer or a percentage string must be given
 
- 			getLength = function (length, relativeTo) {
 
- 				return (/%$/).test(length) ?
 
- 					relativeTo * parseInt(length, 10) / 100 :
 
- 					parseInt(length, 10);
 
- 			},
 
- 			
 
- 			sum = 0,
 
- 			series = this,
 
- 			chart = series.chart,
 
- 			plotWidth = chart.plotWidth,
 
- 			plotHeight = chart.plotHeight,
 
- 			cumulative = 0, // start at top
 
- 			options = series.options,
 
- 			center = options.center,
 
- 			centerX = getLength(center[0], plotWidth),
 
- 			centerY = getLength(center[0], plotHeight),
 
- 			width = getLength(options.width, plotWidth),
 
- 			tempWidth,
 
- 			getWidthAt,
 
- 			height = getLength(options.height, plotHeight),
 
- 			neckWidth = getLength(options.neckWidth, plotWidth),
 
- 			neckHeight = getLength(options.neckHeight, plotHeight),
 
- 			neckY = height - neckHeight,
 
- 			data = series.data,
 
- 			path,
 
- 			fraction,
 
- 			half = options.dataLabels.position === 'left' ? 1 : 0,
 
- 			x1, 
 
- 			y1, 
 
- 			x2, 
 
- 			x3, 
 
- 			y3, 
 
- 			x4, 
 
- 			y5;
 
- 		// Return the width at a specific y coordinate
 
- 		series.getWidthAt = getWidthAt = function (y) {
 
- 			return y > height - neckHeight || height === neckHeight ?
 
- 				neckWidth :
 
- 				neckWidth + (width - neckWidth) * ((height - neckHeight - y) / (height - neckHeight));
 
- 		};
 
- 		series.getX = function (y, half) {
 
- 			return centerX + (half ? -1 : 1) * ((getWidthAt(y) / 2) + options.dataLabels.distance);
 
- 		};
 
- 		// Expose
 
- 		series.center = [centerX, centerY, height];
 
- 		series.centerX = centerX;
 
- 		/*
 
- 		 * Individual point coordinate naming:
 
- 		 *
 
- 		 * x1,y1 _________________ x2,y1
 
- 		 *  \                         /
 
- 		 *   \                       /
 
- 		 *    \                     /
 
- 		 *     \                   /
 
- 		 *      \                 /
 
- 		 *     x3,y3 _________ x4,y3
 
- 		 *
 
- 		 * Additional for the base of the neck:
 
- 		 *
 
- 		 *       |               |
 
- 		 *       |               |
 
- 		 *       |               |
 
- 		 *     x3,y5 _________ x4,y5
 
- 		 */
 
- 		// get the total sum
 
- 		each(data, function (point) {
 
- 			sum += point.y;
 
- 		});
 
- 		each(data, function (point) {
 
- 			// set start and end positions
 
- 			y5 = null;
 
- 			fraction = sum ? point.y / sum : 0;
 
- 			y1 = centerY - height / 2 + cumulative * height;
 
- 			y3 = y1 + fraction * height;
 
- 			//tempWidth = neckWidth + (width - neckWidth) * ((height - neckHeight - y1) / (height - neckHeight));
 
- 			tempWidth = getWidthAt(y1);
 
- 			x1 = centerX - tempWidth / 2;
 
- 			x2 = x1 + tempWidth;
 
- 			tempWidth = getWidthAt(y3);
 
- 			x3 = centerX - tempWidth / 2;
 
- 			x4 = x3 + tempWidth;
 
- 			// the entire point is within the neck
 
- 			if (y1 > neckY) {
 
- 				x1 = x3 = centerX - neckWidth / 2;
 
- 				x2 = x4 = centerX + neckWidth / 2;
 
- 			
 
- 			// the base of the neck
 
- 			} else if (y3 > neckY) {
 
- 				y5 = y3;
 
- 				tempWidth = getWidthAt(neckY);
 
- 				x3 = centerX - tempWidth / 2;
 
- 				x4 = x3 + tempWidth;
 
- 				y3 = neckY;
 
- 			}
 
- 			// save the path
 
- 			path = [
 
- 				'M',
 
- 				x1, y1,
 
- 				'L',
 
- 				x2, y1,
 
- 				x4, y3
 
- 			];
 
- 			if (y5) {
 
- 				path.push(x4, y5, x3, y5);
 
- 			}
 
- 			path.push(x3, y3, 'Z');
 
- 			// prepare for using shared dr
 
- 			point.shapeType = 'path';
 
- 			point.shapeArgs = { d: path };
 
- 			// for tooltips and data labels
 
- 			point.percentage = fraction * 100;
 
- 			point.plotX = centerX;
 
- 			point.plotY = (y1 + (y5 || y3)) / 2;
 
- 			// Placement of tooltips and data labels
 
- 			point.tooltipPos = [
 
- 				centerX,
 
- 				point.plotY
 
- 			];
 
- 			// Slice is a noop on funnel points
 
- 			point.slice = noop;
 
- 			
 
- 			// Mimicking pie data label placement logic
 
- 			point.half = half;
 
- 			cumulative += fraction;
 
- 		});
 
- 		series.setTooltipPoints();
 
- 	},
 
- 	/**
 
- 	 * Draw a single point (wedge)
 
- 	 * @param {Object} point The point object
 
- 	 * @param {Object} color The color of the point
 
- 	 * @param {Number} brightness The brightness relative to the color
 
- 	 */
 
- 	drawPoints: function () {
 
- 		var series = this,
 
- 			options = series.options,
 
- 			chart = series.chart,
 
- 			renderer = chart.renderer;
 
- 		each(series.data, function (point) {
 
- 			
 
- 			var graphic = point.graphic,
 
- 				shapeArgs = point.shapeArgs;
 
- 			if (!graphic) { // Create the shapes
 
- 				point.graphic = renderer.path(shapeArgs).
 
- 					attr({
 
- 						fill: point.color,
 
- 						stroke: options.borderColor,
 
- 						'stroke-width': options.borderWidth
 
- 					}).
 
- 					add(series.group);
 
- 					
 
- 			} else { // Update the shapes
 
- 				graphic.animate(shapeArgs);
 
- 			}
 
- 		});
 
- 	},
 
- 	/**
 
- 	 * Funnel items don't have angles (#2289)
 
- 	 */
 
- 	sortByAngle: noop,
 
- 	
 
- 	/**
 
- 	 * Extend the pie data label method
 
- 	 */
 
- 	drawDataLabels: function () {
 
- 		var data = this.data,
 
- 			labelDistance = this.options.dataLabels.distance,
 
- 			leftSide,
 
- 			sign,
 
- 			point,
 
- 			i = data.length,
 
- 			x,
 
- 			y;
 
- 		
 
- 		// In the original pie label anticollision logic, the slots are distributed
 
- 		// from one labelDistance above to one labelDistance below the pie. In funnels
 
- 		// we don't want this.
 
- 		this.center[2] -= 2 * labelDistance;
 
- 		
 
- 		// Set the label position array for each point.
 
- 		while (i--) {
 
- 			point = data[i];
 
- 			leftSide = point.half;
 
- 			sign = leftSide ? 1 : -1;
 
- 			y = point.plotY;
 
- 			x = this.getX(y, leftSide);
 
- 				
 
- 			// set the anchor point for data labels
 
- 			point.labelPos = [
 
- 				0, // first break of connector
 
- 				y, // a/a
 
- 				x + (labelDistance - 5) * sign, // second break, right outside point shape
 
- 				y, // a/a
 
- 				x + labelDistance * sign, // landing point for connector
 
- 				y, // a/a
 
- 				leftSide ? 'right' : 'left', // alignment
 
- 				0 // center angle
 
- 			];
 
- 		}
 
- 		
 
- 		seriesTypes.pie.prototype.drawDataLabels.call(this);
 
- 	}
 
- });
 
- }(Highcharts));
 
 
  |