2016-02-23 3 views
1

Я создал визуализацию D3, которая содержит диаграмму рассеяния и линейную диаграмму. Они имеют ось x, но каждая из них имеет собственную ось y. Моя проблема заключается в том, как правильно внедрить кисть и обновить обе оси y.Использование кисти D3 с несколькими у-осями

enter image description here

Как вы можете видеть здесь у-оси правильно изначально, а также правильно еще раз, когда кисть выключена. Однако во время «чистки» обе оси y устанавливаются в «левый». Я понимаю, почему это происходит, когда нужно настроить кисть здесь:

brush = d3.svg.brush() 
    .x(brushFilterXScale) 
    .y(brushFilterTransactionsYScale) 
    .on('brush', brushed); 

У меня также есть brushFilterBalanceYScale, который является шкалой для оси справа. Мой вопрос заключается в том, как передать ОБА из этих шкал в brush, чтобы я мог правильно обновлять каждую ось Y?

ответ

2

Я не знаю, как это сделать. Вы можете, однако, реверс отобразить его в вашем brush события:

function brushed() { 

    var extent = brush.extent(), //<-- the extent 
     yDomain = [extent[0][1], extent[1][1]]; //<-- the y domain of the extent 

    y2.domain(
    [ 
     y2Brush.invert(yBrush(yDomain[0])), //<-- take the yDomain start, get it's pixel position, then invert that back into the domain of the y2Brush 
     y2Brush.invert(yBrush(yDomain[1])) 
    ] 
); 

Вот рабочий пример:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    svg { 
 
    font: 10px sans-serif; 
 
    } 
 
    
 
    .line { 
 
    fill: none; 
 
    stroke: steelblue; 
 
    clip-path: url(#clip); 
 
    } 
 
    
 
    circle { 
 
    clip-path: url(#clip); 
 
    } 
 
    
 
    .axis path, 
 
    .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
    } 
 
    
 
    .brush .extent { 
 
    stroke: #fff; 
 
    fill-opacity: .125; 
 
    shape-rendering: crispEdges; 
 
    } 
 
</style> 
 

 
<body> 
 
    <script src="//d3js.org/d3.v3.min.js"></script> 
 
    <script> 
 
    var margin = { 
 
     top: 10, 
 
     right: 40, 
 
     bottom: 100, 
 
     left: 40 
 
     }, 
 
     margin2 = { 
 
     top: 430, 
 
     right: 40, 
 
     bottom: 20, 
 
     left: 40 
 
     }, 
 
     width = 500 - margin.left - margin.right, 
 
     height = 500 - margin.top - margin.bottom, 
 
     height2 = 500 - margin2.top - margin2.bottom; 
 

 

 
    var x = d3.scale.linear().range([0, width]) 
 
     y = d3.scale.linear().range([height, 0]), 
 
     y2 = d3.scale.linear().range([height, 0]), 
 
     xBrush = d3.scale.linear().range([0,width]), 
 
     yBrush = d3.scale.linear().range([height2, 0]), 
 
     y2Brush = d3.scale.linear().range([height2, 0]); 
 

 
    var xAxis = d3.svg.axis().scale(x).orient("bottom"), 
 
     yAxis = d3.svg.axis().scale(y).orient("left"), 
 
     yAxis2 = d3.svg.axis().scale(y2).orient("right"), 
 
     yAxisBrush = d3.svg.axis().scale(yBrush).orient("bottom"); 
 
     xAxisBrush = d3.svg.axis().scale(xBrush).orient("bottom"); 
 

 
    var brush = d3.svg.brush() 
 
     .x(xBrush) 
 
     .y(yBrush) 
 
     .on("brush", brushed); 
 

 
    var line = d3.svg.line() 
 
     .interpolate("monotone") 
 
     .x(function(d) { 
 
     return x(d.x); 
 
     }) 
 
     .y(function(d) { 
 
     return y(d.y); 
 
     }); 
 

 
    var lineBrush = d3.svg.line() 
 
     .interpolate("monotone") 
 
     .x(function(d) { 
 
     return x(d.x); 
 
     }) 
 
     .y(function(d) { 
 
     return yBrush(d.y); 
 
     }); 
 

 
    var svg = d3.select("body").append("svg") 
 
     .attr("width", width + margin.left + margin.right) 
 
     .attr("height", height + margin.top + margin.bottom); 
 

 
    svg.append("defs").append("clipPath") 
 
     .attr("id", "clip") 
 
     .append("rect") 
 
     .attr("width", width) 
 
     .attr("height", height); 
 

 
    var focus = svg.append("g") 
 
     .attr("class", "focus") 
 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
    var context = svg.append("g") 
 
     .attr("class", "context") 
 
     .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); 
 

 
    var data1 = [], 
 
     data2 = []; 
 
    for (var i = 0; i < 100; i++) { 
 
     data1.push({ 
 
     x: i, 
 
     y: Math.random() * 10 
 
     }); 
 
     if (i % 3 === 0){ 
 
     data2.push({ 
 
      x: i, 
 
      y: Math.random() * 100 
 
     }); 
 
     } 
 
    } 
 

 
    x.domain([0,100]); 
 
    y.domain([0, d3.max(data1.map(function(d) { 
 
     return d.y; 
 
    }))]); 
 
    y2.domain([0, d3.max(data2.map(function(d) { 
 
     return d.y; 
 
    }))]); 
 
    xBrush.domain(x.domain()); 
 
    yBrush.domain(y.domain()); 
 
    y2Brush.domain(y2.domain()); 
 

 
    focus.append("path") 
 
     .datum(data1) 
 
     .attr("class", "line") 
 
     .attr("d", line); 
 
     
 
    var scatter = focus.append("g") 
 
     .selectAll("circle") 
 
     .data(data2); 
 
     
 
    scatter 
 
     .enter() 
 
     .append("circle") 
 
     .attr("cx", function(d){ 
 
     return x(d.x); 
 
     }) 
 
     .attr("cy", function(d){ 
 
     return y2(d.y); 
 
     }) 
 
     .attr("r", function(d){ 
 
     d.r = Math.random() * 20; 
 
     return d.r; 
 
     }) 
 
     .style("fill", "orange") 
 
     .style("opacity", "0.5"); 
 
     
 
    focus.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(xAxis); 
 

 
    focus.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis); 
 
     
 
    focus.append("g") 
 
     .attr("transform", "translate(" + width + " ,0)") \t 
 
     .attr("class", "y2 axis") 
 
     .call(yAxis2); 
 

 
    context.append("path") 
 
     .datum(data1) 
 
     .attr("class", "line") 
 
     .attr("d", lineBrush); 
 
     
 
    context.append("g") 
 
     .selectAll("circle") 
 
     .data(data2) 
 
     .enter() 
 
     .append("circle") 
 
     .attr("cx", function(d){ 
 
     return x(d.x); 
 
     }) 
 
     .attr("cy", function(d){ 
 
     return y2Brush(d.y); 
 
     }) 
 
     .attr("r", function(d){ 
 
     return d.r * 0.25; 
 
     }) 
 
     .style("fill", "orange") 
 
     .style("opacity", "0.5"); 
 

 
    context.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height2 + ")") 
 
     .call(xAxisBrush); 
 

 
    context.append("g") 
 
     .attr("class", "x brush") 
 
     .call(brush) 
 
     .selectAll("rect") 
 
     .attr("y", -6) 
 
     .attr("height", height2 + 7); 
 

 
    function brushed() { 
 
     
 
     var extent = brush.extent(), 
 
      yDomain = [extent[0][1], extent[1][1]]; 
 

 
     y2.domain([y2Brush.invert(yBrush(yDomain[0])), y2Brush.invert(yBrush(yDomain[1]))]); 
 
     x.domain(brush.empty() ? xBrush.domain() : [extent[0][0], extent[1][0]]); 
 
     y.domain(brush.empty() ? yBrush.domain() : yDomain); 
 
     
 
     scatter 
 
     .attr("cx", function(d){ 
 
      return x(d.x); 
 
     }) 
 
     .attr("cy", function(d){ 
 
      return y2(d.y); 
 
     }) 
 
     
 
     focus.select(".line").attr("d", line); 
 
     focus.select(".x.axis").call(xAxis); 
 
     focus.select(".y.axis").call(yAxis); 
 
     focus.select(".y2.axis").call(yAxis2); 
 
    } 
 

 
    </script>

Смежные вопросы