【问题标题】:D3 can't draw two brushes togetherD3不能把两个画笔画在一起
【发布时间】:2017-05-20 08:37:11
【问题描述】:

所以我正在尝试制作一些东西,用户可以在折线图中拖动并创建两个相等大小的画笔,问题是我尝试绘制第二个画笔后画笔消失了。我试图创建单独的 attr 和单独的画笔调用,但仍然无法做到。 这是我的代码https://jsfiddle.net/f0gxs41t/

有什么帮助吗?

    <!DOCTYPE html>
<html>
<head>
    <svg width="960" height="400"></svg>
  <meta charset="utf-8">
  <title>
    line chart with drag and drop
  </title>
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
  <script src="./line_graph.js"></script>
  <link rel="stylesheet" type= "text/css" href="./style.css">
</head>
<body>
</body>
</html>

js 文件:

var data=[1,5,2,7,4,7,8,9,5,3,6,8,2,3,5,9,8,5]

var svg=d3.select("svg")
var margin={top:100,bottom:50,left:100,right:0},
   width = +svg.attr("width") - margin.left - margin.right,
   height = +svg.attr("height") - margin.top - margin.bottom,
   g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");


var x_extent=d3.extent(data,function(d,i){return i})
var y_extent=d3.extent(data,function(d,i){return d})


x=d3.scale.linear()
.range([0,width])
.domain(x_extent)

y=d3.scale.linear()
.range([height,0])
.domain(y_extent)

var line=d3.svg.line()
.x(function(d,i){ return x(i)})
.y(function(d,i){return y(d)})

var xAxis = d3.svg.axis().scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis().scale(y)
    .orient("left");

// g.append("g")
// .append("text")
// .attr("fill", "#000")
// .attr("transform","rotate(-90)")
// .attr("y",-35)
// .attr("dy","0.71em")
// .attr("text-anchor","end")
// .text("break something")

g.append("path")
.attr("class","line")
.datum(data)
.attr("d",line)

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate("+margin.left+"," + (height+margin.top) + ")")
    .call(xAxis);

// Add the Y Axis
svg.append("g")
    .attr("class", "y axis")
    .attr("transform", "translate("+margin.left+ ","+margin.top+")")
    .call(yAxis);

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

// if (brush.empty()!==true){
//
// }



var brushes = [];
var parent_brush=d3.svg.brush()
          .x(x)
          .on("brushend",brushed)

var brush1=d3.svg.brush()
          .x(x)
          .on("brushend",brushed)



function brushed(){
  if (parent_brush.empty()==true){
    console.log(parent_brush,"empty")
  }
  else {
    brush_width=parent_brush.extent()[1]-parent_brush.extent()[0]
        console.log(parent_brush,"not empty")
  }
}


svg.append("g")
.attr("class","parent")
.call(parent_brush)
.selectAll("rect")
.attr("x",margin.left)
.attr("y",margin.top)
.attr("height",height)
.style("fill","orange")
.style("fill-opacity",".2")


svg.append("g")
.attr("class","child")
.call(brush1)
.selectAll("rect")
.attr("x",margin.left)
.attr("y",margin.top)
.attr("height",height)
.style("fill","orange")
.style("fill-opacity",".2")

css 文件:

.axis path,
.axis line {
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
}
.hover-line {
  stroke: #6F257F;
  stroke-width: 2px;
  stroke-dasharray: 3,3;
}
.area {
  fill: lightsteelblue;
}
.line{
  fill:none;
  stroke:brown;
  stroke-linejoin:round;
  stroke-linecap:round;
  stroke-width:1.5
}

.focus circle {
  fill: none;
  stroke: steelblue;
}
.brush {
  fill: grey;
  pointer-events: all;
  fill-opacity:0.3;
}

.resize  {
  fill: grey;
  pointer-events: all;
  fill-opacity:0.7;
}

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    考虑使用 d3.js v4...

    子画笔在父画笔“结束”事件处理程序中创建,我们还需要禁用新的父画笔选择。

    var parent_brush = d3.brushX()
      .extent([
        [margin.left, margin.top],
        [margin.left + width, margin.top + height]
      ])
      .on("end", brushedParent);
    var child_brush;
    
    svg.append("g")
      .attr("class", "parent")
      .call(parent_brush);
    
    function brushedParent() {
      // remove new brush selection capture area
      svg.select('.parent .overlay').remove();
    
      if (!child_brush) {
        child_brush = d3.brushX()
          .extent([
            [margin.left, margin.top],
            [margin.left + width, margin.top + height]
          ])
          .on("end", brushedChild);
    
        svg.append("g")
          .attr("class", "child")
          .call(child_brush);
      }
    }
    
    function brushedChild() {
      // remove new brush selection capture area
      svg.select('.child .overlay').remove();
    
      child_selection = d3.brushSelection(svg.select('.child').node());
    
      var parent_selection = d3.brushSelection(svg.select('.parent').node());
      var parent_width = parent_selection[1] - parent_selection[0];
      var resized_child = [child_selection[0], child_selection[0] + parent_width];
    
      child_brush.on("end", null);
      child_brush.move(svg.select('.child'), resized_child);
    }
    

    这里是工作代码sn-p:

    var data = [1, 5, 2, 7, 4, 7, 8, 9, 5, 3, 6, 8, 2, 3, 5, 9, 8, 5]
    
    var svg = d3.select("svg")
    var margin = {
        top: 100,
        bottom: 50,
        left: 100,
        right: 0
      },
      width = +svg.attr("width") - margin.left - margin.right,
      height = +svg.attr("height") - margin.top - margin.bottom,
      g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    var x_extent = d3.extent(data, function(d, i) {
      return i
    })
    var y_extent = d3.extent(data, function(d, i) {
      return d
    })
    
    x = d3.scaleLinear()
      .range([0, width])
      .domain(x_extent)
    
    y = d3.scaleLinear()
      .range([height, 0])
      .domain(y_extent)
    
    var line = d3.line()
      .x(function(d, i) {
        return x(i)
      })
      .y(function(d, i) {
        return y(d)
      })
    
    var xAxis = d3.axisBottom(x);
    var yAxis = d3.axisLeft(y);
    
    g.append("path")
      .attr("class", "line")
      .datum(data)
      .attr("d", line)
    
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
      .call(xAxis);
    
    // Add the Y Axis
    svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(yAxis);
    
    var focus = svg.append("g")
      .attr("class", "focus")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    var brushes = [];
    var parent_brush = d3.brushX()
      .extent([
        [margin.left, margin.top],
        [margin.left + width, margin.top + height]
      ])
      .on("end", brushedParent);
    var child_brush;
    
    svg.append("g")
      .attr("class", "parent")
      .call(parent_brush);
    
    function brushedParent() {
      // remove new brush selection capture area
      svg.select('.parent .overlay').remove();
    
      if (!child_brush) {
        child_brush = d3.brushX()
          .extent([
            [margin.left, margin.top],
            [margin.left + width, margin.top + height]
          ])
          .on("end", brushedChild);
    
        svg.append("g")
          .attr("class", "child")
          .call(child_brush);
      }
    }
    
    function brushedChild() {
      // remove new brush selection capture area
      svg.select('.child .overlay').remove();
    
      child_selection = d3.brushSelection(svg.select('.child').node());
    
      var parent_selection = d3.brushSelection(svg.select('.parent').node());
      var parent_width = parent_selection[1] - parent_selection[0];
      var resized_child = [child_selection[0], child_selection[0] + parent_width];
    
      child_brush.on("end", null);
      child_brush.move(svg.select('.child'), resized_child);
    }
    .axis path,
    .axis line {
      fill: none;
      stroke: grey;
      stroke-width: 1;
      shape-rendering: crispEdges;
    }
    
    .hover-line {
      stroke: #6F257F;
      stroke-width: 2px;
      stroke-dasharray: 3, 3;
    }
    
    .area {
      fill: lightsteelblue;
    }
    
    .line {
      fill: none;
      stroke: brown;
      stroke-linejoin: round;
      stroke-linecap: round;
      stroke-width: 1.5
    }
    
    .focus circle {
      fill: none;
      stroke: steelblue;
    }
    
    .brush {
      fill: grey;
      pointer-events: all;
      fill-opacity: 0.3;
    }
    
    .resize {
      fill: grey;
      pointer-events: all;
      fill-opacity: 0.7;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="960" height="400"></svg>

    【讨论】:

    • @TaranjeetSingh 不客气……但在解除“结束”事件侦听器的绑定之前,请检查是否创建了一些选择,因为这样只需单击图表区域即可解除绑定:)
    • v3 中 d3.brushSelection 的替代方案是什么?
    • @TaranjeetSingh,不确定,您可能需要从 '.brush .selection' d3-3.x-api-reference 手动获取这些尺寸
    猜你喜欢
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多