D3.js画笔控件:获取范围宽度,坐标

Age*_*ths 12 javascript d3.js

我正在使用d3.js,并想知道如何获得边,宽度,坐标等; 程度.在这样的例子http://bl.ocks.org/mbostock/1667367

Ame*_*aBR 58

Brush.extent()

使用画笔控件时,可以使用.extent()画笔对象上的方法访问有关画笔状态的信息.

.extent()方法返回的信息取决于您连接到画笔对象的缩放比例.

如果已经一个刻度联(任一的X标尺 Y形的规模,但不是两者),则程度方法返回形式的两元件阵列[minimum, maximum].

如果有两个 X和Y标尺设置在刷对象,则程度方法返回形式的嵌套阵列[??[xMinimum, yMinimum], [xMaximum, yMaximum]?].

但这些最小值和最大值是多少?这也取决于规模.如果比例具有有效.invert(value)方法,则最小值和最大值将转换为数据域值.对于没有简单invert方法的序数,阈值和其他比例,画笔函数返回对画笔元素有效的坐标系中的值.

1.一维刷

要回答您链接到的具体示例的问题,我们需要查看画笔对象并缩放对象.在该示例中,画笔连接到较小的"上下文"图表(x2比例)上的水平刻度:

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

var brush = d3.svg.brush()
    .x(x2)
    .on("brush", brushed);
Run Code Online (Sandbox Code Playgroud)

刷子的初始化

上面创建的画笔对象仅存在于Javascript中,而不存在于文档中.但是,该对象也是一个可以被调用的函数(类似于轴函数),以便创建一系列矩形,它们将响应鼠标事件(这些是不可见的)和一个"范围"矩形(在本例中)是灰色的,带有白色边框).

context.append("g")
  .attr("class", "x brush")
  .call(brush)  //call the brush function, causing it to create the rectangles
.selectAll("rect") //select all the just-created rectangles
  .attr("y", -6)
  .attr("height", height2 + 7); //set their height
Run Code Online (Sandbox Code Playgroud)

不可见矩形的默认大小基于X和Y标度的输出范围.由于此画笔没有Y刻度,因此必须明确设置矩形的恒定高度和垂直位置.

范围矩形的初始大小基于画笔对象的范围(默认情况下为零宽度和高度).该矩形的高度也在上面的代码中设置.

画笔互动

当用户与屏幕上的画笔交互时,画笔对象捕获这些事件,(1)更新"范围"矩形的宽度,(2)调用与行中"画笔"事件关联的函数.on("brush", brushed).

brushed()功能是:

function brushed() {
  x.domain(brush.empty() ? x2.domain() : brush.extent());
  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
}
Run Code Online (Sandbox Code Playgroud)

这个画笔的目的是缩放主图表,这是通过设置主图表的X比例的域来完成的.如果画笔的宽度为零,则brush.empty()返回true,主图表X-domain设置为小图表中显示的完整域.

但是,如果画笔具有有效宽度,则空测试返回false,并将域设置为结果brush.extent().因为画笔附加到线性X刻度,而没有Y刻度,所以范围[xMin, xMax](在数据编号中)返回,这正是设置域所需的.

从画笔中提取值

如果你需要知道数据值的宽度,这是一个简单的减法问题:

var extent = brush.extent(); //returns [xMin, xMax]
var width = extent[1] - extent[0]; //data-width = max - min
Run Code Online (Sandbox Code Playgroud)

但是,如果要在屏幕上绘制其他元素,则需要知道SVG中的实际坐标,而不仅仅是数据值.要进行转换,您使用的是始终用于从数据转换为SVG坐标的相同内容:您的缩放功能.记住要使用x2控制小图表的比例,而不是主图表的放大比例,如下所示:

var extent = brush.extent(); //returns [xMin, xMax]
var rangeExtent = [x2( extent[0] ), x2( extent[1] ) ]; //convert
var rangeWidth  = rangeExtent[1] - rangeExtent[0];
Run Code Online (Sandbox Code Playgroud)

2. X和Y刷

要重新强调,此示例适用于具有一个(水平/ X)刻度的画笔,这是一个线性刻度.如果您同时使用X和Y线性刻度,则需要使用以下代码分隔X和Y范围值:

function brushed() {

  if (brush.empty()) {
      //either the height OR the width is empty
      x.domain( x2.domain() ); //reset X scale
      y.domain( y2.domain() ); //reset Y scale
  }

  var extent = brush.extent();
  x.domain( [extent[0][0] , extent[1][0] ] ); //min and max data X values
  y.domain( [extent[0][1] , extent[1][1] ] ); //min and max data Y values

  var rangeExtent = [
          [x2(extent[0][0]), y2(extent[0][1])],
          [x2(extent[1][0]), y2(extent[1][1])]
       ];
  var rangeWidth  = rangeExtent[1][0] - rangeExtent[0][0];
  var rangeHeight = rangeExtent[1][1] - rangeExtent[0][1];


  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}
Run Code Online (Sandbox Code Playgroud)

从画笔中提取值

如果您想知道矩形左上角的坐标,您还需要知道Y刻度是否从上到下切换最小值.

或者,您可以从屏幕上的"范围"矩形中获取宽度,高度和左上角坐标,刷子对象会为您修改:

function brushed() {

  //use the brush object's values to set the data domains:
  if (brush.empty()) {
      //either the height OR the width is empty
      x.domain( x2.domain() ); //reset X scale
      y.domain( y2.domain() ); //reset Y scale
  }

  var extent = brush.extent();
  x.domain( [extent[0][0] , extent[1][0] ] ); //min and max data X values
  y.domain( [extent[0][1] , extent[1][1] ] ); //min and max data Y values

  //use the brush extent rectangle to get the SVG coordinates:
  var extentRect = d3.select("g.x.brush rect.extent");

  var rangeWidth  = extentRect.attr("width");
  var rangeHeight = extentRect.attr("height");
  var rangeLeft = extentRect.attr("x");
  var rangeTop = extentRect.attr("y");


  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}
Run Code Online (Sandbox Code Playgroud)

如果使用序数比例,则缩放比较复杂,但查找屏幕坐标的复杂程度较低. 这个答案描述了如何使用带有序数比例的画笔进行缩放.但是,由于返回的值.extent()已经在SVG坐标中,如果需要坐标和宽度,则不必使用比例本身进行转换

参考

画笔控件API页面在页面顶部有一组缩略图图像; 点击其中任何一个打开一个工作示例.有关更多讨论,您可能会对本教程感兴趣,并提供另一个很好的示例.

  • 我已经彻底了解了这个话题!+1 (10认同)