从并行坐标可视化中选择D3中的过滤表

时间:2017-01-15 17:49:59

标签: d3.js filter

我有一个平行坐标可视化,我在下面添加了一个表格,代表了可视化中的所有数据。

我想根据平行坐标可视化的选择来过滤表格。因此,只显示并行坐标可视化中突出显示的数据。

关于如何做到这一点的任何想法?

我已经尝试在画笔部分用红色突出显示表格中的单元格,为标签添加样式,但它似乎不起作用。请参阅以下代码:

    // Add and store a brush for each axis.
    g.append("g")
      .attr("class", "brush")
      .each(function(d) {
        d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
        d3.selectAll("td").style('bgcolor', 'red');
      })
      .selectAll("rect")
      .attr("x", -8)
      .attr("width", 16);

我试图在画笔功能中添加细胞的高光。在这里,我实现了所有细胞变红,但我不知道如何仅突出显示在选择中选择的细胞。

    function brush() {
      var actives = dimensions.filter(function(p) {
          return !y[p].brush.empty();
        }),
        extents = actives.map(function(p) {
          return y[p].brush.extent();
        });
      foreground.style("display", function(d) {
        return actives.every(function(p, i) {
          return extents[i][0] <= d[p] && d[p] <= extents[i][1];
        }) ? null : "none";
      });
      d3.selectAll("td").style('background-color', 'red');
    }

请参阅以下代码,您也可以在以下链接中找到该代码GitHub

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  svg {
    font: 10px sans-serif;
  }

  .background path {
    fill: none;
    stroke: #ddd;
    shape-rendering: crispEdges;
  }

  .foreground path {
    fill: none;
    stroke: steelblue;
    stroke-width: 2;
  }

  .brush .extent {
    fill-opacity: .3;
    stroke: #fff;
    shape-rendering: crispEdges;
  }

  .axis line,
  .axis path {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
  }

  .axis text {
    text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
    cursor: move;
  }

  .tooltip {   
    background-color: rgba(220,220,220,0.5);
    color: #333;
              margin: 10px;
              height: 25px;
              padding-right: 10px;
              padding-left: 10px; 
              padding-top: 10px;
        -webkit-border-radius:10px;
        -moz-border-radius:10px;
        border-radius:10px;
    }

    td, th {
    padding: 1px 4px;
    }

</style>

<body>
  <script src="http://d3js.org/d3.v3.min.js"></script>
  <script>
  // Fuente original: https://bl.ocks.org/jasondavies/1341281
    var margin = {
        top: 30,
        right: 10,
        bottom: 10,
        left: 10
      },
      width = 960 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    var x = d3.scale.ordinal().rangePoints([0, width], 1),
      y = {},
      dragging = {};

    var line = d3.svg.line(),
      axis = d3.svg.axis().orient("left"),
      background,
      foreground;

    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 + ")");

    var notas = [
        {
                "Nombre": "Emily",
                "Matematicas": "10",
                "Ciencias": "10",
                "Historia":  "8",
                "Geografia":  "8",
                "Lengua": "10"
        },
        {
                "Nombre": "Cooper",
                "Matematicas": "10",
                "Ciencias": "7",
                "Historia": "2",
                "Geografia": "8",
                "Lengua": "10"
        }];

    var tooltip = d3.select("body")
        .append("div")
        .style("position", "absolute")
        .style("z-index", "10")
        .style("visibility", "hidden")
        .text("a simple tooltip")
        .attr("class","tooltip");

    // Extract the list of dimensions and create a scale for each.
    x.domain(dimensions = d3.keys(notas[0]).filter(function(d) {
      return d != "Nombre" && (y[d] = d3.scale.linear()
        .domain(d3.extent(notas, function(p) {
          return +p[d];
        }))
        .range([height, 0]));
    }));


    // Add grey background lines for context.
    background = svg.append("g")
      .attr("class", "background")
      .selectAll("path")
      .data(notas)
      .enter().append("path")
      .attr("d", path);

    // Add blue foreground lines for focus.
    foreground = svg.append("g")
      .attr("class", "foreground")
      .selectAll("path")
      .data(notas)
      .enter().append("path")
      .attr("d", path)
      .on("mouseover", function(n){
        d3.select(this)
        .transition().duration(100)
        .style({'stroke' : '#F00'});
        tooltip.text(n.Nombre);
        return tooltip.style("visibility", "visible");
        })
        .on("mousemove", function(){
        return tooltip
            .style("top", (event.pageY-10)+"px")
            .style("left",(event.pageX+10)+"px");
        })
        .on("mouseout", function(d){
        d3.select(this)
            .transition().duration(100)
            .style({'stroke': 'steelblue' })
            .style({'stroke-width' : '2'});
        return tooltip.style("visibility", "hidden");
        });

    // Add a group element for each dimension.
    var g = svg.selectAll(".dimension")
      .data(dimensions)
      .enter().append("g")
      .attr("class", "dimension")
      .attr("transform", function(d) {
        return "translate(" + x(d) + ")";
      })
      .call(d3.behavior.drag()
        .origin(function(d) {
          return {
            x: x(d)
          };
        })
        .on("dragstart", function(d) {
          dragging[d] = x(d);
          background.attr("visibility", "hidden");
        })
        .on("drag", function(d) {
          dragging[d] = Math.min(width, Math.max(0, d3.event.x));
          foreground.attr("d", path);
          dimensions.sort(function(a, b) {
            return position(a) - position(b);
          });
          x.domain(dimensions);
          g.attr("transform", function(d) {
            return "translate(" + position(d) + ")";
          })
        })
        .on("dragend", function(d) {
          delete dragging[d];
          transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
          transition(foreground).attr("d", path);
          background
            .attr("d", path)
            .transition()
            .delay(500)
            .duration(0)
            .attr("visibility", null);
        }));

    // Add an axis and title.
    g.append("g")
      .attr("class", "axis")
      .each(function(d) {
        d3.select(this).call(axis.scale(y[d]));
      })
      .append("text")
      .style("text-anchor", "middle")
      .attr("y", -9)
      .text(function(d) {
        return d;
      });

    // Add and store a brush for each axis.
    g.append("g")
      .attr("class", "brush")
      .each(function(d) {
        d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
      })
      .selectAll("rect")
      .attr("x", -8)
      .attr("width", 16);

    function position(d) {
      var v = dragging[d];
      return v == null ? x(d) : v;
    }

    function transition(g) {
      return g.transition().duration(500);
    }

    // Returns the path for a given data point.
    function path(d) {
      return line(dimensions.map(function(p) {
        return [position(p), y[p](d[p])];
      }));
    }

    function brushstart() {
      d3.event.sourceEvent.stopPropagation();
    }

    // Handles a brush event, toggling the display of foreground lines.
    function brush() {
      var actives = dimensions.filter(function(p) {
          return !y[p].brush.empty();
        }),
        extents = actives.map(function(p) {
          return y[p].brush.extent();
        });
      foreground.style("display", function(d) {
        return actives.every(function(p, i) {
          return extents[i][0] <= d[p] && d[p] <= extents[i][1];
        }) ? null : "none";
      });
    }


// The table generation function
function tabulate(data, columns) {
    var table = d3.select("body").append("table")
            .attr("style", "margin-left: 250px"),
        thead = table.append("thead"),
        tbody = table.append("tbody");

    // append the header row
    thead.append("tr")
        .selectAll("th")
        .data(columns)
        .enter()
        .append("th")
            .text(function(column) { return column; });

    // create a row for each object in the data
    var rows = tbody.selectAll("tr")
        .data(notas)
        .enter()
        .append("tr");

    // create a cell in each row for each column
    var cells = rows.selectAll("td")
        .data(function(row) {
            return columns.map(function(column) {
                return {column: column, value: row[column]};
            });
        })
        .enter()
        .append("td")
        .attr("style", "font-family: Courier") // sets the font style
            .html(function(d) { return d.value; });

    return table;
}

// render the table
 var peopleTable = tabulate(notas, ["Nombre", "Matematicas","Ciencias", "Historia","Geografia", "Lengua"]);


  </script>

  </body>
</html>

我已在JSFiddle中添加了代码,但它没有显示任何内容。我不确定我做错了什么。我不熟悉JSFiddle,所以我可能做错了。

我也试过使用divgrid(DivGrid)并使用以下代码我可以看到当我尝试刷表时如何更新。问题是它没有更新我需要的数据。我只是要显示5条记录。

  <script src="divgrid.js"></script>
  ...
    // Handles a brush event, toggling the display of foreground lines.
    function brush() {
      var actives = dimensions.filter(function(p) {
          return !y[p].brush.empty();
        }),
        extents = actives.map(function(p) {
          return y[p].brush.extent();
        });
      foreground.style("display", function(d) {
        return actives.every(function(p, i) {
          return extents[i][0] <= d[p] && d[p] <= extents[i][1];
        }) ? null : "none";
      });
      //d3.selectAll("td").style('background-color', 'red');
       var grid = d3.divgrid();
         d3.select('body')
            .datum(notas.slice(0,5))
            .call(grid);
    }

我遇到的问题(我认为)是(1)表格的更新并不是真正在正确的位置,因为它只是在开始刷时更新,而不是刷过线条时(2)我需要找到一种从所选行中拾取数据的方法。我已经添加到github中的代码作为参考(GitHub

有什么想法吗?

由于

0 个答案:

没有答案