2017-10-13 82 views
0

我是初学者,当我尝试选择lineChart中的某个元素时出现问题。 我知道有这么多的精英,所以我来这里寻求一些帮助:) 我在there和linechart找到一个画笔演示(对不起,他们不允许我插入2个链接,因为我没有10个声望)演示然后我写的代码的打击:使用d3画笔选择线条图中的元素

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 

 
<style type="text/css"> 
 
    /* 13. Basic Styling with CSS */ 
 

 
    /* Style the lines by removing the fill and applying a stroke */ 
 
    .line { 
 
     fill: none; 
 
     stroke: #ffab00; 
 
     stroke-width: 3; 
 
    } 
 

 
    /* Style the dots by assigning a fill and stroke */ 
 
    .dot { 
 
     fill: #1 fab40; 
 
     stroke: #fff; 
 
    } 
 
    .dot .selected { 
 
     stroke: red; 
 
    } 
 

 
</style> 
 
<!-- Body tag is where we will append our SVG and SVG objects--> 
 
<body> 
 
</body> 
 

 
<!-- Load in the d3 library --> 
 
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<script> 
 

 
    // 2. Use the margin convention practice 
 
    var margin = {top: 20, right: 50, bottom: 20, left: 50} 
 
     , width = window.innerWidth - margin.left - margin.right // Use the window's width 
 
     , height = window.innerHeight - margin.top - margin.bottom; // Use the window's height 
 

 
    // The number of datapoints 
 
    var n = 21; 
 

 
    // 5. X scale will use the index of our data 
 
    var xScale = d3.scaleLinear() 
 
     .domain([0, n-1]) // input 
 
     .range([0, width]); // output 
 

 
    // 6. Y scale will use the randomly generate number 
 
    var yScale = d3.scaleLinear() 
 
     .domain([0, 1]) // input 
 
     .range([height, 0]); // output 
 

 
    // 7. d3's line generator 
 
    var line = d3.line() 
 
     .x(function(d, i) { return xScale(i); }) // set the x values for the line generator 
 
     .y(function(d) { return yScale(d.y); }) // set the y values for the line generator 
 
     .curve(d3.curveMonotoneX);// apply smoothing to the line 
 

 
    // 8. An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number 
 
    var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } }); 
 

 
    // 1. Add the SVG to the page and employ #2 
 
    var svg = d3.select("body").append("svg") 
 
     .attr("width", width + margin.left + margin.right) 
 
     .attr("height", height + margin.top + margin.bottom) 
 
     .append("g") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    // 3. Call the x axis in a group tag 
 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom 
 

 
    // 4. Call the y axis in a group tag 
 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft 
 

 
    // 9. Append the path, bind the data, and call the line generator 
 
    svg.append("path") 
 
     .datum(dataset) // 10. Binds data to the line 
 
     .attr("class", "line") // Assign a class for styling 
 
     .attr("d", line); // 11. Calls the line generator 
 

 
    // 12. Appends a circle for each datapoint 
 
    var dot = svg.append("g") 
 
     .attr("class", "dot") // Assign a class for styling 
 
     .selectAll(".dot") 
 
     .data(dataset) 
 
     .enter().append("circle") // Uses the enter().append() method 
 
     .attr("r", 5) 
 
     .attr("cx", function(d, i) { return xScale(i) }) 
 
     .attr("cy", function(d) { return yScale(d.y) }); 
 

 
    var brush = svg.append("g") 
 
     .attr("class", "brush") 
 
     .call(d3.brush() 
 
      .extent([[0, 0], [width, height]]) 
 
      .on("start brush end", brushed)); 
 

 
    function brushed() { 
 
     var selection = d3.event.selection; 
 
     dot.classed("selected", selection && function(d) { 
 
      return selection[0][0] <= d.x && d.x < selection[1][0] 
 
       && selection[0][1] <= d.y && d.y < selection[1][1]; 
 
     }); 
 
    } 
 

 

 
</script>

我尝试写这样this demo相同的代码,但我不能选择任何圆点,问题出在哪里? 非常感谢!

回答

1

重写你brushed功能是这样的:

function brushed() { 
    var selection = d3.event.selection; 

    dot.classed("selected", selection && function(d,i) { 
     return selection[0][0] <= xScale(i) && xScale(i) < selection[1][0] 
      && selection[0][1] <= yScale(d.y) && yScale(d.y) < selection[1][1]; 
    }); 
} 

注意的是,我们使用xScaleyScale这里,对于正确匹配选择的区域和点的坐标。工作示例低于:

// 2. Use the margin convention practice 
 
    var margin = {top: 20, right: 50, bottom: 20, left: 50} 
 
     , width = window.innerWidth - margin.left - margin.right // Use the window's width 
 
     , height = window.innerHeight - margin.top - margin.bottom; // Use the window's height 
 

 
    // The number of datapoints 
 
    var n = 21; 
 

 
    // 5. X scale will use the index of our data 
 
    var xScale = d3.scaleLinear() 
 
     .domain([0, n-1]) // input 
 
     .range([0, width]); // output 
 

 
    // 6. Y scale will use the randomly generate number 
 
    var yScale = d3.scaleLinear() 
 
     .domain([0, 1]) // input 
 
     .range([height, 0]); // output 
 

 
    // 7. d3's line generator 
 
    var line = d3.line() 
 
     .x(function(d, i) { return xScale(i); }) // set the x values for the line generator 
 
     .y(function(d) { return yScale(d.y); }) // set the y values for the line generator 
 
     .curve(d3.curveMonotoneX);// apply smoothing to the line 
 

 
    // 8. An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number 
 
    var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } }); 
 

 
    // 1. Add the SVG to the page and employ #2 
 
    var svg = d3.select("body").append("svg") 
 
     .attr("width", width + margin.left + margin.right) 
 
     .attr("height", height + margin.top + margin.bottom) 
 
     .append("g") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    // 3. Call the x axis in a group tag 
 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom 
 

 
    // 4. Call the y axis in a group tag 
 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft 
 

 
    // 9. Append the path, bind the data, and call the line generator 
 
    svg.append("path") 
 
     .datum(dataset) // 10. Binds data to the line 
 
     .attr("class", "line") // Assign a class for styling 
 
     .attr("d", line); // 11. Calls the line generator 
 

 
    // 12. Appends a circle for each datapoint 
 
    var dot = svg.append("g") 
 
     .attr("class", "dot") // Assign a class for styling 
 
     .selectAll(".dot") 
 
     .data(dataset) 
 
     .enter().append("circle") // Uses the enter().append() method 
 
     .attr("r", 5) 
 
     .attr("cx", function(d, i) { return xScale(i) }) 
 
     .attr("cy", function(d) { return yScale(d.y) }); 
 

 
    var brush = svg.append("g") 
 
     .attr("class", "brush") 
 
     .call(d3.brush() 
 
      .extent([[0, 0], [width, height]]) 
 
      .on("start brush", brushed) 
 
      .on("end", getSelectedDots) 
 
     ); 
 
     
 
    var selectedDots = []; 
 
    
 
    function getSelectedDots() { 
 
     var selection = d3.event.selection; 
 
     
 
     dot.classed("selected", selection && function(d,i) { 
 
      var isSelectedDot = selection[0][0] <= xScale(i) && xScale(i) < selection[1][0] 
 
       && selection[0][1] <= yScale(d.y) && yScale(d.y) < selection[1][1]; 
 
       
 
      if (isSelectedDot) { 
 
      selectedDots.push(d); 
 
      } 
 

 
      return isSelectedDot; 
 
     }); 
 
     
 
     console.log('selectedDots ', selectedDots); 
 
    } 
 

 
    function brushed() { 
 
     var selection = d3.event.selection; 
 
     
 
     dot.classed("selected", selection && function(d,i) {   
 
      return selection[0][0] <= xScale(i) && xScale(i) < selection[1][0] 
 
       && selection[0][1] <= yScale(d.y) && yScale(d.y) < selection[1][1]; 
 
     }); 
 
    }
/* 13. Basic Styling with CSS */ 
 

 
    /* Style the lines by removing the fill and applying a stroke */ 
 
    .line { 
 
     fill: none; 
 
     stroke: #ffab00; 
 
     stroke-width: 3; 
 
    } 
 

 
    /* Style the dots by assigning a fill and stroke */ 
 
    .dot { 
 
     fill: #1fab40; 
 
     stroke: #fff; 
 
    } 
 
    .dot .selected { 
 
     stroke: red; 
 
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

+0

谢谢!您太客气了 – lomo

+0

我很抱歉打扰你,现在我可以选择我需要的点,但个个都是坐标的SVG我真正需要的是真实的数据,我怎样才能得到它们? – lomo

+0

@lomo我重写了我的答案的代码片段,请看看它。注意'getSelectedDots'函数,我附加在'd3.brush'的'end'事件上。现在,在每次选择后,所选点的数据对象数组将出现在控制台上。 –