d3.js brush with multiline chart -


i'm making multi-line chart , using brush select time periods. it's broadly based on mike bostock's example @ http://bl.ocks.org/mbostock/1667367

my chart @ http://lowercasen.com/dev/d3/general/piezobrush.html

my problem in selecting multiple lines in 'focus' area apply brush to. i've nested data based on key, data within function. because function calls brush outside function, can't access data , i'm getting typeerror: undefined not object (evaluating 'data.length')

here's code nests data:

     datanest.foreach(function(d, i) {         focus.append("path")            .attr("class", "line")                  .attr("id", d.key.replace(/\s+/g, ''))  //the replace stuff getting rid of spaces                  .attr("d", levelfocus(d.values));          context.append("path")             .attr("class", "line")                  .attr("id", d.key.replace(/\s+/g, ''))  //the replace stuff getting rid of spaces                  .attr("d", levelcontext(d.values));  

and @ bottom have function brush:

     function brushed() {        xfocus.domain(brush.empty() ? xcontext.domain() : brush.extent());        focus.selectall(".line").attr("d", levelfocus(d.values));        focus.select(".x.axis").call(xaxisfocus);      } 

it works fine x axis (if comment out line i'm trying select lines) don't know how select lines correctly.

apologies garbled syntax or confusing language, coding skills basic @ best.

any appreciated, i've searched hours solution.

here's full code requested lars

    <!doctype html>     <html lang="en">     <head>             <meta charset="utf-8">             <title>multiline brush</title>     <script src="http://d3js.org/d3.v3.js"></script>     <script src="d3/tooltip.js"></script>         <link href="styles/evidentlysocharts.css" rel="stylesheet">         <meta name="viewport" content="initial-scale=1">         <style>      svg {       font: 10px sans-serif;     }      path {          stroke-width: 1;         fill: none;     }      #stream1, #nebo1d {         stroke: #009390;     }      #stream1legend, #nebo1dlegend {         fill: #009390;     }      #stream2, #nebo2d {         stroke: #8dc63f;     }      #stream2legend, #nebo2dlegend {         fill: #8dc63f;     }      #stream3, #nebo1s {         stroke: #132d46;     }      #stream3legend, #nebo1slegend {         fill: #132d46;     }      #stream4, #nebo2s {         stroke: #aaa813;     }      #stream4legend, #nebo2slegend {         fill: #aaa813;     }      #stream5, #nebo3 {         stroke: #619dd4;     }      #stream5legend, #nebo3legend {         fill: #619dd4;     }      .pn1d, .pn2d {       fill: none;       clip-path: url(#clip);     }      .pn1d {       stroke: #009390;     }      .pn2d {       stroke: #1b4164;     }      .axis path,     .axis line {       fill: none;       stroke: #000;       stroke-width: 1px;       shape-rendering: crispedges;     }      .brush .extent {       stroke: #fff;       fill-opacity: .125;       shape-rendering: crispedges;     }      </style>         </head>        <body>     <script>      var marginfocus = {top: 10, right: 10, bottom: 250, left: 40},         margincontext = {top: 430, right: 10, bottom: 170, left: 40},         width = 960 - marginfocus.left - marginfocus.right,         heightfocus = 650 - marginfocus.top - marginfocus.bottom,         heightcontext = 650 - margincontext.top - margincontext.bottom;         legendoffset = 550;      var parsedate = d3.time.format("%d/%m/%y %h:%m").parse;      var xfocus = d3.time.scale().range([0, width]),         xcontext = d3.time.scale().range([0, width]),         yfocus = d3.scale.linear().range([heightfocus, 0]),         ycontext = d3.scale.linear().range([heightcontext, 0]);      var xaxisfocus = d3.svg.axis().scale(xfocus).orient("bottom"),         xaxiscontext = d3.svg.axis().scale(xcontext).orient("bottom"),         yaxisfocus = d3.svg.axis().scale(yfocus).orient("left");      var levelfocus = d3.svg.line()         .interpolate("linear")         .x(function(d) { return xfocus(d.date); })         .y(function(d) { return yfocus(d.level); });       var levelcontext = d3.svg.line()         .interpolate("linear")         .x(function(d) { return xcontext(d.date); })         .y(function(d) { return ycontext(d.level); });      var svg = d3.select("body").append("svg")         .attr("width", width + marginfocus.left + marginfocus.right)         .attr("height", heightfocus + marginfocus.top + marginfocus.bottom);      svg.append("defs").append("clippath")         .attr("id", "clip")       .append("rect")         .attr("width", width)         .attr("height", heightfocus);      var focus = svg.append("g")         .attr("class", "focus")         .attr("transform", "translate(" + marginfocus.left + "," + marginfocus.top + ")");      var context = svg.append("g")         .attr("class", "context")         .attr("transform", "translate(" + margincontext.left + "," + margincontext.top + ")");      d3.csv("data/piezonebonestsimple.csv", function(error, data) {         data.foreach(function(d) {         d.date = parsedate(d.date);         d.level = +d.level;         });        xfocus.domain(d3.extent(data.map(function(d) { return d.date; })));       yfocus.domain([d3.min(data.map(function(d) { return d.level; })) -2,0]);       xcontext.domain(xfocus.domain());       ycontext.domain(yfocus.domain());          // nest entries piezo         var datanest = d3.nest()             .key(function(d) {return d.piezo;})             .entries(data);          legendspace = width/datanest.length; // spacing legend // ******      var brush = d3.svg.brush()         .x(xcontext)         .on("brush", brushed);       focus.selectall("g").data(datanest)         .enter()         .append("g")         .attr("class", "line")         .attr("id", function(d) { return d.key.replace(/\s+/g, '') })  //the replace stuff getting rid of spaces         .append("path")         .attr("d", function(d) { return levelfocus(d.values); });          context.selectall("g").data(datanest)         .enter()         .append("g")         .attr("class", "line")         .attr("id", function(d) { return d.key.replace(/\s+/g, '') })  //the replace stuff getting rid of spaces         .append("path")         .attr("d", function(d) { return levelcontext(d.values); });             focus.append("g")           .attr("class", "x axis")           .attr("transform", "translate(0," + heightfocus + ")")           .call(xaxisfocus);        focus.append("g")           .attr("class", "y axis")           .call(yaxisfocus);        context.append("g")           .attr("class", "x axis")           .attr("transform", "translate(0," + heightcontext + ")")           .call(xaxiscontext);        context.append("g")           .attr("class", "x brush")           .call(brush)         .selectall("rect")           .attr("y", -6)           .attr("height", heightcontext + 7);      function brushed() {       xfocus.domain(brush.empty() ? xcontext.domain() : brush.extent());       focus.selectall(".line").attr("d", levelfocus(datanest.values));       focus.select(".x.axis").call(xaxisfocus);     }      });       </script>     </body>     </html> 

it boils down 2 things far can see. first, elements you're selecting updated g , not path elements , second, need reference data bound elements in order set d. both fixed , brushed function looks this.

function brushed() {    xfocus.domain(brush.empty() ? xcontext.domain() : brush.extent());    focus.selectall("path").attr("d", function(d) { return levelfocus(d.values); });    focus.select(".x.axis").call(xaxisfocus); } 

complete demo here. note bits still missing, in particular clip path restrict lines chart area. can copied , pasted directly example you've referenced though.


Comments

Popular posts from this blog

ruby on rails - RuntimeError: Circular dependency detected while autoloading constant - ActiveAdmin.register Role -

c++ - OpenMP unpredictable overhead -

javascript - Wordpress slider, not displayed 100% width -