javascript - 使用 d3 画笔选择折线图中的元素

标签 javascript d3.js frontend

我是初学者,当我尝试选择折线图中的某些元素时遇到问题。 我知道有很多精英,所以我来这里寻求帮助:) 我在 there 中找到了一个画笔演示和一个折线图(抱歉他们不允许我插入 2 个链接,因为我没有 10 个信誉)演示然后我编写了以下代码:

<!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 相同的代码,但我无法选择任何点,问题出在哪里? 非常感谢!

最佳答案

重写您的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>

关于javascript - 使用 d3 画笔选择折线图中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46727389/

相关文章:

JavaScript/jQuery - 向上滚动按钮

javascript - 无论如何(内置/自定义写入)在 Kendo UI Grid 中进行内联编辑之前显示确认对话框?

javascript - 如何将局部变量传递给全局函数

javascript - jQuery - 切换按钮显示/隐藏表数据

javascript - 为什么 keyup 有效但 keydown 不起作用

javascript - d3 饼图/ donut chart 中标签的过渡

javascript - Sinon单元测试MySQL连接

javascript - 与 d3 可重用模式的交互

javascript - 在文本标签内添加一个 div

internet-explorer - IE11 VM 不再可供下载 - 其他测试选项是什么?