#************************************************************************************* # TOCOMMENT #************************************************************************************* class @ChartCandyDonut constructor: (@holder) -> @innerRadius = 55 @labelMargin = 12 @holderChart = @holder.find('div.templates div.chart') @holderTable = @holder.find('div.templates div.table') @initTools() @initSize() d3.json(@holder.data('url'), (d) => @loadTemplates d) centerLabel: (d, radius, text, position) -> c = @arc.centroid(d) x = c[0] y = c[1] h = Math.sqrt(x * x + y * y) tX = (x / h * radius) tY = (y / h * radius) sizeText = if position is 'inside' then String(text).length * 3.5 else 0 if tX > 0 then tX -= sizeText else tX += sizeText return "translate(" + tX + "," + tY + ")" centerHoleText: (hole) -> totalHeight = 0 heightElements = [] for content, i in @data.hole elemHeight = Math.round(Number(@holderChart.find('g.hole text.text' + i).height()) * 0.66) + 10 totalHeight += elemHeight heightElements.push elemHeight currentHeight = totalHeight / 1.8 * -1 for content, i in @data.hole currentHeight += heightElements[i] hole.selectAll("text.text" + i).attr("dy", currentHeight) drawChart: () -> @holderChart.html('') @root = d3.select("##{@holder.attr('id')} div.templates div.chart") @chart = @root.append("svg:svg").attr("width", @fullWidth()).attr("height", @fullHeight()) @chart.data([@data.slices]) donut = d3.layout.pie().sort(null) @arc = d3.svg.arc().innerRadius(@radius - @innerRadius).outerRadius(@radius) @arcs = @chart.selectAll("g.arc").data(donut.value((d) -> d.value)).enter().append("svg:g").attr("class", "arc").attr("transform", "translate(" + (@radius + @margins[3]) + "," + (@radius + @margins[0]) + ")") @arcs.append("svg:path").attr('class', (d, i) -> "slice-#{i+1}" ).attr "d", @arc drawHole: () -> hole = @chart.append("svg:g").attr("class", "hole").attr("transform", "translate(" + (@radius + @margins[3]) + "," + (@radius + @margins[0]) + ")") for content, i in @data.hole hole.append("svg:text").attr("class", "label text#{i}").attr("dy", 0).attr("text-anchor", "middle").text(content) @centerHoleText hole drawLabels: () -> @drawLabel 'label', @radiusLabel, 'outside' if @data.show_label @drawLabel 'valuef', (@radiusLabel - @innerRadius/2.5 - 20), 'inside' drawLabel: (key, radius, position) -> @arcs.append("svg:text").attr("transform", (d,i) => @centerLabel(d, radius, @data.slices[i][key], position)) .attr("dy", ".35em").attr("text-anchor", (d) -> (if (d.endAngle + d.startAngle) / 2 > Math.PI then "end" else "start")) .text (d,i) => if @data.slices[i]['percent'] > 3 or position is 'outside' (if position is 'inside' then @data.slices[i][key] else @data.slices[i][key]) else '' drawTooltip: () -> @tooltip = @root.append("div").attr('class', 'tooltip') fullHeight: () -> @height + @margins[0] + @margins[2] fullWidth: () -> @width + @margins[1] + @margins[3] initSize: () -> @margins = for side in ['Top', 'Right', 'Bottom', 'Left'] then Number(@holderChart.css('padding' + side).replace('px', '')) @holderChart.css('padding', '0px') @width = @holder.innerWidth() - @margins[1] - @margins[3] @height = @holder.innerHeight() - @margins[0] - @margins[2] @radius = Math.min(@width, @height) / 2 @radiusLabel = @labelMargin + @radius initTools: () -> @tools = @holder.find('div.tools') @tools.find('div.holder-template').bind('change', (e) => @showTemplate()) loadChart: () -> @drawChart() @drawHole() @drawLabels() @drawTooltip() @setChartEvents() loadTable: () -> content = '
' + @data.label + ' | ' + @data.value + ' |
---|---|
#{d.label} | #{d.value} |
' + @data.total.label + ' | ' + @data.total.value + ' |