D3 刷分组条形图

2023-12-02

我试图让刷牙工作与此示例类似,但使用分组条形图:http://bl.ocks.org/mbostock/1667367

我对刷牙的工作原理不太了解(我找不到任何好的教程),所以我对出了什么问题有点不知所措。我将尝试在下面包含相关的代码。该图表按天跟踪修复损坏的构建的时间,然后按投资组合进行分组。到目前为止,画笔已创建,用户可以移动和拖动它,但主图表中的条形图被奇怪地重新绘制,并且 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); });

这是画笔功能(尝试几种不同的选项)...

function brushed() {
    main_x1.domain(brush.empty() ? mini_x1.domain() : brush.extent());

    //main.select("rect")
      //.attr("x", function(d) { return d.values; })
      //.attr("width", function(d) { return d.values; });
    bar.select("rect")
      .attr("width", function(d) { return main_x1.rangeBand(); })
      .attr("x", function(d) { return main_x1(d.portfolio); });
      //.attr("y", function(d) { console.log(d); return main_y(d.buildFixTime); })
      //.attr("height", function(d) { return main_height - main_y(d.buildFixTime); });

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

问题来自于尝试使用画笔设置 x 尺度域,当您的 x 尺度是ordinal规模。换句话说,x 轴的预期域是类别列表,而不是最大最小数值范围。所以问题就出在最上面的刷机函数上:

function brushed() {
    main_x0.domain(brush.empty() ? mini_x0.domain() : brush.extent());

设置的域为brush.extent()是一个由两个数字组成的数组,它完全偏离了你的序数范围。

根据维基百科,如果附加到画笔函数的比例之一是序数比例,则返回的值brush.extent()是输出范围内的值,而不是输入域内的值。序数音阶没有invert() method将范围值转换为域值。

因此,您有几种如何继续的选择:

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

您可以创建自己的“反转”函数来找出哪些分类值(日期)mini_x0.domain) 包含在返回的范围内brush.extent()。那么你就必须both重置main_x0.domain仅在轴上包含这些日期,and过滤掉您的矩形以仅绘制这些矩形。

Or你可以离开domain of main_x0.是,并改变range反而。通过扩大图表的范围,可以使条形间隔更大。与剪切路径相结合以切断绘图区域之外的条形,这具有仅显示条形的特定子集的效果,这正是您想要的。

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

因此,如果您的原始 x 范围是从 [0,100] 开始,并且画笔覆盖区域 [20,60],那么您需要一个满足以下条件的新范围:

  • 新范围宽度的20%标记为0;
  • 新范围宽度的 60% 标记为 100。

所以,

  • 新范围的总宽度为 ( (100-0) / (60-20) )*(100-0) = 250;
  • 新范围的起点为 (0 - (20/100)*250) = -50;
  • 新范围的终点位于 (-50) + 250 = 200。

现在您可以自己完成所有代数计算来计算出这种转换。但这实际上只是另一种类型的缩放方程,所以为什么不创建一个new缩放函数在旧范围和放大范围之间进行转换。

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

In code:

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

基于简化代码的工作小提琴(注意:您仍然需要在主图上设置一个剪切矩形):
http://fiddle.jshell.net/CjaD3/1/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

D3 刷分组条形图 的相关文章

随机推荐

  • ggplot2 中的自定义轴刻度标签

    我想展示一个简短的时间序列 显示 22 年来欧洲海洛因缉获量的异质性 然而 某些年份包含不同数量的国家 我想通过在 x 轴上放置每年的 n xx 来在图表中显示这一点 有谁知道我应该怎么做 across time lt ggplot by
  • Dropwizard集成测试找不到资源文件

    对于 dropwizard 来说非常陌生 我正在尝试 完全 创建一个集成测试 以他们为例 https dropwizard github io dropwizard manual testing html public class Logi
  • C# 中的泛型类型推断如何工作?

    如果我有以下代码 private BaseMessage getMessage return new OtherMessage private void CheckType
  • Hangfire VB 启动抛出 SQL 异常

    See 这个 StackOverflow 问题一些背景 Hangfire 看起来对我来说是正确的解决方案 但我在让它发挥作用时遇到了困难 我的开发环境是VB 2010和SQL 2005 不是最新的工具 Public Sub Configur
  • 比较c中字节数组中的任意位序列

    我的 c 代码中有几个 uint8 t 数组 我想将一个数组中的任意序列位与另一个数组进行比较 例如 我有 bitarray 1 和 bitarray 2 我想将 bitarray 1 的位 13 47 与 bitarray 2 的位 5
  • 嵌套 SQL 查询是原子的吗?

    我有一些微服务 几乎 系统 其中每个程序都有自己的端口 此外 并非系统中的所有端口都可用 为简单起见 我决定在 PostgreSQL 的表中保留空闲端口列表 因此 我有这张表 service port sm srv 5600 null 56
  • 在 Swift 中将整数转换为罗马数字字符串

    我正在寻找一个Integer在 Swift 中并将其转换为罗马数字String 有任何想法吗 人们可以写一个扩展Int 与下面看到的类似 请注意 对于小于 1 的数字 此代码将返回 虽然这对于罗马数字来说可能没问题 零不存在 但您可能希望在
  • 使特定用户的会话无效

    因此 对于我的网络应用程序 如果我删除当前登录的用户 并且我想使他 她的会话无效 这样 一旦他 她刷新页面或导航 他们就不再登录 我现在的方式是 如果用户成功登录 我会将用户对象存储在我的SessionScoped豆 并存储HttpSess
  • 聊天客户端表情窗口JAVA

    我一直在致力于创建一个聊天客户端 java swing 并且我刚刚使我的表情符号完全可用 但除了让用户输入 之外 例如 我想提供一个包含所有可用表情符号的弹出窗口 我正在寻找的是一种制作这样一个窗口的方法 例如像 Skype 的那样 我可以
  • 在多个节点实例中共享 IO 对象

    我想在两个节点实例之间共享由 socket io 创建的房间 已经使用 redis store 但无法在不同的节点实例上获取 io sockets in ROOM ID emit MESSAGE DATA 我在尝试 实例A io set s
  • C中的宏如何分配内存?

    我想知道C中的内存是如何分配给 define变量的 define VAR1 10 我有 2 个问题 VAR1 的类型是什么 VAR1 存储在哪个内存段中 VAR1 存储在哪个内存段中 在任何一个细分市场中 VAR1仅在预处理阶段相关 在运行
  • HTML 创建等大小的方形网格图片系统

    如何创建具有相同大小的正方形垂直和水平对齐的图片网格系统 下面是一个 2 x 2 的图片系统 由于某种原因 图像未对齐 如果需要的话 我希望能够稍后自定义正方形 使它们成为具有特定尺寸的矩形 也喜欢使用引导程序
  • Android DOM 解析器 - 从描述标签检索图像链接

    我正在使用 DOM 解析器来解析此 XML feed http loc grupolusofona pt index php format feed 我的解析器对所有标签都工作得很好 我只是缺少能够从描述标签中检索图像的想法 feed 上的
  • 图像的路径和扩展

    我想从iPhone设备获取相册图像的路径a 我还需要该图像的扩展名和他们的名字 newFilePath NSHomeDirectory stringByAppendingPathComponent textFieldNormalFile n
  • 自定义 ItemTemplate 未显示在 Visual Studio 2010 中 - 添加新项

    我之前在 VS2005 2010 中创建过 ItemTemplates 从来没有遇到过任何问题 在 Windows8 上使用 VS 2012 Ultimate 版本时 我正在创建的 ItemTemplate 未显示在 添加新项 列表中 仅尝
  • 定义函数模板特化的正确语法是什么?

    在 C Primer Plus 2001 捷克语翻译 中 我发现了这些不同的模板专业化语法 函数模板 template
  • (BYTE)-1 是什么意思

    我正在阅读别人的代码 define CPUTYPE INVALID BYTE 1 这意味着什么 我想它具有与以下相同的效果 define CPUTYPE INVALID 255 如果我们已经有 typedef unsigned char B
  • 在 ASP.NET 中,内联表达式是在后面的代码之前还是之后执行?

    Do ASP 内联表达式 在执行代码隐藏中的代码之前或之后在服务器上运行 内联代码在 asp net 页面生命周期中预渲染页面之后执行 因此 它可以在某些事情之前运行 也可以在某些事情之后运行 在此处阅读页面生命周期 http msdn m
  • 推送到 GitHub 时出错 - 权限不足,无法将对象添加到存储库数据库

    我在尝试对 GitHub 存储库执行 git Push 时遇到异常错误 Counting objects 8 done Delta compression using 2 threads Compressing objects 100 4
  • D3 刷分组条形图

    我试图让刷牙工作与此示例类似 但使用分组条形图 http bl ocks org mbostock 1667367 我对刷牙的工作原理不太了解 我找不到任何好的教程 所以我对出了什么问题有点不知所措 我将尝试在下面包含相关的代码 该图表按天