Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript D3刷涂分组条形图_Javascript_D3.js_Brush - Fatal编程技术网

Javascript D3刷涂分组条形图

Javascript D3刷涂分组条形图,javascript,d3.js,brush,Javascript,D3.js,Brush,我试图让刷牙工作与此示例类似,但使用分组条形图: 我真的不太了解刷牙是如何工作的(我还没有找到任何好的教程),所以我有点不知道哪里出了问题。我将尝试在下面包含相关的代码位。图表按天跟踪修复损坏的构建的时间,然后按组合分组。到目前为止,画笔已经创建,用户可以移动和拖动它,但主图表中的条形图被奇怪地重新绘制,x轴根本没有更新。如果您能提供任何帮助,我们将不胜感激。多谢各位 // x0 is the time scale on the X axis var main_x0 = d3.scale.ord

我试图让刷牙工作与此示例类似,但使用分组条形图:

我真的不太了解刷牙是如何工作的(我还没有找到任何好的教程),所以我有点不知道哪里出了问题。我将尝试在下面包含相关的代码位。图表按天跟踪修复损坏的构建的时间,然后按组合分组。到目前为止,画笔已经创建,用户可以移动和拖动它,但主图表中的条形图被奇怪地重新绘制,x轴根本没有更新。如果您能提供任何帮助,我们将不胜感激。多谢各位

// x0 is the time scale on the X axis
var main_x0 = d3.scale.ordinal().rangeRoundBands([0, main_width-275], 0.2);
var mini_x0 = d3.scale.ordinal().rangeRoundBands([0, main_width-275], 0.2);

// x1 is the portfolio scale on the X axis
var main_x1 = d3.scale.ordinal();
var mini_x1 = d3.scale.ordinal();

// Define the X axis
var main_xAxis = d3.svg.axis()
    .scale(main_x0)
    .tickFormat(dateFormat)
    .orient("bottom");

var mini_xAxis = d3.svg.axis()
    .scale(mini_x0)
    .tickFormat(dateFormat)
    .orient("bottom");
绑定数据后

// define the axis domains
main_x0.domain(data.result.map( function(d) { return d.date; } )
    .sort(d3.ascending));
mini_x0.domain(data.result.map( function(d) { return d.date; } )
    .sort(d3.ascending));

main_x1.domain(data.result.map( function(d) { return d.portfolio; } )
    .sort(d3.ascending))
    .rangeRoundBands([0, main_x0.rangeBand() ], 0);
mini_x1.domain(data.result.map( function(d) { return d.portfolio; } )
    .sort(d3.ascending))
    .rangeRoundBands([0, main_x0.rangeBand() ], 0);

// Create brush for mini graph
var brush = d3.svg.brush()
  .x(mini_x0)
  .on("brush", brushed);
在添加轴等之后

// Create the bars
var bar = main.selectAll(".bars")
  .data(nested)
.enter().append("g")
  .attr("class", function(d) { return d.key + "-group bar"; })
  .attr("fill", function(d) { return color(d.key); } );

bar.selectAll("rect").append("rect")
  .data(function(d) { return d.values; })
.enter().append("rect")
  .attr("class", function(d) { return d.portfolio; })
  .attr("transform", function(d) { return "translate(" + main_x0(d.date) + ",0)"; })
  .attr("width", function(d) { return main_x1.rangeBand(); })
  .attr("x", function(d) { return main_x1(d.portfolio); })
  .attr("y", function(d) { return main_y(d.buildFixTime); })
  .attr("height", function(d) { return main_height - main_y(d.buildFixTime); });
这里是画笔功能(尝试几个不同的选项)


当x比例为顺序比例时,试图使用画笔设置x比例域会出现问题。换句话说,x轴的预期域是类别列表,而不是最大-最小数值范围。因此,问题就在刷牙功能的顶部:

function brushed() {
    main_x0.domain(brush.empty() ? mini_x0.domain() : brush.extent());
brush.extent()
设置的域是一个由两个数字组成的数组,它完全摆脱了顺序刻度

,如果附加到笔刷函数的其中一个刻度是顺序刻度,则
brush.extent()
返回的值是输出范围内的值,而不是输入域内的值。将范围值转换为域值

因此,您有几个关于如何继续的选项:

您可以使用主x轴的线性时间刻度而不是顺序刻度来重新绘制整个图形。但是,您必须编写自己的函数来计算该轴上每天的宽度,而不能使用
.rangeBand()

您可以创建自己的“反转”函数,以确定哪些分类值(在
mini\u x0.domain
上的日期)包含在
brush.extent()返回的范围内。然后,您必须重置
main\u x0.domain
以仅包含轴上的日期,并过滤出矩形以仅绘制这些矩形

或者您可以离开
main\u x0.
be的域,改为更改范围。通过使图形的范围变大,可以使条形图的间距变大。与用于在打印区域外切断条形图的剪裁路径相结合,这样做的效果是仅显示条形图的某个子集,这正是您想要的

但是新的范围应该是什么呢?
brush.extent()
返回的范围是刷牙矩形的开始和结束位置。如果将这些值用作主图形上的范围,则整个图形将被压缩到该宽度。这与你想要的正好相反。您需要的是将最初填充该宽度的图形区域拉伸以填充整个绘图区域

因此,如果原始x范围为[0100],且笔刷覆盖区域[20,60],则需要满足以下条件的新范围:

  • 新范围宽度的20%标记为0
  • 新范围宽度的60%标记为100
所以,

  • 新范围的总宽度为((100-0)/(60-20))*(100-0)=250
  • 新范围的起点为(0-(20/100)*250)=-50
  • 新范围的末尾为(-50)+250=200
现在你可以自己做所有的代数来计算这个转换。但这实际上只是另一种类型的缩放方程,所以为什么不创建一个新的缩放函数来在旧范围和放大范围之间进行转换呢

具体来说,我们需要一个线性比例,其输出范围设置为绘图区域的实际范围。然后根据要拉伸以覆盖绘图区域的拉丝区域的范围设置域。最后,我们通过使用线性标度来计算顺序标度的范围,从而计算出该范围的原始最大值和最小值与屏幕的距离。从那里,我们可以调整其他顺序比例,重新定位所有矩形

代码:

//Initialization:
var main_xZoom = d3.scale.linear()
    .range([0, main_width - 275])
    .domain([0, main_width - 275]);

//Brushing function:
function brushed() {
    var originalRange = main_xZoom.range();
    main_xZoom.domain(brush.empty() ? 
                     originalRange: 
                     brush.extent() );

    main_x0.rangeRoundBands( [
        main_xZoom(originalRange[0]),
        main_xZoom(originalRange[1])
        ], 0.2);

    main_x1.rangeRoundBands([0, main_x0.rangeBand()], 0);

    bar.selectAll("rect")
        .attr("transform", function (d) {
            return "translate(" + main_x0(d.date) + ",0)";
        })
        .attr("width", function (d) {
            return main_x1.rangeBand();
        })
        .attr("x", function (d) {
            return main_x1(d.portfolio);
        });

    main.select("g.x.axis").call(main_xAxis);
}
基于简化代码工作fiddle(注意:您仍然需要在主绘图上设置一个剪切矩形):

看起来您在
rect
元素中添加了
rect
元素--您不需要这样做。另外,您可能需要
bar。在
brushed
函数中选择all(“rect”)
。看起来您正在更新
main_x1
的域,然后使用不同的比例重新绘制
main_xAxis
。好的,这很有意义,但是当我将域更改为main_x0时,我得到了以下错误:uncaughttypeerror:object113没有方法“getDay”,你能提供一个完整的例子来说明这个问题吗?你能把它缩小到一个最小的例子吗?回购协议中有很多代码,其中大部分与此无关。嗨,拉尔斯,这里有一个简化版本:再次感谢。这是一个有趣的谜题。事后看来,我很遗憾建议()使用顺序刻度而不是时间刻度。实际上,使用时间刻度并不难,您只需要通过查找连续两天的刻度值之间的差值来获得每个日簇的宽度。@AmeliaBR对于这个示例,我感激不尽。这是非常好的,正是我需要开始的。多谢各位@这是一个令人敬畏的解释;非常感谢。
//Initialization:
var main_xZoom = d3.scale.linear()
    .range([0, main_width - 275])
    .domain([0, main_width - 275]);

//Brushing function:
function brushed() {
    var originalRange = main_xZoom.range();
    main_xZoom.domain(brush.empty() ? 
                     originalRange: 
                     brush.extent() );

    main_x0.rangeRoundBands( [
        main_xZoom(originalRange[0]),
        main_xZoom(originalRange[1])
        ], 0.2);

    main_x1.rangeRoundBands([0, main_x0.rangeBand()], 0);

    bar.selectAll("rect")
        .attr("transform", function (d) {
            return "translate(" + main_x0(d.date) + ",0)";
        })
        .attr("width", function (d) {
            return main_x1.rangeBand();
        })
        .attr("x", function (d) {
            return main_x1(d.portfolio);
        });

    main.select("g.x.axis").call(main_xAxis);
}