Skip to content

Instantly share code, notes, and snippets.

@dcalacci
Created November 17, 2015 05:44
Show Gist options
  • Save dcalacci/2e8fd0ad8218c74fd803 to your computer and use it in GitHub Desktop.
Save dcalacci/2e8fd0ad8218c74fd803 to your computer and use it in GitHub Desktop.

pie chart (coffeescript)

simple pie chart with update in coffeescript.

this code opts to not remove keys that are lost on an update, and instead just treats them as zero values.

pieWidth = 300
pieHeight = 300
window.pie = null
window.pie = new PieChart [{'participantId': 'participant1',
'secondsSpoken': 5},
{'participantId': 'participant2',
'secondsSpoken': 10}], pieWidth, pieHeight
window.pie.render()
setTimeout(
() =>
window.pie.change( [{'participantId': 'participant1', 'secondsSpoken': 8},
{'participantId': 'participant2', 'secondsSpoken': 7}]
)
, 1000
)
setTimeout(
() =>
window.pie.change( [{'participantId': 'participant1', 'secondsSpoken': 0},
{'participantId': 'participant2', 'secondsSpoken': 5},
{'participantId': 'participant3', 'secondsSpoken': 5}]
)
, 3000
)
setTimeout(
() =>
window.pie.change( [{'participantId': 'participant1', 'secondsSpoken': 3},
{'participantId': 'participant2', 'secondsSpoken': 5},
{'participantId': 'participant3', 'secondsSpoken': 5}]
)
, 4000
)
<body>
<div id="pie-chart">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.8/d3.min.js"></script>
<script src="pieChart.js"></script>
<script src="all.js"></script>
</body>
class window.PieChart
constructor: (data, width, height) ->
@data = data
@prevData = data # to keep track of previous data step. same at first.
console.log("[pieChart] data:", @data);
@margin = {top: 10, right: 10, bottom: 10, left: 10}
@width = width - @margin.right - @margin.left
@height = width - @margin.top - @margin.bottom
@radius = d3.min([@width, @height]) / 2
@arc = d3.svg.arc()
.innerRadius(@radius - 100)
.outerRadius(@radius - 20)
# key function to access arc/data identifiers
@key = (d) -> d.data.participantId
@pie = d3.layout.pie()
.value (d) -> d.secondsSpoken
.sort(null);
@color = (d) ->
if (d.data.participantId == "participant1")
"#aaaaa"
else
"#B2B2B2"
render: (id="#pie-chart") =>
@chart = d3.select(id)
.append "svg"
.attr "class", "pieChart"
.attr "width", @width + @margin.left + @margin.right
.attr "height", @height + @margin.top + @margin.bottom
.append "g"
.attr "transform", "translate(" + (@width / 2) + "," + (@height / 2) + ")"
@chartBody = @chart.append "g"
console.log @pie(@data)
@path = @chartBody
.selectAll "path"
.data @pie(@data)
.enter().append "path"
@path .transition()
.duration(500)
.attr "fill", @color
.attr "d", @arc
change: (data) ->
# don't lose keys, just put them to 0
data = @setLostKeysToZero data
# keep track of previous data state
@prevData = @data
@data = data
# render new arcs from new keys
@path.data @pie(data)
.enter().append "path"
.attr "fill", @color
.attr "d", @arc
# transition to make the update pretty
@path.transition()
.duration 750
.attrTween "d", @arcTween
# convenience function to set keys that were lost between @data and
# data to 0, instead of removing them from the chart
# completely. Not necessary, but can make some transitions better.
setLostKeysToZero: (data) =>
for item0 in @data
found = false
for item1 in data
if item0.participantId == item1.participantId
found = true
if !found
item0.secondsSpoken = 0
data.push(item0)
data
# re-arranges data to object keyed by the @key function
# makes it easy to reference specific arcs
orderData: (layout) ->
res = {}
for obj in layout
res[@key(obj)] = obj
return res
# transition function for pie chart
arcTween: (d) =>
# grab the old angle data from the previous data, interpolate to
# new
oldAngles = @orderData(@pie(@prevData))
i = d3.interpolate(oldAngles[@key(d)], d)
# function to give interpolation step for each tween step
return (t) => @arc(i(t))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment