Question

I'm currently learning d3.js, and as a task I am trying to build a line chart using a custom data source. For some reason, I can't get the line generator to work, and it seems like it can't create the d attribute for the path element. I don't seem to get any error messages either. Could someone please take a look?

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    rect.bar {
        //fill: steelblue;
    }
.axis text {
    font: 10px sans-serif;
}

.axis path, .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
}
</style>
<body>
<script src="http://d3js.org/d3.v2.js"></script>
<script>
data = [{
name:'A Negative',
data:[{x:1346103936,y:0.10252502},{x:1346190336,y:0.10838352},{x:1346276736,y:0.11182367},{x:1346363136,y:0.1469633},{x:1346449536,y:0.108044505},{x:1346535936,y:0.10141762},{x:1346622336,y:0.13505103},{x:1346708736,y:0.11661343},{x:1346795136,y:0.09985885},{x:1346881536,y:0.10367505},{x:1346967936,y:0.12067748},{x:1347054336,y:0.1329808},{x:1347140736,y:0.14677866},{x:1347227136,y:0.14087029},{x:1347313536,y:0.13160454},{x:1347399936,y:0.1313771},{x:1347486336,y:0.14144897},{x:1347572736,y:0.15051538},{x:1347659136,y:0.15604788},{x:1347745536,y:0.14364798},{x:1347831936,y:0.12961338},{x:1347918336,y:0.11450371},{x:1348004736,y:0.11712107},{x:1348091136,y:0.12876798},{x:1348177536,y:0.10429894},{x:1348263936,y:0.110398784},{x:1348350336,y:0.10483569},{x:1348436736,y:0.14220005},{x:1348523136,y:0.11701017},{x:1348609536,y:0.12221267},{x:1348696576,y:0.11133491}]},{
name:'A Positive',
data:[{x:1346105088,y:0.20869565},{x:1346191488,y:0.14895636},{x:1346277888,y:0.2819277},{x:1346364288,y:0.19342105},{x:1346450688,y:0.35833332},{x:1346537088,y:0.19473684},{x:1346623488,y:0.23015076},{x:1346709888,y:0.15840708},{x:1346796288,y:0.23293903},{x:1346882688,y:0.21885246},{x:1346969088,y:0.22707888},{x:1347055488,y:0.26593626},{x:1347141888,y:0.22822087},{x:1347228288,y:0.24236642},{x:1347314688,y:0.17460318},{x:1347401088,y:0.19075145},{x:1347487488,y:0.1594203},{x:1347573888,y:0.13432837},{x:1347660288,y:0.0},{x:1347746688,y:0.18100129},{x:1347833088,y:0.1605938},{x:1347919488,y:0.12987013},{x:1348005888,y:0.12683824},{x:1348092288,y:0.15542522},{x:1348178688,y:0.13584906},{x:1348265088,y:0.14351852},{x:1348351488,y:0.1322314},{x:1348437888,y:0.13709678},{x:1348524288,y:0.17438692},{x:1348610688,y:0.0},{x:1348700160,y:0.18169399}]},{
name:'A Uncertain',
data:[{x:1346104576,y:0.04397342},{x:1346190976,y:0.044665344},{x:1346277376,y:0.049782943},{x:1346363776,y:0.051038638},{x:1346450176,y:0.050243802},{x:1346536576,y:0.03118218},{x:1346622976,y:0.04424348},{x:1346709376,y:0.04498049},{x:1346795776,y:0.04105231},{x:1346882176,y:0.04970384},{x:1346968576,y:0.045589853},{x:1347054976,y:0.046243627},{x:1347141376,y:0.05226451},{x:1347227776,y:0.047814183},{x:1347314176,y:0.04413969},{x:1347400576,y:0.03914877},{x:1347486976,y:0.042237047},{x:1347573376,y:0.054126237},{x:1347659776,y:0.04697353},{x:1347746176,y:0.04476943},{x:1347832576,y:0.042521983},{x:1347918976,y:0.05310476},{x:1348005376,y:0.059566505},{x:1348091776,y:0.043783925},{x:1348178176,y:0.043761015},{x:1348264576,y:0.046513315},{x:1348350976,y:0.0384231},{x:1348437376,y:0.04024283},{x:1348523776,y:0.040613018},{x:1348610176,y:0.04732518},{x:1348696576,y:0.06337391}]},{
name:'A Positive',
data:[{x:1346104320,y:0.109645985},{x:1346190720,y:0.092952825},{x:1346277120,y:0.10988262},{x:1346363520,y:0.12258253},{x:1346449920,y:0.12162819},{x:1346536320,y:0.11145041},{x:1346622720,y:0.17937773},{x:1346709120,y:0.1605882},{x:1346795520,y:0.15555955},{x:1346881920,y:0.15066825},{x:1346968320,y:0.17311412},{x:1347054720,y:0.21528025},{x:1347141120,y:0.20169735},{x:1347227520,y:0.15779452},{x:1347313920,y:0.1469917},{x:1347400320,y:0.15995567},{x:1347486720,y:0.17675863},{x:1347573120,y:0.14658852},{x:1347659520,y:0.2049946},{x:1347745920,y:0.15699232},{x:1347832320,y:0.14301357},{x:1347918720,y:0.1457654},{x:1348005120,y:0.1532571},{x:1348091520,y:0.17817244},{x:1348177920,y:0.13126957},{x:1348264320,y:0.12135763},{x:1348350720,y:0.14930858},{x:1348437120,y:0.14171022},{x:1348523520,y:0.12027296},{x:1348609920,y:0.13843122},{x:1348696576,y:0.15421592}]},{
name:'A Uncertain',
data:[{x:1346103936,y:0.046369042},{x:1346190336,y:0.042160377},{x:1346276736,y:0.06631727},{x:1346363136,y:0.043078776},{x:1346449536,y:0.049522486},{x:1346535936,y:0.041241966},{x:1346622336,y:0.041665666},{x:1346708736,y:0.0461979},{x:1346795136,y:0.044713285},{x:1346881536,y:0.041361943},{x:1346967936,y:0.051421918},{x:1347054336,y:0.04684727},{x:1347140736,y:0.048165746},{x:1347227136,y:0.053684916},{x:1347313536,y:0.05550549},{x:1347399936,y:0.05435959},{x:1347486336,y:0.04710294},{x:1347572736,y:0.05433203},{x:1347659136,y:0.06015368},{x:1347745536,y:0.047590178},{x:1347831936,y:0.045565397},{x:1347918336,y:0.056516618},{x:1348004736,y:0.06080917},{x:1348091136,y:0.068452686},{x:1348177536,y:0.049881306},{x:1348263936,y:0.04221391},{x:1348350336,y:0.0484556},{x:1348436736,y:0.0402809},{x:1348523136,y:0.058744337},{x:1348609536,y:0.054147776},{x:1348696576,y:0.056016088}]},{
name:'A Negative',
data:[{x:1346104832,y:0.25386313},{x:1346191232,y:0.14606741},{x:1346277632,y:0.17222223},{x:1346364032,y:0.19863014},{x:1346450432,y:0.17857143},{x:1346536832,y:0.14606741},{x:1346623232,y:0.12448133},{x:1346709632,y:0.12931034},{x:1346796032,y:0.25714287},{x:1346882432,y:0.22222222},{x:1346968832,y:0.1764706},{x:1347055232,y:0.28846154},{x:1347141632,y:0.1826923},{x:1347228032,y:0.2236842},{x:1347314432,y:0.091836736},{x:1347400832,y:0.25},{x:1347487232,y:0.17567568},{x:1347573632,y:0.15384616},{x:1347660032,y:0.0},{x:1347746432,y:0.23584905},{x:1347832832,y:0.13718411},{x:1347919232,y:0.0},{x:1348005632,y:0.13533835},{x:1348092032,y:0.0},{x:1348178432,y:0.06315789},{x:1348264832,y:0.0},{x:1348351232,y:0.14457831},{x:1348437632,y:0.13253012},{x:1348524032,y:0.1},{x:1348610432,y:0.0},{x:1348700160,y:0.29826254}]}];


var x = d3.scale.linear()
        .range([0, "100%"])
        .domain(d3.extent(data[0].data, function(d) { return d.x }));

var y = d3.scale.linear()
        .domain([0, d3.max(data[0].data, function(d) { return d.y; })])
        .range([0, "100%"]);



var line = d3.svg.line()
        .x(function(d) { return x(d.x)})
        .y(function(d) { return y(d.y)})
        .interpolate("basis");

var svg = d3.select("body").append("svg")
            .attr("width", "100%")
            .attr("height", "500px");

var colors = d3.scale.category20().range();

var group = svg.selectAll("g").data(data);

group.enter().append("g")
        .attr("fill", function(d, i) { return colors[i % colors.length]; })
        .attr("opacity", "0.5").attr("stroke", "black").attr("stroke-width", "2");

group.selectAll("path")
        .data(function(d) {return d.data})
    .enter().append("path")
        .attr("d", line)
        .attr("class", "line");



</script>
Was it helpful?

Solution

I see a couple problems. The first is that the width and height attributes of SVG elements should be specified as unit-less numbers—always in pixels. This defines the coordinate space of the SVG element as well as its size on-screen. You can also set width and height style properties using px or percentages, but you should only do this in addition to setting the width and height attributes. The typical pattern is:

var width = 960,
    height = 500;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

You might also want to look at the margin conventions example for more information.

The second thing I would change is to use this coordinate space to set the range of your scales, rather than using the percentage positioning:

var x = d3.scale.linear()
    .domain(…)
    .range([0, width]);

var y = d3.scale.linear()
    .domain(…)
    .range([height, 0]);

Note that the y-scale's range is inverted, so that y-0 is at the bottom of the chart rather than the default top. Again, see the conventions example for details.

Lastly, it looks like your x-values are seconds since UNIX epoch, so I would recommend converting your data to Date objects and then using a d3.time.scale. This makes it much easier to add an x-axis with date labels in the future. You can convert to dates as a preprocessing step like so:

data.forEach(function(series) {
  series.data.forEach(function(d) {
    d.x = new Date(d.x * 1000);
  });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top