css插件饼状统计图,CSS3 经典饼图统计图表

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

// Run the code when the DOM is ready

$( pieChart );

function pieChart() {

// Config settings

var chartSizePercent = 55; // The chart radius relative to the canvas width/height (in percent)

var sliceBorderWidth = 1; // Width (in pixels) of the border around each slice

var sliceBorderStyle = "#fff"; // Colour of the border around each slice

var sliceGradientColour = "#ddd"; // Colour to use for one end of the chart gradient

var maxPullOutDistance = 25; // How far, in pixels, to pull slices out when clicked

var pullOutFrameStep = 4; // How many pixels to move a slice with each animation frame

var pullOutFrameInterval = 40; // How long (in ms) between each animation frame

var pullOutLabelPadding = 65; // Padding between pulled-out slice and its label

var pullOutLabelFont = "bold 16px 'Trebuchet MS', Verdana, sans-serif"; // Pull-out slice label font

var pullOutValueFont = "bold 12px 'Trebuchet MS', Verdana, sans-serif"; // Pull-out slice value font

var pullOutValuePrefix = "$"; // Pull-out slice value prefix

var pullOutShadowColour = "rgba( 0, 0, 0, .5 )"; // Colour to use for the pull-out slice shadow

var pullOutShadowOffsetX = 5; // X-offset (in pixels) of the pull-out slice shadow

var pullOutShadowOffsetY = 5; // Y-offset (in pixels) of the pull-out slice shadow

var pullOutShadowBlur = 5; // How much to blur the pull-out slice shadow

var pullOutBorderWidth = 2; // Width (in pixels) of the pull-out slice border

var pullOutBorderStyle = "#333"; // Colour of the pull-out slice border

var chartStartAngle = -.5 * Math.PI; // Start the chart at 12 o'clock instead of 3 o'clock

// Declare some variables for the chart

var canvas; // The canvas element in the page

var currentPullOutSlice = -1; // The slice currently pulled out (-1 = no slice)

var currentPullOutDistance = 0; // How many pixels the pulled-out slice is currently pulled out in the animation

var animationId = 0; // Tracks the interval ID for the animation created by setInterval()

var chartData = []; // Chart data (labels, values, and angles)

var chartColours = []; // Chart colours (pulled from the HTML table)

var totalValue = 0; // Total of all the values in the chart

var canvasWidth; // Width of the canvas, in pixels

var canvasHeight; // Height of the canvas, in pixels

var centreX; // X-coordinate of centre of the canvas/chart

var centreY; // Y-coordinate of centre of the canvas/chart

var chartRadius; // Radius of the pie chart, in pixels

// Set things up and draw the chart

init();

/**

* Set up the chart data and colours, as well as the chart and table click handlers,

* and draw the initial pie chart

*/

function init() {

// Get the canvas element in the page

canvas = document.getElementById('chart');

// Exit if the browser isn't canvas-capable

if ( typeof canvas.getContext === 'undefined' ) return;

// Initialise some properties of the canvas and chart

canvasWidth = canvas.width;

canvasHeight = canvas.height;

centreX = canvasWidth / 2;

centreY = canvasHeight / 2;

chartRadius = Math.min( canvasWidth, canvasHeight ) / 2 * ( chartSizePercent / 100 );

// Grab the data from the table,

// and assign click handlers to the table data cells

var currentRow = -1;

var currentCell = 0;

$('#chartData td').each( function() {

currentCell++;

if ( currentCell % 2 != 0 ) {

currentRow++;

chartData[currentRow] = [];

chartData[currentRow]['label'] = $(this).text();

} else {

var value = parseFloat($(this).text());

totalValue += value;

value = value.toFixed(2);

chartData[currentRow]['value'] = value;

}

// Store the slice index in this cell, and attach a click handler to it

$(this).data( 'slice', currentRow );

$(this).click( handleTableClick );

// Extract and store the cell colour

if ( rgb = $(this).css('color').match( /rgb\((\d+), (\d+), (\d+)/) ) {

chartColours[currentRow] = [ rgb[1], rgb[2], rgb[3] ];

} else if ( hex = $(this).css('color').match(/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/) ) {

chartColours[currentRow] = [ parseInt(hex[1],16) ,parseInt(hex[2],16), parseInt(hex[3], 16) ];

} else {

alert( "Error: Colour could not be determined! Please specify table colours using the format '#xxxxxx'" );

return;

}

} );

// Now compute and store the start and end angles of each slice in the chart data

var currentPos = 0; // The current position of the slice in the pie (from 0 to 1)

for ( var slice in chartData ) {

chartData[slice]['startAngle'] = 2 * Math.PI * currentPos;

chartData[slice]['endAngle'] = 2 * Math.PI * ( currentPos + ( chartData[slice]['value'] / totalValue ) );

currentPos += chartData[slice]['value'] / totalValue;

}

// All ready! Now draw the pie chart, and add the click handler to it

drawChart();

$('#chart').click ( handleChartClick );

}

/**

* Process mouse clicks in the chart area.

*

* If a slice was clicked, toggle it in or out.

* If the user clicked outside the pie, push any slices back in.

*

* @param Event The click event

*/

function handleChartClick ( clickEvent ) {

// Get the mouse cursor position at the time of the click, relative to the canvas

var mouseX = clickEvent.pageX - this.offsetLeft;

var mouseY = clickEvent.pageY - this.offsetTop;

// Was the click inside the pie chart?

var xFromCentre = mouseX - centreX;

var yFromCentre = mouseY - centreY;

var distanceFromCentre = Math.sqrt( Math.pow( Math.abs( xFromCentre ), 2 ) + Math.pow( Math.abs( yFromCentre ), 2 ) );

if ( distanceFromCentre <= chartRadius ) {

// Yes, the click was inside the chart.

// Find the slice that was clicked by comparing angles relative to the chart centre.

var clickAngle = Math.atan2( yFromCentre, xFromCentre ) - chartStartAngle;

if ( clickAngle < 0 ) clickAngle = 2 * Math.PI + clickAngle;

for ( var slice in chartData ) {

if ( clickAngle >= chartData[slice]['startAngle'] && clickAngle <= chartData[slice]['endAngle'] ) {

// Slice found. Pull it out or push it in, as required.

toggleSlice ( slice );

return;

}

}

}

// User must have clicked outside the pie. Push any pulled-out slice back in.

pushIn();

}

/**

* Process mouse clicks in the table area.

*

* Retrieve the slice number from the jQuery data stored in the

* clicked table cell, then toggle the slice

*

* @param Event The click event

*/

function handleTableClick ( clickEvent ) {

var slice = $(this).data('slice');

toggleSlice ( slice );

}

/**

* Push a slice in or out.

*

* If it's already pulled out, push it in. Otherwise, pull it out.

*

* @param Number The slice index (between 0 and the number of slices - 1)

*/

function toggleSlice ( slice ) {

if ( slice == currentPullOutSlice ) {

pushIn();

} else {

startPullOut ( slice );

}

}

/**

* Start pulling a slice out from the pie.

*

* @param Number The slice index (between 0 and the number of slices - 1)

*/

function startPullOut ( slice ) {

// Exit if we're already pulling out this slice

if ( currentPullOutSlice == slice ) return;

// Record the slice that we're pulling out, clear any previous animation, then start the animation

currentPullOutSlice = slice;

currentPullOutDistance = 0;

clearInterval( animationId );

animationId = setInterval( function() { animatePullOut( slice ); }, pullOutFrameInterval );

// Highlight the corresponding row in the key table

$('#chartData td').removeClass('highlight');

var labelCell = $('#chartData td:eq(' + (slice*2) + ')');

var valueCell = $('#chartData td:eq(' + (slice*2+1) + ')');

labelCell.addClass('highlight');

valueCell.addClass('highlight');

}

/**

* Draw a frame of the pull-out animation.

*

* @param Number The index of the slice being pulled out

*/

function animatePullOut ( slice ) {

// Pull the slice out some more

currentPullOutDistance += pullOutFrameStep;

// If we've pulled it right out, stop animating

if ( currentPullOutDistance >= maxPullOutDistance ) {

clearInterval( animationId );

return;

}

// Draw the frame

drawChart();

}

/**

* Push any pulled-out slice back in.

*

* Resets the animation variables and redraws the chart.

* Also un-highlights all rows in the table.

*/

function pushIn() {

currentPullOutSlice = -1;

currentPullOutDistance = 0;

clearInterval( animationId );

drawChart();

$('#chartData td').removeClass('highlight');

}

/**

* Draw the chart.

*

* Loop through each slice of the pie, and draw it.

*/

function drawChart() {

// Get a drawing context

var context = canvas.getContext('2d');

// Clear the canvas, ready for the new frame

context.clearRect ( 0, 0, canvasWidth, canvasHeight );

// Draw each slice of the chart, skipping the pull-out slice (if any)

for ( var slice in chartData ) {

if ( slice != currentPullOutSlice ) drawSlice( context, slice );

}

// If there's a pull-out slice in effect, draw it.

// (We draw the pull-out slice last so its drop shadow doesn't get painted over.)

if ( currentPullOutSlice != -1 ) drawSlice( context, currentPullOutSlice );

}

/**

* Draw an individual slice in the chart.

*

* @param Context A canvas context to draw on

* @param Number The index of the slice to draw

*/

function drawSlice ( context, slice ) {

// Compute the adjusted start and end angles for the slice

var startAngle = chartData[slice]['startAngle'] + chartStartAngle;

var endAngle = chartData[slice]['endAngle'] + chartStartAngle;

if ( slice == currentPullOutSlice ) {

// We're pulling (or have pulled) this slice out.

// Offset it from the pie centre, draw the text label,

// and add a drop shadow.

var midAngle = (startAngle + endAngle) / 2;

var actualPullOutDistance = currentPullOutDistance * easeOut( currentPullOutDistance/maxPullOutDistance, .8 );

startX = centreX + Math.cos(midAngle) * actualPullOutDistance;

startY = centreY + Math.sin(midAngle) * actualPullOutDistance;

context.fillStyle = 'rgb(' + chartColours[slice].join(',') + ')';

context.textAlign = "center";

context.font = pullOutLabelFont;

context.fillText( chartData[slice]['label'], centreX + Math.cos(midAngle) * ( chartRadius + maxPullOutDistance + pullOutLabelPadding ), centreY + Math.sin(midAngle) * ( chartRadius + maxPullOutDistance + pullOutLabelPadding ) );

context.font = pullOutValueFont;

context.fillText( pullOutValuePrefix + chartData[slice]['value'] + " (" + ( parseInt( chartData[slice]['value'] / totalValue * 100 + .5 ) ) + "%)", centreX + Math.cos(midAngle) * ( chartRadius + maxPullOutDistance + pullOutLabelPadding ), centreY + Math.sin(midAngle) * ( chartRadius + maxPullOutDistance + pullOutLabelPadding ) + 20 );

context.shadowOffsetX = pullOutShadowOffsetX;

context.shadowOffsetY = pullOutShadowOffsetY;

context.shadowBlur = pullOutShadowBlur;

} else {

// This slice isn't pulled out, so draw it from the pie centre

startX = centreX;

startY = centreY;

}

// Set up the gradient fill for the slice

var sliceGradient = context.createLinearGradient( 0, 0, canvasWidth*.75, canvasHeight*.75 );

sliceGradient.addColorStop( 0, sliceGradientColour );

sliceGradient.addColorStop( 1, 'rgb(' + chartColours[slice].join(',') + ')' );

// Draw the slice

context.beginPath();

context.moveTo( startX, startY );

context.arc( startX, startY, chartRadius, startAngle, endAngle, false );

context.lineTo( startX, startY );

context.closePath();

context.fillStyle = sliceGradient;

context.shadowColor = ( slice == currentPullOutSlice ) ? pullOutShadowColour : "rgba( 0, 0, 0, 0 )";

context.fill();

context.shadowColor = "rgba( 0, 0, 0, 0 )";

// Style the slice border appropriately

if ( slice == currentPullOutSlice ) {

context.lineWidth = pullOutBorderWidth;

context.strokeStyle = pullOutBorderStyle;

} else {

context.lineWidth = sliceBorderWidth;

context.strokeStyle = sliceBorderStyle;

}

// Draw the slice border

context.stroke();

}

/**

* Easing function.

*

* A bit hacky but it seems to work! (Note to self: Re-read my school maths books sometime)

*

* @param Number The ratio of the current distance travelled to the maximum distance

* @param Number The power (higher numbers = more gradual easing)

* @return Number The new ratio

*/

function easeOut( ratio, power ) {

return ( Math.pow ( 1 - ratio, power ) + 1 );

}

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值