2017-10-05 54 views
1

我们正在使用的平行坐标绘图和绘图数据可以在here找到。此平行坐标图不适用于d3的第4版。我们根据从v3到v4的API更改进行了更改。我认为主要问题在于下面显示的刷子功能。D3 v4平行坐标绘图笔刷选择

function brush() { 
    let actives = dimensions.filter(function (p) { 
     return d3.brushSelection(y[p]) !== null; 
    }); 

    console.log(actives); 
    let extents = actives.map(function (p) { 
      return d3.brushSelection(y[p]); 
    }); 

    foreground.style("display", function (d) { 
     return actives.every(function (p, i) { 
      return extents[i][0] <= d[p] && d[p] <= extents[i][1]; 
     }) ? null : "none"; 
    }); 
} 

该日志显示“Array []”为活动项。目前,我们将每个维度的笔刷范围设置为[[-8,0],[8,height]],这也可能是一个问题。完整的代码在下面提供。

<!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; 
} 

.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; 
} 
</style> 
<body> 
<script src="https://d3js.org/d3.v4.min.js"></script> 
<script> 
let margin = {top: 30, right: 10, bottom: 10, left: 10}, 
    width = 960 - margin.left - margin.right, 
    height = 500 - margin.top - margin.bottom; 

let x = d3.scalePoint().range([0, width]).padding(1), 
    y = {}, 
    dragging = {}; 

let line = d3.line(), 
    axis = d3.axisLeft(), //Argument for axisLeft? Compare to code on original plot 
    background, 
    foreground; 

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

d3.csv("cars.csv", function (error, cars) { 

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

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

    // Add blue foreground lines for focus. 
    foreground = svg.append("g") 
     .attr("class", "foreground") 
     .selectAll("path") 
     .data(cars) 
     .enter().append("path") 
     .attr("d", path); 

    // Add a group element for each dimension. 
    let g = svg.selectAll(".dimension") 
     .data(dimensions) 
     .enter().append("g") 
     .attr("class", "dimension") 
     .attr("transform", function (d) { 
      return "translate(" + x(d) + ")"; 
     }) 
     .call(d3.drag() 
      .subject(function (d) { 
       return {x: x(d)}; 
      }) 
      .on("start", 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("end", 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.brushY().extent([[-8,0],[8,height]]).on("start", brushstart).on("brush", brush)); 
         }) 
     .selectAll("rect") 
     .attr("x", -8) 
     .attr("width", 16); 
}); 

function position(d) { 
    let 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() { 
    //return !y[p].brush.empty was the original return value. 

    let actives = dimensions.filter(function (p) { 
     return d3.brushSelection(y[p]) !== null; 
    }); 

    console.log(actives); 
    let extents = actives.map(function (p) { 
      return d3.brushSelection(y[p]); 
    }); 

    foreground.style("display", function (d) { 
     return actives.every(function (p, i) { 
      return extents[i][0] <= d[p] && d[p] <= extents[i][1]; 
     }) ? null : "none"; 
    }); 
} 
</script> 

如果有人熟悉d3并可以提供任何指导,将不胜感激。我们也尝试在画笔函数中使用d3.event.selection和y [p] .brush.selection。

+0

你是谁的情节不工作?它是否绘制了阴谋?它是否给你任何错误? – jrogers12

回答

0

我偶然发现了完全相同的问题,但设法解决它后,下面的变化。

添加刷每个轴这样:

y[d] = d3.scaleLinear().domain(d3.extent(data, function(p) { 
    return +p[d]; 
})).range([height, 0]); 
y[d].brush = d3.brushY() 
    .extent([[-8, y[d].range()[1]], [8, y[d].range()[0]]]) 
    .on('brush', brush); 

随后,上面得到为刷子回调添加刷组时:

g.append('g') 
    .attr('class', 'brush') 
    .each(function(d) { 
    d3.select(this).call(y[d].brush); 
    }) 
    .selectAll('rect') 
    .attr('x', -8) 
    .attr('width', 16); 

最后,改变刷处理程序是:

function brush() { 
    const actives = []; 
    // filter brushed extents 
    svg.selectAll('.brush') 
    .filter(function(d): any { 
     return d3.brushSelection(this as any); 
    }) 
    .each(function(d) { 
     actives.push({ 
     dimension: d, 
     extent: d3.brushSelection(this as any) 
     }); 
    }); 
    // set un-brushed foreground line disappear 
    foreground.style('display', function(d) { 
    return actives.every(function(active) { 
     const dim = active.dimension; 
     return active.extent[0] <= y[dim](d[dim]) && y[dim](d[dim]) <= active.extent[1]; 
    }) ? null : 'none'; 
    }); 
} 

如果上面的内容令人困惑,请参阅这个独立的示例,该示例帮助我以正确的brus hing与d3 v4平行坐标:https://gist.github.com/kotomiDu/d1fd0fe9397db41f5f8ce1bfb92ad20d