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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22873551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 23:56:26  来源:igfitidea点击:

D3.js Brush Controls: getting extent width, coordinates

javascriptd3.js

提问by AgentElevenFifths

I'm using d3.js, and was wondering how I might get the sides, width, coordinates, etc; of the extent. In an example like this http://bl.ocks.org/mbostock/1667367

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

回答by AmeliaBR

Brush.extent()

Brush.extent()

When using a brush control, you access information about the state of the brush using the .extent()method on the brush object.

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

The information returned by the .extent()method depends on what sort of scale(s) you have connected to the brush object.

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

If you have onescale linked (eitheran X-scale ora Y-scale, but not both), then the extent method returns a two-element array of the form [minimum, maximum].

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

If you have bothX and Y scales attached to the brush object, then the extent method returns a nested array of the form [??[xMinimum, yMinimum], [xMaximum, yMaximum]?].

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

But what are these minimum and maximum values? That also depends on the scale. If the scale has a valid .invert(value)method, the minimum and maximum values will be converted into your data domainvalues. For ordinal, threshold and other scales which do not have a simple invertmethod, the brush function returns the values in the coordinate system in effect for the brush element.

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

1. One dimension brush

1.一维笔刷

To answer your question for the specific example you linked to, we need to look at the brush object and scales objects. In that example, the brush is connected to the horizontal scale on the smaller, "context" chart (the x2scale):

要针对您链接到的特定示例回答您的问题,我们需要查看笔刷对象和缩放对象。在该示例中,画笔连接到较小的“上下文”图表(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);

brush's initialisation

刷子的初始化

The brush object created above only exists in the Javascript, not in the document. However, the object is also a function which can be called (similar to the axis functions) in order to create a series of rectangles which will respond to mouse events (these are invisible) and the one "extent" rectangle (which in this example is coloured gray with a white border).

上面创建的brush对象只存在于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

The default size of the invisible rectangles is based on the output range of the X and Y scales. Because this brush doesn't have a Y scale, the constant height and vertical position of the rectangles has to be set explicitly.

不可见矩形的默认大小基于 X 和 Y 比例的输出范围。因为这个画笔没有 Y 刻度,所以必须明确设置矩形的恒定高度和垂直位置。

The initial size of the extent rectangle is based on the extent of the brush object (zero width and height by default). The height of that rectangle is also set in the above code.

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

brush interaction

刷交互

When the user interacts with the brush on screen, the brush object captures those events and (1) updates the width of the "extent" rectangle, (2) calls the function which you associated with the "brush" event in the line .on("brush", brushed).

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

The brushed()function is:

brushed()功能是:

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

The purpose of this brush is to scale the main chart, and this is done by setting the domain of the main chart's X-scale. If the brush has zero-width, brush.empty()returns true and the main chart X-domain is set to the full domain shown in the small chart.

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

However, if the brush has a valid width, the empty test returns false, and the domain is set to the results of brush.extent(). Because the brush is attached to a linear X scale, and no Y scale, the extent is returned in the form [xMin, xMax](in the datanumbers), which is exactly what is needed for setting the domain.

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

Extracting values from brush

从画笔中提取值

If you needed to know the width in the datavalues, it is a simple matter of subtraction:

如果您需要知道数据值的宽度,只需简单的减法即可:

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

However, if you are drawing other elements on screen, you want to know the actual coordinates in the SVG, not just the data values. To do the conversion, you use the same thing you always use to convert from data to SVG coordinates: your scale function. Remembering to use the x2scale that controls the small chart, not the zoomed-in scale of the main chart, that would look like:

但是,如果您在屏幕上绘制其他元素,您想知道 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];


2. X and Y brush

2. X 和 Y 画笔

To re-emphasize, this example is for a brush with one(horizontal / X) scale, which is a linearscale. If you were using both X and Y linear scales, you would need to separate out the X and Y extent values with code like this:

再次强调,此示例适用于具有一个(水平 / 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);
}

Extracting values from brush

从画笔中提取值

If you want to know the coordinates of the top-left point of the rectangle, you'll also need to know whether your Y scale switches the minimum value from top to bottom.

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

Alternately,you could get the width, height, and top left coordinate from the on-screen "extent" rectangle, which the brush object modifies for you:

或者,您可以从屏幕上的“范围”矩形中获取宽度、高度和左上角坐标,画笔对象会为您修改这些矩形:

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

If you are using ordinal scales, it is more complicated for zooming, but less complicated for finding screen coordinates. This answer describes how to use a brush with an ordinal scale to zoom. However, since the values returned by .extent()are already in SVG coordinates, you would not have to use the scale itself to convert back if you want coordinates and width

如果您使用序数比例,缩放会更复杂,但查找屏幕坐标就不那么复杂了。 这个答案描述了如何使用带有顺序比例的画笔来缩放。但是,由于返回的值.extent()已经在 SVG 坐标中,如果您想要坐标和宽度,则不必使用比例本身来转换回来

References

参考

The API page for the brush controlhas a set of thumbnail images at the top of the page; click on any of them to open up a working example. For more discussion, you might be interested in this tutorial with another good example of brushes in action.

画笔控件API页面在页面顶部有一组缩略图;单击其中任何一个以打开一个工作示例。有关更多讨论,您可能对本教程感兴趣,其中包含另一个使用画笔的好示例