Skip to content

Instantly share code, notes, and snippets.

@rubyonrailstutor
Created January 9, 2014 21:13
Show Gist options
  • Save rubyonrailstutor/8342139 to your computer and use it in GitHub Desktop.
Save rubyonrailstutor/8342139 to your computer and use it in GitHub Desktop.
real time angular d3 piechart
angular.module('CrowdSound').directive 'csChart', () ->
restrict: "E"
scope:
question: "="
index: "="
link: (scope, element, attrs) ->
scope.data = []
class PieChart
constructor: (element) ->
@width = 350
@height = 350
# @oRadius = @width/2
@iRadius = 50
@padding = 2
@layout = d3.layout.pie().value( (d) =>
d.votes)
@chart = d3.select(element[0])
@svg = @chart.append("svg")
.attr("width", @width)
.attr("height", @height)
@color = d3.scale.category10().domain(d3.range(0,10))
@arcGroup = @svg.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
@labelGroup = @svg.append("g")
.attr("class", "label")
.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
arc: () ->
d3.svg.arc()
.innerRadius(@iRadius)
.outerRadius(@oRadius())
oRadius: () ->
@width/2
toggleWidth: () ->
width = d3.select("#question#{scope.index}").style("width")
return if width.match("%")
if width == "auto" || parseInt(width) < 350
@width = 220
@height = 220
@svg.attr("width", @width).attr("height", @height)
@arcGroup.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
@labelGroup.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
else
@width = 350
@height = 350
@svg.attr("width", @width).attr("height", @height)
@arcGroup.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
@labelGroup.attr("transform", "translate(" + @oRadius() + "," + @oRadius() + ")" )
arcTween: (oldData, d, i) =>
# if oldData[i]
# s0 = oldData[i].startAngle
# e0 = oldData[i].endAngle
# else
# s0 = 0
# e0 = 0
# i = d3.interpolate({startAngle: s0, endAngle: e0}, {startAngle: d.startAngle, endAngle: d.endAngle})
i = d3.interpolate(this._current, d)
(t) =>
b = i(t)
@arc()(b)
render: (oldData, newData) ->
console.log "render csPie triggered"
return if _.compact(_.pluck(newData, 'votes')).length is 0
@toggleWidth()
pieData = @layout(newData)
oldPieData = @layout(oldData)
@arcGroup.selectAll("path").data(pieData)
.enter().append("path")
.attr("fill", (d,i) => @color(i) )
.transition()
.duration(1000)
.attr("d", (d) =>
@arc()(d)
)
.each((d) =>
this._current = d
)
@arcGroup.selectAll("path").data(pieData)
.transition()
.attr("fill", (d,i) => @color(i) )
.duration(1000)
.attrTween("d", (d,i) =>
@arcTween(oldPieData, d,i));
@arcGroup.selectAll("path").data(pieData)
.exit()
.remove()
.transition()
.duration(1000)
.attrTween("d", (d,i) =>
@arcTween(oldPieData, d,i));
@labelGroup.selectAll("text").data(pieData)
.enter()
.append("text")
.transition()
.duration(500)
.attr('transform', (d) => 'translate(' + @arc().centroid(d) + ')' )
.attr('text-anchor', 'middle')
.text((d) ->
if d.value is 0
""
else
d.data.answer.substr(0,10) + " (" + d.value + ")")
@labelGroup.selectAll("text").data(pieData)
.transition()
.duration(500)
.attr('transform', (d) => 'translate(' + @arc().centroid(d) + ')' )
.attr('text-anchor', 'middle')
.text((d) ->
if d.value is 0
""
else
d.data.answer.substr(0,10) + " (" + d.value + ")")
@labelGroup.selectAll("text").data(pieData)
.exit().remove()
.transition()
.duration(500)
pieChart = new PieChart(element)
scope.$watch "data",
(newData, oldData) =>
if newData
pieChart.render(oldData, newData)
,
true
scope.$watch 'question',
(newData, oldData) ->
if newData
rawData = []
_.each newData.answers, (obj) ->
if obj.votes?
datum = {}
datum.votes = obj.votes
datum.answer = obj.name
rawData.push datum
scope.data = rawData
,
true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment