2016-03-09 74 views
0

我想繪製一個折線圖,其中兩行繪製,一行顯示在今天的日期之前,另一行顯示在今天的日期之後,我正在使用D3的剪輯路徑,用戶可以點擊按鈕來更新圖表。這部分工作,但當我試圖讓代碼可重用,因爲我想第一個下面的第二個圖表,當我將第二個容器傳遞給相同的圖表函數(即圖表1的#graph1和圖表2的#graph2)它只繪製軸線但不繪製第二個圖形的線條(第一個圖形仍然有效),有人能讓我指向正確的方向嗎?謝謝。 下面是我的代碼:第二次調用D3可重複使用的折線圖只繪製座標軸,但不繪製直線

function chart(selection) { 
     selection.each(function(data) { 

     var svg = d3.select(this).selectAll("svg").data([data]); 

     // Update the outer dimensions. 
     svg.attr("width", width) 
      .attr("height", height); 

     // Update the inner dimensions. 
     var g = svg.select("g") 
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

     if(alreadyClicked==true){ 

     svg.select("#clip-before rect") 
     .transition().duration(400) 
     .attr("width", xScale(parsedate(today))) 
     .attr("height", height- margin.top - margin.bottom); 

     svg.select("#clip-after rect") 
     .transition().duration(400) 
     .attr("x", xScale(parsedate(today))) 
     .attr("width", width-xScale(parsedate(today))) 
     .attr("height", height- margin.top - margin.bottom); 

     svg.selectAll("path.line-after") 
     .data(data).transition() 
     .duration(400).attr("d", line_after(data)); 

     svg.selectAll("path.line-before") 
     .data(data).transition() 
     .duration(400).attr("d", line_before(data)); 


     }else{ 
     g.append("clipPath") 
       .attr("id", "clip-before") 
       .append("rect") 
       .attr("width", xScale(parsedate(today))) 
       .attr("height", height- margin.top - margin.bottom); 

     g.append("clipPath") 
       .attr("id", "clip-after") 
       .append("rect") 
       .attr("x", xScale(parsedate(today))) 
       .attr("width", width-xScale(parsedate(today))) 
       .attr("height", height- margin.top - margin.bottom); 

     g.selectAll(".line") 
       .data(["after"]) 
       .enter().append("path") 
       .attr("class", function(d) { return "line-" + d; }) 
       .attr("clip-path", function(d) { return "url(#clip-" + d + ")"; }) 
       .attr("d", line_after(data)); 

     g.selectAll(".line") 
       .data(["before"]) 
       .enter().append("path") 
       .attr("class", function(d) { return "line-" + d; }) 
       .attr("clip-path", function(d) { return "url(#clip-" + d + ")"; }) 
       .attr("d", line_before(data)); 


     } 





    // Add the X Axis 
     g.append("g") 
      .attr("class", "x axis"); 


     svg.select(".x.axis") 
      .attr("transform", "translate(0,300)").transition().duration(400).call(xAxis); 

     g.selectAll(".x.axis text") // select all the text elements for the xaxis 
      .attr("transform", function(d) { 
      return "translate(" + this.getBBox().height*-2 + "," + this.getBBox().height + ")rotate(-45)"; 
     }); 

     // Add the Y Axis 
     g.append("g") 
      .attr("class", "y axis"); 

     svg.select(".y.axis").transition().duration(400).call(yAxis); 


    }); //end selection.each 
}//end chart 
+0

你可以在[jsFiddle](http://jsfiddle.net)或[Plunkr](http://plnkr.co)或在這裏的內聯代碼示例中重現此問題嗎?這將有助於我們嘗試解決問題。例如,我懷疑這是與id有關,但我無法確定如果沒有玩它看。 – GregL

+0

我的代碼在github上好嗎?因爲我已經有一個回購。這裏是:http://jhjanicki.github.io/reusable-line-chart/,這裏是代碼https://github.com/jhjanicki/reusable-line-chart謝謝! – jhjanicki

+0

你的代碼中有很少的bug,這些都會產生這種噪音。我們必須以可重用的方式更改/編寫代碼。如果你有興趣,那麼我們會解釋什麼是錯的。 :D –

回答

0

/** 
 
* PredictGraph code start 
 
*/ 
 
(function() { 
 
\t d3.PredictGraph = function() { 
 
    \t // OPTIONS 
 
\t // (manipulated with getters and setters below) 
 
\t var margin = {top: 50, right: 20, bottom: 100, left: 60}, 
 
\t \t width = getWidth($(window).width()), 
 
\t \t height = 450, 
 
\t \t xValue = function(d) { return d.date; }, 
 
\t \t yValue = function(d) { return d.actualvalue; }, 
 
\t \t yValue2= function(d) { return d.predictedvalue;}, 
 
\t \t xScale = d3.time.scale().range([0, width]), 
 
\t \t yScale = d3.scale.linear().range([height, 0]), 
 
\t \t xAxis = xAxis = d3.svg.axis().scale(xScale) 
 
\t \t \t .orient("bottom").ticks(10).tickFormat(d3.time.format("%Y-%m-%d")), //this is where the date is formatted for the axis, 
 
\t \t yAxis = d3.svg.axis().scale(yScale) 
 
\t \t \t .orient("left").ticks(10), 
 
\t \t line = d3.svg.line().x(X).y(Y), 
 
\t \t line_before= d3.svg.line() 
 
\t \t \t \t .x(function(d) { return xScale(d.date);}) 
 
\t \t \t \t .y(function(d) { return yScale(d.actualvalue); 
 
\t \t \t \t \t \t \t }), 
 
\t \t line_after= d3.svg.line() 
 
\t \t \t \t .x(function(d) { return xScale(d.date);}) 
 
\t \t \t \t .y(function(d) { return yScale(d.predictedvalue);}) 
 
\t \t today= moment()._d, //date object 
 
\t \t formatDate = d3.time.format("%Y-%m-%d"), 
 
\t \t todayFormatted = formatDate(moment()._d), 
 
\t \t alreadyClicked=false; 
 
\t function chart(selection) { 
 
\t \t selection.each(function(data) { 
 
\t \t console.log(this); 
 
\t \t var max_actual = d3.max(data, function(d) { return d.actualvalue;}); //before 
 
\t \t var max_predicted = d3.max(data, function(d) { return d.predictedvalue;}); //after 
 
\t \t var max = Math.max(max_actual, max_predicted); //overall 
 
\t \t var min_actual = d3.min(data, function(d) { return d.actualvalue;}); //before 
 
\t \t var min_predicted = d3.min(data, function(d) { return d.predictedvalue;}); //after 
 
\t \t var min = Math.min(min_actual, min_predicted); \t \t \t 
 
\t \t var parsedate = d3.time.format("%Y-%m-%d").parse; \t \t 
 
\t \t // to convert date from a formated string into a date object 
 
\t \t \t data.forEach(function(d) {d.date = parsedate(d.date);}); \t \t \t 
 
\t \t // Update the x-scale. 
 
\t \t xScale.domain(d3.extent(data, function(d) { return d.date; })).range([0, width- margin.left - margin.right]); 
 
\t \t // Update the y-scale. 
 
\t \t yScale.domain([min,max]).range([height- margin.top - margin.bottom,0]); 
 
\t \t // Select the svg element, if it exists. 
 
\t \t var svg = d3.select(this).selectAll("svg").data([data]); 
 
\t \t //Otherwise, create the skeletal chart. 
 
\t \t var gEnter = svg.enter().append("svg").append("g"); 
 
\t \t // Update the outer dimensions. 
 
\t \t svg.attr("width", width).attr("height", height); 
 
\t \t // Update the inner dimensions. 
 
\t \t var g = svg.select("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); \t \t 
 
\t \t console.log(svg.select("#clip-before"+this.id)); 
 
      var currNode=this; \t \t \t \t 
 
\t \t if(svg.select("#clip-before"+this.id)[0][0]!=null){ \t \t \t 
 
\t \t  svg.select("#clip-before"+this.id+" rect") 
 
\t \t  .transition().duration(400) 
 
\t \t  .attr("width", xScale(parsedate(today))) 
 
\t \t \t .attr("height", height- margin.top - margin.bottom); 
 
\t \t \t 
 
\t \t \t svg.select("#clip-after"+this.id+" rect") 
 
\t \t  .transition().duration(400) 
 
\t \t  .attr("x", xScale(parsedate(today))) 
 
\t \t  .attr("width", width-xScale(parsedate(today))) 
 
\t \t \t .attr("height", height- margin.top - margin.bottom); 
 
\t \t \t 
 
\t \t \t svg.selectAll("path.line-after") 
 
\t \t \t .data(data).transition() 
 
      .duration(400).attr("d", line_after(data)); 
 
       
 
      svg.selectAll("path.line-before") 
 
\t \t \t .data(data).transition() 
 
      .duration(400).attr("d", line_before(data)); 
 
       
 
      svg.select("line.today") 
 
\t \t  .transition().duration(400) 
 
\t \t  .attr({'x1': xScale(parsedate(today)),'y1': 0,'x2': xScale(parsedate(today)),'y2': height- margin.top - margin.bottom}) 
 
\t \t \t \t .style("stroke", "#FF7F66") 
 
\t \t \t \t .style("stroke-dasharray", ("3, 3")) 
 
\t \t \t \t .style("fill", "none"); \t    
 
\t \t }else{ 
 
\t \t \t g.append("clipPath") 
 
\t \t \t \t .attr("id", "clip-before"+this.id) 
 
\t \t \t \t .append("rect") 
 
\t \t \t \t .attr("width", xScale(parsedate(today))) 
 
\t \t \t \t .attr("height", height- margin.top - margin.bottom); 
 
\t \t \t \t 
 
\t \t \t g.append("clipPath") 
 
\t \t \t \t .attr("id", "clip-after"+this.id) 
 
\t \t \t \t .append("rect") 
 
\t \t \t \t .attr("x", xScale(parsedate(today))) 
 
\t \t \t \t .attr("width", width-xScale(parsedate(today))) 
 
\t \t \t \t .attr("height", height- margin.top - margin.bottom); 
 
\t \t \t \t 
 
\t \t \t g.selectAll(".line") 
 
\t \t \t \t .data(["after"]) 
 
\t \t \t \t .enter().append("path") 
 
\t \t \t \t .attr("class", function(d) { return "line-" + d; }) 
 
\t \t \t \t .attr("clip-path", function(d) { return "url(#clip-"+d+currNode.id+")"; }) 
 
\t \t \t \t .attr("d", line_after(data)); 
 
\t \t \t \t 
 
\t \t \t g.selectAll(".line") 
 
\t \t \t \t .data(["before"]) 
 
\t \t \t \t .enter().append("path") 
 
\t \t \t \t .attr("class", function(d) { return "line-" + d; }) 
 
\t \t \t \t .attr("clip-path", function(d) { return "url(#clip-"+d+currNode.id+")"; }) 
 
\t \t \t \t .attr("d", line_before(data)); 
 
\t \t \t \t 
 
\t \t \t g.append("line") 
 
\t \t \t \t .attr("class","today") 
 
\t \t \t \t .attr({ 
 
\t \t \t \t \t 'x1': xScale(parsedate(today)), 
 
\t \t \t \t \t 'y1': 0, 
 
\t \t \t \t \t 'x2': xScale(parsedate(today)), 
 
\t \t \t \t \t 'y2': height- margin.top - margin.bottom 
 
\t \t \t \t }) 
 
\t \t \t \t .style("stroke", "#FF7F66") 
 
\t \t \t \t .style("stroke-dasharray", ("3, 3")) 
 
\t \t \t \t .style("fill", "none"); \t \t \t 
 
\t \t } 
 
\t \t // Add the X Axis 
 
\t \t g.append("g") 
 
\t \t \t \t .attr("class", "x axis"); 
 
\t \t \t \t //.call(xAxis); 
 
\t \t \t \t 
 
\t \t svg.select(".x.axis") 
 
    \t \t \t \t .attr("transform", "translate(0,300)").transition().duration(400).call(xAxis); 
 
    \t \t   
 
\t \t g.selectAll(".x.axis text") // select all the text elements for the xaxis 
 
\t \t \t .attr("transform", function(d) { 
 
\t \t \t \t return "translate(" + this.getBBox().height*-2 + "," + this.getBBox().height + ")rotate(-45)"; 
 
\t \t \t }); 
 

 
\t \t // Add the Y Axis 
 
\t \t g.append("g") 
 
    \t \t \t \t .attr("class", "y axis"); //.call(yAxis) 
 
\t \t \t 
 
\t \t svg.select(".y.axis").transition().duration(400).call(yAxis); \t \t 
 
\t  alreadyClicked = true; 
 
\t \t }); 
 
\t } 
 

 
\t // The x-accessor for the path generator; xScale ∘ xValue. 
 
\t function X(d) { 
 
\t \t return xScale(formatDate.parse(d.date)); 
 
\t } 
 

 
\t // The y-accessor for the path generator; yScale ∘ yValue. 
 
\t function Y(d) { 
 
\t \t return yScale(d.actualvalue); 
 
\t } 
 
    
 
\t function Y2(d){ 
 
\t \t return yScale(d.predictedvalue); 
 
\t } 
 

 
\t chart.margin = function(_) { 
 
\t \t if (!arguments.length) return margin; 
 
\t \t margin = _; 
 
\t \t return chart; 
 
\t }; 
 

 
\t chart.width = function(_) { 
 
\t \t if (!arguments.length) return width; 
 
\t \t width = _; 
 
\t \t return chart; 
 
\t }; 
 

 
\t chart.height = function(_) { 
 
\t \t if (!arguments.length) return height; 
 
\t \t height = _; 
 
\t \t return chart; 
 
\t }; 
 

 
\t chart.x = function(_) { 
 
\t \t if (!arguments.length) return xValue; 
 
\t \t xValue = _; 
 
\t \t return chart; 
 
\t }; 
 

 
\t chart.y = function(_) { 
 
\t \t if (!arguments.length) return yValue; 
 
\t \t yValue = _; 
 
\t \t return chart; 
 
\t }; 
 
\t function getWidth(width){ 
 
\t 
 
\t \t \t if (width > 1500 || width < 990) { 
 
\t \t \t \t return 800; 
 
\t \t \t }else if (width > 1300 && width > 990){ 
 
\t \t \t \t return 700; 
 
\t \t \t }else{ 
 
\t \t \t \t return 650; 
 
\t \t \t } 
 
\t \t } 
 
\t return chart; 
 
\t }; 
 
})(); 
 

 
/*PredictGraph code end*/ 
 

 

 
/*app.js code start*/ 
 

 
\t \t var chart = d3.PredictGraph(); \t 
 
\t \t //Global Variables 
 
\t \t 
 
\t \t var formatDate = d3.time.format("%Y-%m-%d"); 
 
\t \t var today = formatDate(moment()._d) || "2016-01-01"; 
 
\t \t var first_day = formatDate(getFirstDay()) || "2015-01-01"; 
 
\t \t var numMonths = "three"; //one, three, six, twelve 
 
\t \t var last_day = formatDate(getLastDay(numMonths)) || "2016-04-01"; 
 
\t \t var product = "product1"; 
 
\t \t var loaded = false; 
 
\t \t // called everytime a user clicks on a month button or select a dropdown menu item 
 
\t \t // input params: the firstDay (today minus 12 months), lastDay (pass value retrieved from numMonths into getLastDay) 
 
\t \t // \t \t \t \t productSelected (selected product based on dropdown menu value) 
 
\t \t function updateResults(firstDay, lastDay, productSelected){ 
 
\t \t 
 
\t \t \t //get data... will get from Django eventually instead of json file 
 
\t \t \t //d3.json("data/data.json",function(data){ \t 
 
      var data=[{"date":"2015-01-01","productname":"product1","actualvalue":512,"predictedvalue":05},{"date":"2015-02-01","productname":"product1","actualvalue":311,"predictedvalue":426},{"date":"2015-03-01","productname":"product1","actualvalue":305,"predictedvalue":725},{"date":"2015-04-01","productname":"product1","actualvalue":396,"predictedvalue":887},{"date":"2015-05-01","productname":"product1","actualvalue":70,"predictedvalue":299},{"date":"2015-06-01","productname":"product1","actualvalue":32,"predictedvalue":40},{"date":"2015-07-01","productname":"product1","actualvalue":157,"predictedvalue":504},{"date":"2015-08-01","productname":"product1","actualvalue":335,"predictedvalue":372},{"date":"2015-09-01","productname":"product1","actualvalue":426,"predictedvalue":899},{"date":"2015-10-01","productname":"product1","actualvalue":983,"predictedvalue":842},{"date":"2015-11-01","productname":"product1","actualvalue":701,"predictedvalue":569},{"date":"2015-12-01","productname":"product1","actualvalue":674,"predictedvalue":387},{"date":"2016-01-01","productname":"product1","actualvalue":986,"predictedvalue":65},{"date":"2016-02-01","productname":"product1","actualvalue":426,"predictedvalue":49},{"date":"2016-03-01","productname":"product1","actualvalue":130,"predictedvalue":63},{"date":"2016-04-01","productname":"product1","actualvalue":674,"predictedvalue":889},{"date":"2016-05-01","productname":"product1","actualvalue":192,"predictedvalue":983},{"date":"2016-06-01","productname":"product1","actualvalue":6,"predictedvalue":186},{"date":"2016-07-01","productname":"product1","actualvalue":476,"predictedvalue":181},{"date":"2016-08-01","productname":"product1","actualvalue":493,"predictedvalue":544},{"date":"2016-09-01","productname":"product1","actualvalue":121,"predictedvalue":792},{"date":"2016-10-01","productname":"product1","actualvalue":745,"predictedvalue":712},{"date":"2016-11-01","productname":"product1","actualvalue":755,"predictedvalue":46},{"date":"2016-12-01","productname":"product1","actualvalue":361,"predictedvalue":810},{"date":"2015-01-01","productname":"product2","actualvalue":675,"predictedvalue":722},{"date":"2015-02-01","productname":"product2","actualvalue":690,"predictedvalue":388},{"date":"2015-03-01","productname":"product2","actualvalue":994,"predictedvalue":871},{"date":"2015-04-01","productname":"product2","actualvalue":678,"predictedvalue":656},{"date":"2015-05-01","productname":"product2","actualvalue":901,"predictedvalue":216},{"date":"2015-06-01","productname":"product2","actualvalue":304,"predictedvalue":491},{"date":"2015-07-01","productname":"product2","actualvalue":223,"predictedvalue":360},{"date":"2015-08-01","productname":"product2","actualvalue":299,"predictedvalue":487},{"date":"2015-09-01","productname":"product2","actualvalue":80,"predictedvalue":267},{"date":"2015-10-01","productname":"product2","actualvalue":760,"predictedvalue":830},{"date":"2015-11-01","productname":"product2","actualvalue":122,"predictedvalue":273},{"date":"2015-12-01","productname":"product2","actualvalue":859,"predictedvalue":258},{"date":"2016-01-01","productname":"product2","actualvalue":807,"predictedvalue":729},{"date":"2016-02-01","productname":"product2","actualvalue":82,"predictedvalue":939},{"date":"2016-03-01","productname":"product2","actualvalue":72,"predictedvalue":348},{"date":"2016-04-01","productname":"product2","actualvalue":544,"predictedvalue":429},{"date":"2016-05-01","productname":"product2","actualvalue":512,"predictedvalue":562},{"date":"2016-06-01","productname":"product2","actualvalue":510,"predictedvalue":800},{"date":"2016-07-01","productname":"product2","actualvalue":283,"predictedvalue":847},{"date":"2016-08-01","productname":"product2","actualvalue":172,"predictedvalue":343},{"date":"2016-09-01","productname":"product2","actualvalue":315,"predictedvalue":633},{"date":"2016-10-01","productname":"product2","actualvalue":863,"predictedvalue":184},{"date":"2016-11-01","productname":"product2","actualvalue":125,"predictedvalue":623},{"date":"2016-12-01","productname":"product2","actualvalue":400,"predictedvalue":920}]; 
 
\t \t \t \t // get data between first and last day and for the selected product 
 
\t \t \t \t // draw a single line as a test 
 
\t \t \t \t var test_data = data.filter(function(el){ 
 
\t \t \t \t \t return el.date < lastDay && el.date > firstDay && el.productname == productSelected 
 
\t \t \t \t }); 
 
\t \t \t d3.select("#graph1").datum(test_data).call(chart); 
 
\t \t \t //}); 
 
\t \t } 
 
\t \t 
 
\t \t function updateResults2(firstDay, lastDay, productSelected){ 
 
\t \t \t //get data... will get from Django eventually instead of json file 
 
\t \t \t //d3.json("data/data.json",function(data){ 
 
\t \t var data=[{"date":"2015-01-01","productname":"product1","actualvalue":512,"predictedvalue":805},{"date":"2015-02-01","productname":"product1","actualvalue":311,"predictedvalue":426},{"date":"2015-03-01","productname":"product1","actualvalue":305,"predictedvalue":725},{"date":"2015-04-01","productname":"product1","actualvalue":396,"predictedvalue":887},{"date":"2015-05-01","productname":"product1","actualvalue":70,"predictedvalue":299},{"date":"2015-06-01","productname":"product1","actualvalue":32,"predictedvalue":40},{"date":"2015-07-01","productname":"product1","actualvalue":157,"predictedvalue":504},{"date":"2015-08-01","productname":"product1","actualvalue":335,"predictedvalue":372},{"date":"2015-09-01","productname":"product1","actualvalue":426,"predictedvalue":899},{"date":"2015-10-01","productname":"product1","actualvalue":983,"predictedvalue":842},{"date":"2015-11-01","productname":"product1","actualvalue":701,"predictedvalue":569},{"date":"2015-12-01","productname":"product1","actualvalue":674,"predictedvalue":387},{"date":"2016-01-01","productname":"product1","actualvalue":986,"predictedvalue":65},{"date":"2016-02-01","productname":"product1","actualvalue":426,"predictedvalue":49},{"date":"2016-03-01","productname":"product1","actualvalue":130,"predictedvalue":63},{"date":"2016-04-01","productname":"product1","actualvalue":674,"predictedvalue":889},{"date":"2016-05-01","productname":"product1","actualvalue":192,"predictedvalue":983},{"date":"2016-06-01","productname":"product1","actualvalue":6,"predictedvalue":186},{"date":"2016-07-01","productname":"product1","actualvalue":476,"predictedvalue":181},{"date":"2016-08-01","productname":"product1","actualvalue":493,"predictedvalue":544},{"date":"2016-09-01","productname":"product1","actualvalue":121,"predictedvalue":792},{"date":"2016-10-01","productname":"product1","actualvalue":745,"predictedvalue":712},{"date":"2016-11-01","productname":"product1","actualvalue":755,"predictedvalue":46},{"date":"2016-12-01","productname":"product1","actualvalue":361,"predictedvalue":810},{"date":"2015-01-01","productname":"product2","actualvalue":675,"predictedvalue":722},{"date":"2015-02-01","productname":"product2","actualvalue":690,"predictedvalue":388},{"date":"2015-03-01","productname":"product2","actualvalue":994,"predictedvalue":871},{"date":"2015-04-01","productname":"product2","actualvalue":678,"predictedvalue":656},{"date":"2015-05-01","productname":"product2","actualvalue":901,"predictedvalue":216},{"date":"2015-06-01","productname":"product2","actualvalue":304,"predictedvalue":491},{"date":"2015-07-01","productname":"product2","actualvalue":223,"predictedvalue":360},{"date":"2015-08-01","productname":"product2","actualvalue":299,"predictedvalue":487},{"date":"2015-09-01","productname":"product2","actualvalue":80,"predictedvalue":267},{"date":"2015-10-01","productname":"product2","actualvalue":760,"predictedvalue":830},{"date":"2015-11-01","productname":"product2","actualvalue":122,"predictedvalue":273},{"date":"2015-12-01","productname":"product2","actualvalue":859,"predictedvalue":258},{"date":"2016-01-01","productname":"product2","actualvalue":807,"predictedvalue":729},{"date":"2016-02-01","productname":"product2","actualvalue":82,"predictedvalue":939},{"date":"2016-03-01","productname":"product2","actualvalue":72,"predictedvalue":348},{"date":"2016-04-01","productname":"product2","actualvalue":544,"predictedvalue":429},{"date":"2016-05-01","productname":"product2","actualvalue":512,"predictedvalue":562},{"date":"2016-06-01","productname":"product2","actualvalue":510,"predictedvalue":800},{"date":"2016-07-01","productname":"product2","actualvalue":283,"predictedvalue":847},{"date":"2016-08-01","productname":"product2","actualvalue":172,"predictedvalue":343},{"date":"2016-09-01","productname":"product2","actualvalue":315,"predictedvalue":633},{"date":"2016-10-01","productname":"product2","actualvalue":863,"predictedvalue":184},{"date":"2016-11-01","productname":"product2","actualvalue":125,"predictedvalue":623},{"date":"2016-12-01","productname":"product2","actualvalue":400,"predictedvalue":920}]; 
 
\t \t \t \t 
 
\t \t \t \t // get data between first and last day and for the selected product 
 
\t \t \t \t // draw a single line as a test 
 
\t \t \t \t var test_data = data.filter(function(el){ 
 
\t \t \t \t \t return el.date < lastDay && el.date > firstDay && el.productname == productSelected 
 
\t \t \t \t }); 
 
\t \t \t \t d3.select("#graph2").datum(test_data).call(chart); \t \t 
 
\t \t \t //}); 
 
\t \t } 
 
\t \t $(document).ready(function(){ \t \t 
 
\t \t \t $("#button30").click(function(){ 
 
\t \t \t \t $(".buttons1").removeClass("selected-button"); 
 
\t \t \t \t $("#button30").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button30").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button90").click(function(){ 
 
\t \t \t \t $(".buttons1").removeClass("selected-button"); 
 
\t \t \t \t $("#button90").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button90").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button180").click(function(){ 
 
\t \t \t \t $(".buttons1").removeClass("selected-button"); 
 
\t \t \t \t $("#button180").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button180").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button360").click(function(){ 
 
\t \t \t \t $(".buttons1").removeClass("selected-button"); 
 
\t \t \t \t $("#button360").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button360").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t updateResults(first_day,last_day,product); 
 
\t \t \t $("#button30-2").click(function(){ 
 
\t \t \t \t $(".buttons2").removeClass("selected-button"); 
 
\t \t \t \t $("#button30-2").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button30-2").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults2(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button90-2").click(function(){ 
 
\t \t \t \t $(".buttons2").removeClass("selected-button"); 
 
\t \t \t \t $("#button90-2").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button90-2").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults2(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button180-2").click(function(){ 
 
\t \t \t \t $(".buttons2").removeClass("selected-button"); 
 
\t \t \t \t $("#button180-2").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button180-2").data('months'); 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); 
 
\t \t \t \t updateResults2(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t $("#button360-2").click(function(){ 
 
\t \t \t \t $(".buttons2").removeClass("selected-button"); 
 
\t \t \t \t $("#button360-2").addClass("selected-button"); 
 
\t \t \t \t numMonths= $("#button360-2").data('months'); //or .data() 
 
\t \t \t \t first_day=formatDate(getFirstDay()); 
 
\t \t \t \t last_day=formatDate(getLastDay(numMonths)); // to set last day 
 
\t \t \t \t updateResults2(first_day,last_day,product); 
 
\t \t \t }); 
 
\t \t \t 
 
\t \t \t updateResults2(first_day,last_day,product); 
 

 
    \t \t }); 
 
\t \t \t // function to set last day date... basically today + 1, 3, 6, or 12 months, default is 3 
 
\t \t \t function getLastDay(months){ 
 

 
\t \t \t \t switch(months){ 
 
\t \t \t \t \t case "one": 
 
\t \t \t \t 
 
\t \t \t \t \t \t return moment().add(1, 'months')._d; 
 
\t \t \t \t \t break; 
 
\t \t \t \t \t case"six": 
 
\t \t \t \t 
 
\t \t \t \t \t \t return moment().add(6, 'months')._d; 
 
\t \t \t \t \t break; 
 
\t \t \t \t \t case"twelve": 
 
\t \t \t \t \t 
 
\t \t \t \t \t \t return moment().add(12, 'months')._d; 
 
\t \t \t \t \t break; 
 
\t \t \t \t \t default: 
 
\t \t \t \t \t \t return moment().add(3, 'months')._d; 
 
\t \t \t \t }; 
 

 
\t \t \t } 
 
\t \t \t 
 
\t \t \t // function to set first day date... basically today - 12 
 
\t \t \t function getFirstDay(){ 
 
\t \t \t \t return moment().subtract(12,'months')._d; 
 
\t \t \t }
.container{ 
 
    margin-top:50px;} 
 
html, body { 
 
    height: 100%; font-family: 'Open Sans', sans-serif;} 
 
.wrap{ 
 
    min-heigh:100%; 
 
} 
 
.prediction{ 
 
    height:700px; 
 
} 
 
.footer{ 
 
    width:100%; 
 
    position:fixed; 
 
    bottom:0px;padding:0px;text-align:center;} 
 
.footer p{margin-left:auto;margin-right:auto;} 
 
    .selected-button{background-color: black;border-color: black;color:white;} 
 
    
 
\t .axis path, 
 
\t .axis line { 
 
\t \t fill: none; 
 
\t \t stroke: #000; 
 
\t \t shape-rendering: crispEdges; 
 
\t } 
 
\t .x.axis path {} \t .line { 
 
\t \t fill: none; 
 
\t \t stroke: steelblue; 
 
\t \t stroke-width: 1.5px; 
 
\t } 
 

 
\t .line-before { 
 
\t \t stroke:#2185C5; 
 
\t \t fill: none; 
 
\t } 
 
\t .line-after{ 
 
\t \t stroke:#FFB779; 
 
\t \t fill: none; 
 
\t }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script> 
 
    <script src="http://jhjanicki.github.io/reusable-line-chart/js/bootstrap.min.js"></script> 
 
<script src="http://jhjanicki.github.io/reusable-line-chart/js/moment.js"></script> 
 
    <!-- D3 --><script src="http://d3js.org/d3.v3.js" charset="utf-8"></script> 
 
    \t <!-- underscore --><script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<div class="container" id="main"> 
 
<section class="prediction" id="prediction1"> 
 
<div class="row"> 
 
<div class="col-lg-12"> 
 
<div class="buttons"> 
 
<button type="button" class="btn btn-default buttons1" data-months="one" id="button30"> 1 Month</button> 
 
<button type="button" class="btn btn-default selected-button buttons1" data-months="three" id="button90"> 3 Months</button> 
 
<button type="button" class="btn btn-default buttons1" data-months="six" id="button180"> 6 Months</button> 
 
<button type="button" class="btn btn-default buttons1" data-months="twelve" id="button360"> 12 Months</button> 
 
</div> 
 
<div id="graph1"> 
 
</div> 
 
</div> 
 
</div> <!-- end row --> 
 
<div class="row"> 
 
<div class="col-lg-12"> 
 
<div class="buttons"> 
 
<button type="button" class="btn btn-default buttons2" data-months="one" id="button30-2"> 1 Month</button> 
 
<button type="button" class="btn btn-default selected-button buttons2" data-months="three" id="button90-2"> 3 Months</button> 
 
<button type="button" class="btn btn-default buttons2" data-months="six" id="button180-2"> 6 Months</button> 
 
<button type="button" class="btn btn-default buttons2" data-months="twelve" id="button360-2"> 12 Months</button> 
 
</div> 
 
<div id="graph2"></div> 
 
</div></div> <!-- end row --> 
 
    </section> \t 
 
\t </div> <!-- end container -->

我通過你http://jhjanicki.github.io/reusable-line-chart/了,看到app.js行號110個updateResults(FIRST_DAY,LAST_DAY,產品);此行將調用第一個圖並在行號206處將alreadyClicked值設置爲true,並且當您在第151行處調用updateResults2(first_day,last_day,product);時,第二個圖的'alreadyClicked'值將被設置爲true,否則零件將不會執行,並且此時它將嘗試進行動畫製作,但實際上不存在這樣的元素。我們必須爲每個svg保留單獨的剪輯路徑,那麼只有我們可以實現這一點。嘗試分析代碼並理解。希望這是你正在尋找的。如果不問我:D

+0

這很有道理!實際上我今天注意到它可能與alreadyClicked有關,但是當我將一個setter函數添加到已經被alreadyClicked使用的圖表函數並將其設置爲false時,它仍然不起作用(即'var chart2 = d3.PredictGraph()。alreadyClicked (false); d3.select(「#graph2」)。datum(data).call(chart2);')。但是你的解決方案工作得很好。非常感謝! – jhjanicki

+0

p.s.我試着大聲迴應你的回答,因爲我非常感謝你閱讀了我的代碼,並且我學到了一些東西,但是我猜想,自從我剛開始以來,我還沒有足夠的聲望去做。但非常感謝! – jhjanicki

+0

好的,沒關係。很高興能夠幫助你,並且很高興你能很好地理解它 –