Using D3 to render data based charts in Ember


#1

I’ve been using D3js recently to do some charting in my applications but I am really struggling to take something that works and renders in a standard ‘HTML with tags’ way and turn that into an Ember component.

Taking a simple example from blocks.org:

<!DOCTYPE html>
<html>
  <head>    
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Testing Pie Chart</title>
.slice text { font-size: 16pt; font-family: Arial; }
    var w = 300,                        //width
    h = 300,                            //height
    r = 100,                            //radius
    color = d3.scale.category20c();    
    data = [{"label":"one", "value":20}, 
            {"label":"two", "value":50}, 
            {"label":"three", "value":30}];
    
    var vis = d3.select("#chart")
        .append("svg:svg")              
        .data([data])                   
            .attr("width", w)          
            .attr("height", h)
        .append("svg:g")               
            .attr("transform", "translate(" + r + "," + r + ")")   

    var arc = d3.svg.arc()              
        .outerRadius(r);

    var pie = d3.layout.pie()           
        .value(function(d) { return d.value; });   

    var arcs = vis.selectAll("g.slice")    
        .data(pie)                          
        .enter()                            
            .append("svg:g")                
                .attr("class", "slice");    

        arcs.append("svg:path")
                .attr("fill", function(d, i) { return color(i); } ) 
                .attr("d", arc);                                    

        arcs.append("svg:text")                                    
                .attr("transform", function(d) {                    
                d.innerRadius = 0;
                d.outerRadius = r;
                return "translate(" + arc.centroid(d) + ")";        
            })
            .attr("text-anchor", "middle")                          
            .text(function(d, i) { return data[i].label; });   
        
    </script>
  </body>
</html>

Assume that D3 is imported correctly into the Ember component, I find it very challenging to refactor into something that Ember will accept. I end up in a mess of errors ranging from ‘not a function’ to ‘undefined’ or general unexpected token syntax problems. I suspect my best efforts also have things being triggered in incorrect load orders.

I’ve been surprised at the lack of resources that talk about using D3 in an ember context and wondered if anyone could provide some tips or guidance on what to look out for.


#2

You are right it is difficult to find Ember/D3 resources. Here are a couple of working Ember / D3 examples I threw together that may lead you in the right direction. Some are direct implementations of pure D3 examples, others are my own rough efforts. All use component based charts.

I used ember install ember-browserify and standard npm install d3 to add d3.js to the below Ember apps.

Be sure to stay aware of the d3.js version being implemented. d3.js 3.X.X to 4.X.X has some breaking changes. You may need use npm install d3@3.5.17 3.5.17 was the last version 3 release.

ember-d3-sample3

ember-d3-v4-streamgraph


#3

Hi! You very helpfully replied to a similar question I made on Stack Overflow a few days ago. I had a look at your examples and they are very cool. Unfortunately I have yet to be able to refactor them into a usable form in my application - something which is my error not yours.

If you would be willing, I’d love to know a bit more about how you structure the pie chart in the sample3 repo. I understand the elements in the D3 sample in the OP but when I try to emberise them I fall flat.

I did try and take your Pie Chart code and boil it down to what I considered to be ‘just the basics’ but couldn’t get it to trigger correctly.


#4

No problem, sorry about the repeat answer. Here is an EmberTwiddle that is much cleaner than the crude example provided in the sample-3 app. The example below displays a static chart.

The construction of the chart takes place in the didInsertElement() component hook. This should provide a much clearer breakdown of how the chart is built within the component.

didInsertElement() {
    const data = this.get('data');

    this.setColor();
    this.setRadius();
    this.setArc();
    this.setLabelArc();
    this.setSvg();
    this.buildChart(data);

    this._super(...arguments);
},

D3 Pie Chart Ember Twiddle

Please let me know if you have further questions.


#5

That is super helpful, thank you very much!