2016-06-17 3 views
1

d3js новичок здесь. Я использую d3js для рендеринга svg на сервере. После прохождения через некоторые уроки я смог придумать это:d3js с узлом, как добавить строки в круговую диаграмму?

var fs = require('fs'); 
var d3 = require('d3'); 
var jsdom = require('jsdom'); 
var _ = require("underscore"); 
var chartWidth = 500, chartHeight = 500; 

var arc = d3.svg.arc() 
    .outerRadius(chartWidth/2 - 10) 
    .innerRadius(0); 

var colours = ['#98abc5','#8a89a6','#7b6888','#6b486b','#a05d56',"#d0743c", "#ff8c00"]; 

var pieData = [ 
    { 
     "category" : "Category A", 
     "amount" : 300 
    }, 
    { 
     "category" : "Category B", 
     "amount" : 300 
    } 
]; 

makePie(pieData); 

function makePie(pieData, outputLocation){ 
    var amount = _.pluck(pieData, "amount"); 
    var category = _.pluck(pieData, "category"); 

    jsdom.env({ 
     html:'', 
     features:{ QuerySelector:true }, //you need query selector for D3 to work 
     done:function(errors, window){ 
      window.d3 = d3.select(window.document); //get d3 into the dom 

      //do yr normal d3 stuff 
      var svg = window.d3.select('body') 
       .append('div') 
        .attr('class','container') //make a container div to ease the saving process 
       .append('svg') 
        .attr({ 
         xmlns:'http://www.w3.org/2000/svg', 
         width:chartWidth, 
         height:chartHeight 
        }) 
       .append('g') 
        .attr('transform','translate(' + chartWidth/2 + ',' + chartWidth/2 + ')'); 

      svg.selectAll('.arc') 
       .data(d3.layout.pie()(amount)) 
        .enter() 
       .append('path') 
        .attr({ 
         'class':'arc', 
         'd':arc, 
         'fill':function(d,i){ 
          return colours[i]; 
         }, 
         'stroke':'#fff' 
        }); 
      //write out the children of the container div 
      fs.writeFileSync("test.svg", window.d3.select('.container').html()) //using sync to keep the code simple 

     } 
    }); 
} 

Хотя это делает диаграмму SVG, я не знаю, как добавить строки в таблице, которая покажет, какая секция относится к какой категории.

Как это сделать?

+0

рад помочь! :) –

ответ

1

Edit/Update (примечание: написано 'thudfactor') - это как добавить метки/линии

var data = [{ 
 
    label: 'Star Wars', 
 
    instances: 207 
 
}, { 
 
    label: 'Lost In Space', 
 
    instances: 3 
 
}, { 
 
    label: 'the Boston Pops', 
 
    instances: 20 
 
}, { 
 
    label: 'Indiana Jones', 
 
    instances: 150 
 
}, { 
 
    label: 'Harry Potter', 
 
    instances: 75 
 
}, { 
 
    label: 'Jaws', 
 
    instances: 5 
 
}, { 
 
    label: 'Lincoln', 
 
    instances: 1 
 
}]; 
 

 
svg = d3.select("svg"); 
 
canvas = d3.select("#canvas"); 
 
art = d3.select("#art"); 
 
labels = d3.select("#labels"); 
 

 
// Create the pie layout function. 
 
// This function will add convenience 
 
// data to our existing data, like 
 
// the start angle and end angle 
 
// for each data element. 
 
jhw_pie = d3.layout.pie() 
 
jhw_pie.value(function (d, i) { 
 
    // Tells the layout function what 
 
    // property of our data object to 
 
    // use as the value. 
 
    return d.instances; 
 
}); 
 

 
// Store our chart dimensions 
 
cDim = { 
 
    height: 500, 
 
    width: 500, 
 
    innerRadius: 50, 
 
    outerRadius: 150, 
 
    labelRadius: 175 
 
} 
 

 
// Set the size of our SVG element 
 
svg.attr({ 
 
    height: cDim.height, 
 
    width: cDim.width 
 
}); 
 

 
// This translate property moves the origin of the group's coordinate 
 
// space to the center of the SVG element, saving us translating every 
 
// coordinate individually. 
 
canvas.attr("transform", "translate(" + (cDim.width/2) + "," + (cDim.width/2) + ")"); 
 

 
pied_data = jhw_pie(data); 
 

 
// The pied_arc function we make here will calculate the path 
 
// information for each wedge based on the data set. This is 
 
// used in the "d" attribute. 
 
pied_arc = d3.svg.arc() 
 
    .innerRadius(50) 
 
    .outerRadius(150); 
 

 
// This is an ordinal scale that returns 10 predefined colors. 
 
// It is part of d3 core. 
 
pied_colors = d3.scale.category10(); 
 

 
// Let's start drawing the arcs. 
 
enteringArcs = art.selectAll(".wedge").data(pied_data).enter(); 
 

 
enteringArcs.append("path") 
 
    .attr("class", "wedge") 
 
    .attr("d", pied_arc) 
 
    .style("fill", function (d, i) { 
 
    return pied_colors(i); 
 
}); 
 

 
// Now we'll draw our label lines, etc. 
 
enteringLabels = labels.selectAll(".label").data(pied_data).enter(); 
 
labelGroups = enteringLabels.append("g").attr("class", "label"); 
 
labelGroups.append("circle").attr({ 
 
    x: 0, 
 
    y: 0, 
 
    r: 2, 
 
    fill: "#000", 
 
    transform: function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     return "translate(" + pied_arc.centroid(d) + ")"; 
 
    }, 
 
     'class': "label-circle" 
 
}); 
 

 
// "When am I ever going to use this?" I said in 
 
// 10th grade trig. 
 
textLines = labelGroups.append("line").attr({ 
 
    x1: function (d, i) { 
 
     return pied_arc.centroid(d)[0]; 
 
    }, 
 
    y1: function (d, i) { 
 
     return pied_arc.centroid(d)[1]; 
 
    }, 
 
    x2: function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     midAngle = Math.atan2(centroid[1], centroid[0]); 
 
     x = Math.cos(midAngle) * cDim.labelRadius; 
 
     return x; 
 
    }, 
 
    y2: function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     midAngle = Math.atan2(centroid[1], centroid[0]); 
 
     y = Math.sin(midAngle) * cDim.labelRadius; 
 
     return y; 
 
    }, 
 
     'class': "label-line" 
 
}); 
 

 
textLabels = labelGroups.append("text").attr({ 
 
    x: function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     midAngle = Math.atan2(centroid[1], centroid[0]); 
 
     x = Math.cos(midAngle) * cDim.labelRadius; 
 
     sign = (x > 0) ? 1 : -1 
 
     labelX = x + (5 * sign) 
 
     return labelX; 
 
    }, 
 
    y: function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     midAngle = Math.atan2(centroid[1], centroid[0]); 
 
     y = Math.sin(midAngle) * cDim.labelRadius; 
 
     return y; 
 
    }, 
 
     'text-anchor': function (d, i) { 
 
     centroid = pied_arc.centroid(d); 
 
     midAngle = Math.atan2(centroid[1], centroid[0]); 
 
     x = Math.cos(midAngle) * cDim.labelRadius; 
 
     return (x > 0) ? "start" : "end"; 
 
    }, 
 
     'class': 'label-text' 
 
}).text(function (d) { 
 
    return d.data.label 
 
}); 
 

 
alpha = 0.5; 
 
spacing = 12; 
 

 
function relax() { 
 
    again = false; 
 
    textLabels.each(function (d, i) { 
 
     a = this; 
 
     da = d3.select(a); 
 
     y1 = da.attr("y"); 
 
     textLabels.each(function (d, j) { 
 
      b = this; 
 
      // a & b are the same element and don't collide. 
 
      if (a == b) return; 
 
      db = d3.select(b); 
 
      // a & b are on opposite sides of the chart and 
 
      // don't collide 
 
      if (da.attr("text-anchor") != db.attr("text-anchor")) return; 
 
      // Now let's calculate the distance between 
 
      // these elements. 
 
      y2 = db.attr("y"); 
 
      deltaY = y1 - y2; 
 
      
 
      // Our spacing is greater than our specified spacing, 
 
      // so they don't collide. 
 
      if (Math.abs(deltaY) > spacing) return; 
 
      
 
      // If the labels collide, we'll push each 
 
      // of the two labels up and down a little bit. 
 
      again = true; 
 
      sign = deltaY > 0 ? 1 : -1; 
 
      adjust = sign * alpha; 
 
      da.attr("y",+y1 + adjust); 
 
      db.attr("y",+y2 - adjust); 
 
     }); 
 
    }); 
 
    // Adjust our line leaders here 
 
    // so that they follow the labels. 
 
    if(again) { 
 
     labelElements = textLabels[0]; 
 
     textLines.attr("y2",function(d,i) { 
 
      labelForLine = d3.select(labelElements[i]); 
 
      return labelForLine.attr("y"); 
 
     }); 
 
     setTimeout(relax,20) 
 
    } 
 
} 
 

 
relax();
.label-text { 
 
    alignment-baseline: middle; 
 
    font-size: 12px; 
 
    font-family: arial,helvetica,"sans-serif"; 
 
    fill: #393939; 
 
} 
 
.label-line { 
 
    stroke-width: 1; 
 
    stroke: #393939; 
 
} 
 
.label-circle { 
 
    fill: #393939; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<svg> 
 
    <g id="canvas"> 
 
     <g id="art" /> 
 
     <g id="labels" /></g> 
 
</svg>

ли вы имеете в виду что-то вроде этого?

var w = 400; 
 
var h = 400; 
 
var r = h/2; 
 
var color = d3.scale.category20c(); 
 

 
var data = [{ 
 
    "label": "Category A", 
 
    "value": 20 
 
}, { 
 
    "label": "Category B", 
 
    "value": 50 
 
}, { 
 
    "label": "Category C", 
 
    "value": 30 
 
}]; 
 

 

 
var vis = d3.select('#pie').append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); 
 
var pie = d3.layout.pie().value(function(d) { 
 
    return d.value; 
 
}); 
 
var arc = d3.svg.arc().outerRadius(r); 
 
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", function(d) { 
 
    return arc(d); 
 
    }); 
 

 
// add the text 
 
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 src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="pie"> 
 

 
</div>

+0

Ну, это тоже работает. :) Тем не менее, я искал криволинейные линии, которые указывали бы на кусочек пирога и имели бы «категорию а» на одном конце :) –

+0

ой, это было не совсем понятно .. у меня будет еще один выстрел –

+0

Что-то вроде этого: http://bl.ocks.org/dbuezas/9306799 без анимации :) –

Смежные вопросы