Created
September 10, 2012 21:58
-
-
Save dylang/3694235 to your computer and use it in GitHub Desktop.
piehole
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function testPie(element) { | |
// constants | |
var FONT = 'ProximaNova'; | |
var WIDTH = 390, | |
HEIGHT = 390, | |
CENTER_X = 200, | |
CENTER_Y = 200, | |
CX_CY = CENTER_X+','+CENTER_Y; | |
// TODO - move this MP to JSP | |
var MESSAGE_PROPERTIES_TYPES = { | |
COOLING: 'Cooling', | |
HEATING: 'Heating', | |
WATER_HEATING: 'Hot Water', | |
APPLIANCES: 'Appliances', | |
LIGHTING: 'Lighting', | |
OTHER: 'Other' | |
}; | |
// Order of the questions | |
var PIE_ORDER = ['COOLING', 'HEATING', 'WATER_HEATING', 'APPLIANCES', 'LIGHTING', 'OTHER'], | |
PIE_COLORS = { COOLING: '#1087C9', HEATING: '#AB3E2C', WATER_HEATING: '#663366', APPLIANCES: '#C2B59B', LIGHTING: '#65D9C5', OTHER: '#8FC740'}; | |
// set arrays of the slice fill colors and sizes | |
var sliceColors = ['1087C9','AB3E2C','663366','C2B59B','65D9C5','8FC740'], | |
sliceData = [30, 30, 20, 10, 70, 38]; | |
// pie vars | |
var paper = Raphael(element, WIDTH, HEIGHT), | |
slicePercents = [], | |
SLICE_COUNT = sliceData.length, | |
rDeg = -90, | |
s1 = 's1,1,', | |
s2 = 's1.05,1.05,', | |
paths = paper.set(), | |
total = 0, | |
start; | |
var | |
i = 0; | |
for (i = 0; i < SLICE_COUNT; i++) { | |
total += sliceData[i]; | |
} | |
Raphael.el.rHide = function () { | |
this.attr({opacity:0}); | |
}; | |
Raphael.el.rShow = function () { | |
this.attr({opacity:1}); | |
}; | |
function hideHole() { | |
holes.attr({opacity:0}); | |
} | |
paper.customAttributes.segment = function (x, y, r, a1, a2) { | |
var flag = (a2 - a1) > 180, | |
a1 = (a1 % 360) * Math.PI / 180; | |
a2 = (a2 % 360) * Math.PI / 180; | |
return { | |
path: [["M", x, y], ["l", r * Math.cos(a1), r * Math.sin(a1)], ["A", r, r, 0, +flag, 1, x + r * Math.cos(a2), y + r * Math.sin(a2)], ["z"]] | |
}; | |
}; | |
/** | |
* animate | |
* @param ms miliseconds | |
* @param ind pie slice number. null for gray, number for how many to show in color | |
*/ | |
function pieAnimate(ms,ind) { | |
var start = 0, end, val, | |
rDeg = -90, | |
indj = parseInt(ind)+SLICE_COUNT, | |
j, newPercent; | |
// loop through pie slices | |
for (i = 0; i < SLICE_COUNT; i++) { | |
j = i+SLICE_COUNT; | |
val = 360 / total * sliceData[i]; | |
end = start+val; | |
newPercent = Math.round((sliceData[i] / total) * 100); | |
slicePercents.push(newPercent); | |
percent[i].attr('text',newPercent); | |
//$('.tip-container section:eq('+i+') .percentage').html(newPercent); | |
// set a complete class, figure out colors | |
var hexColor = 'dddddd'; | |
paths[j].attr({cursor:'default'}); | |
if ( i<=ind ) { | |
paths[j].data('class','finished'); | |
hexColor = sliceColors[i]; | |
} else if (ind==SLICE_COUNT-1) { | |
hexColor = sliceColors[SLICE_COUNT-1]; | |
} else if (ind==SLICE_COUNT) { | |
paths[j].data('class','finished').attr({cursor:'pointer'}); | |
} | |
// calculate the new slice sizes, animate them | |
paths[i].animate({ | |
segment: [CENTER_X, CENTER_Y, 165, start, end, i, ind], | |
fill: '#'+hexColor, | |
transform:['paper'+rDeg+','+CX_CY] | |
}, | |
ms || 700, | |
'backOut'); | |
paths[j].attr({ | |
segment: [CENTER_X, CENTER_Y, 165, start, start+=val, i, ind], | |
transform:['paper'+rDeg+','+CX_CY] | |
}); | |
} | |
// make the selected slice larger, show the corresponding donuteHole | |
if (ind<SLICE_COUNT) { | |
// show the stuff in the hole | |
hideHole(); | |
circle.rShow(); | |
headers[ind].rShow(); | |
inProg.rShow(); | |
// active class for the active audit section | |
paths[indj].data('class','active'); | |
// bump the active slice out | |
paths[ind].animate({transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY], fill: '#888888'}, 700, "backOut"); | |
paths[indj].animate({transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY]},0); | |
} | |
// rotate the pie, so that the first slice starts at 12:00 | |
paths.transform('paper'+rDeg+','+CX_CY); | |
} | |
// okay this is tricky. we create TWO pies, one that sits over the other, invisible, so that hovering over the hole | |
// doesn't hover out of the slice. All the click and hover functions happen on the invisible pie on top. Ya dig? | |
// first we build the colorful "underpie": | |
start = 0; | |
for (i = 0; i < SLICE_COUNT; i++) { | |
val = 360 / total * sliceData[i]; | |
(function (i, val) { | |
paths.push(paper.path().attr({segment: [CENTER_X, CENTER_Y, 1, start, start + val], stroke: "#ffffff", "stroke-width": 3, opacity:1})); | |
})(i, val); | |
start += val; | |
} | |
// cut out a hole next, so it is layered between the overpie and underpie. add the text. | |
var holes = paper.set(), | |
headers = paper.set(), | |
headers2= paper.set(), | |
percent = paper.set(), | |
perc2 = paper.set(), | |
circle = paper.circle(CENTER_X, CENTER_Y, 95).attr({fill: '#F5F5F5', stroke: '#FFFFFF', "stroke-width":3}), | |
instr = paper.text(CENTER_X, CENTER_Y, 'Answer the questions on\nthe right to see your\n energy use breakdown.').attr({'font-size':12,'font-family':'proxima'}), | |
inProg = paper.text(CENTER_X, CENTER_Y+25, 'In progress').attr({'font-size':16,'font-family':FONT,'fill':'#000000'}), | |
notStrt = paper.text(CENTER_X, CENTER_Y+25, 'Not started').attr({'font-size':16,'font-family':FONT,'fill':'#000000'}), | |
average = paper.set(); | |
for (i = 0; i < SLICE_COUNT; i++) { | |
(function (i) { | |
var t1 = paper.text(CENTER_X-20 , CENTER_Y-15, sliceData[i]).attr({'font-size':55,'font-family':FONT,'font-weight':'bold','fill':'#000000'}), | |
t1W = (t1.getBBox().width)/2, | |
t2 = paper.text(CENTER_X+t1W, CENTER_Y-15, '%').attr({'font-size':55,'font-family':FONT,'font-weight':'normal','fill':'#000000'}), | |
perc1 = paper.set(); | |
percent.push(t1); | |
headers.push(paper.text(CENTER_X, CENTER_Y-15, MESSAGE_PROPERTIES_TYPES[PIE_ORDER[i]]).attr({'font-size':25,'font-family':FONT,'font-weight':'bold','fill':'#'+sliceColors[i]})); | |
headers2.push(paper.text(CENTER_X, CENTER_Y+25, MESSAGE_PROPERTIES_TYPES[PIE_ORDER[i]]).attr({'font-size':25,'font-family':FONT,'font-weight':'bold','fill':'#'+sliceColors[i]})); | |
perc1.push(t1,t2); | |
perc2.push(perc1); | |
average.push(paper.text(CENTER_X, CENTER_Y+20, Math.round((sliceData[i] / total) * 100)+'% is the average used\nby utility customers').attr({'font-size':12,'font-family':FONT,'font-weight':'normal','fill':'#000000'})); | |
})(i); | |
} | |
holes.push(circle,headers,headers2,perc2,instr,inProg,notStrt,average); | |
hideHole(); | |
// then we build an invisible pie, layered on top of everything else | |
start = 0; | |
for (i = 0; i < SLICE_COUNT; i++) { | |
var val = 360 / total * sliceData[i], | |
j = i+SLICE_COUNT; | |
(function (i, j, val) { | |
paths | |
.push(paper.path() | |
.attr({ | |
segment: [ CENTER_X, CENTER_Y, 1, start, start + val], | |
stroke: "#000", | |
fill:"#fff", | |
"stroke-width": 3, | |
opacity:0 | |
}) | |
.click(function () { // the hidden over-pie. | |
// click the slice | |
var getClass = paths[j].data('class'); | |
if (getClass=='finished') { | |
// set a class, so that the hover effects don't work when the pie is spinning | |
paths.data('class','animating'); | |
// reset the scale, don't want the bounce effect when the pie spins | |
paths.stop().transform(s1+CX_CY+'paper'+rDeg+','+CX_CY); | |
// get the right rotation of the pie, based on what was clicked | |
var z = paths[i].attr('segment'); | |
var t = z[4]-((z[4]-z[3])/2); // should give the center line of a slice | |
rDeg = -t; // new rotation degree is the center of the selected slice (set this as global) | |
// hide the hole | |
hideHole(); | |
// rotate the pie so that active slice faces the audit | |
paths.animate({transform: [s1+CX_CY+'paper'+rDeg+','+CX_CY]}, 700, "backOut", function(){ | |
// remove that animating class, so hover animation works again | |
setTimeout(function(){ | |
paths.data('class','finished'); | |
paths[i].data('class','selected'); | |
},500); | |
// pop the clicked slice back out | |
for (vi = 0; vi < SLICE_COUNT; vi++) { | |
paths[vi].animate({opacity:0.5}, 700, "backOut"); | |
}; | |
paths[i].animate({opacity:1, transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY]}, 700, "backOut"); | |
paths[j].attr({transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY]}); | |
// show the slice-specific tip modal | |
//$('.tip-container section').hide(); | |
//$('.tip-container').show().children('section').eq(i).show(); | |
}); | |
} | |
}) | |
.hover( | |
// hover over | |
function() { | |
var getClass = paths[j].data('class'); | |
if (getClass !== 'animating') { | |
hideHole(); | |
circle.rShow(); | |
paths[i].animate({transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY]}, 200, "backOut"); | |
paths[j].attr({transform: [s2+CX_CY+'paper'+rDeg+','+CX_CY]}); | |
} | |
if (getClass == 'started') { | |
headers[i].rShow(); | |
notStrt.rShow(); | |
} | |
if (getClass == 'active') { | |
headers[i].rShow(); | |
inProg.rShow(); | |
} | |
if (getClass == 'finished' || getClass == 'selected') { | |
headers2[i].rShow(); | |
perc2[i].attr({opacity:1}); | |
} | |
if (getClass == undefined) { | |
headers[i].attr({'fill': '#888888'}).rShow(); | |
average[i].rShow(); | |
paths[i].animate({fill: '#888888'}, 200, "backOut"); | |
} | |
}, | |
// hover out | |
function() { | |
var getClass = paths[j].data('class'); | |
if (getClass == 'started' || getClass == 'finished' || getClass == undefined) { | |
var transform = paths[j].attr('transform'); // redundant, but necessary, otherwise the rotation value is from before the slice was clicked | |
hideHole(); | |
paths[i].animate({transform: [s1+CX_CY+'paper'+rDeg+','+CX_CY]}, 400, "backOut"); | |
paths[j].attr({transform: [s1+CX_CY+'paper'+rDeg+','+CX_CY]}); | |
} | |
if (getClass == 'selected') { | |
hideHole(); | |
} | |
if (getClass == 'active') { | |
circle.rShow(); | |
headers[i].rShow(); | |
inProg.rShow(); | |
} | |
if (getClass == undefined) { | |
paths.animate({fill: '#dddddd'}, 200, "backOut"); | |
} | |
for (var vi = SLICE_COUNT; vi < (SLICE_COUNT*2); vi++) { | |
getClass = paths[vi].data('class'); | |
// set the right hole back | |
if (getClass == 'active' ) { | |
circle.rShow(); | |
headers[vi-SLICE_COUNT].rShow(); | |
inProg.rShow(); | |
} | |
} | |
} | |
)); | |
})(i, j, val); | |
start += val; | |
} | |
// make-a da pie on page load | |
//pieAnimate(700); | |
pieAnimate(700,SLICE_COUNT-1); | |
//pieAnimate(700,auditNext); | |
//pieAnimate(700,auditPrev); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment