散点图

此示例总共包含超过 1000 行代码(此处无法嵌入太多代码)。因此,所有代码都可以在 http://blockbuilder.org/SumNeuron/956772481d4e625eec9a59fdb9fbe5b2 上访问 (或者在 https://bl.ocks.org/SumNeuron/956772481d4e625eec9a59fdb9fbe5b2 上托管 。请注意,bl.ocks.org 使用 iframe,因此要查看调整大小,你需要单击打开的按钮(iframe 的右下角)。由于存在大量代码,因此它已被分解为多个文件,相关的代码段将通过文件名和行号引用。请仔细阅读此示例。

什么使图表?

任何完整的图表都有几个核心组件; 这些包括:

  • 标题
  • 轴标签
  • 数据

根据图表可能还包括其他方面 - 例如图表图例。但是,许多这些元素可以通过工具提示来规避。出于这个原因,有交互式图表特定元素 - 例如在数据之间切换的按钮。

由于我们的图表内容将是交互式的,因此图表本身是动态的 - 例如,当窗口大小改变时调整大小。SVG 是可扩展的,因此你可以只保留当前透视图来缩放图表。但是,根据设置的透视图,即使图表仍有足够的空间(例如,如果宽度大于高度),图表可能会变得太小而无法读取。因此,最好只重绘剩余大小的图表。

此示例将介绍如何动态计算按钮,标题,轴,轴标签的位置,以及处理不同数据量的数据集

建立

组态

由于我们的目标是重用代码,因此我们应该创建一个配置文件来包含图表各方面的全局选项。这种配置文件的一个例子是 charts_configuration.json

如果我们查看这个文件,我们可以看到我已经包含了几个元素,这些元素在制作图表时应该已经有了明确的用途:

  • files(存储我们的图表数据所在的字符串)
  • document_state(当前为我们的图表选择了哪个按钮)
  • chart_ids(我们将制作的图表的 html ID)
  • svg(svg 的选项,例如大小)
  • plot_attributes
    • 标题(设置各种字体属性)
    • 工具提示(设置各种工具提示样式属性)
    • 轴(设置各种字体属性)
    • 按钮(设置各种字体和样式属性)
  • 地块
    • 散射(设置散点图的各个方面,例如点半径)
  • 颜色(要使用的特定调色板)

助手功能

除了设置这些全局方面,我们还需要定义一些辅助函数。这些可以在 helpers.js 下找到

  • ajax_json(同步或异步加载 json 文件)
  • keys(返回给定对象的键 - 相当于 d3.keys()
  • parseNumber(一般编号解析,以防我们不知道是什么类型或数字)
  • typeofNumber(返回数字类型)

index.html

最后我们应该设置我们的 html 文件。出于此示例的目的,我们将图表放在 section 标记中,其中 id 与配置文件中提供的 id 匹配(第 37 行)。由于百分比只有在可以从其父成员计算时才有效,我们还包括一些基本样式(第 19-35 行)

制作散点图

让我们打开 make_scatter_chart.js。现在让我们密切注意第 2 行,其中预定了许多最重要的变量:

  • svg - d3 选择图表的 svg
  • chart_group - d3 选择将放置数据的 svg 内的组
  • canvas - 为方便起见,svg 提取的核心方面
  • 利润 - 我们需要考虑的利润率
  • maxi_draw_space 是我们可以绘制数据的最大 x 和 y 值
  • doc_state - 如果我们使用按钮(在本例中我们是),文档的当前状态

你可能已经注意到我们没有在 html 中包含 svg。因此,在我们对图表做任何事情之前,我们需要添加 svg toindex.html(如果它还不存在)。这是通过函数 make_chart_svg 在文件 make_svg.js 中实现的。看看 make_svg.js,我们看到我们在 svg 宽度和高度的图表配置中使用辅助函数 parseNumber。如果数字是浮点数,它会使 svg 的宽度和高度与其截面的宽度和高度成比例。如果数字是整数,它只会将其设置为整数。

第 6 - 11 行测试 - 实际上 - 如果这是第一次调用,则设置 chart_group(如果是第一次调用,则设置文档状态)。

第 14-15 行通过点击的按钮提取当前选择的数据; 第 16 行 data_extent。虽然 d3 具有提取数据范围的功能,但我更倾向于将数据范围存储在此变量中。

第 27-38 行包含通过制作边距,按钮,标题和轴来设置图表的魔法。这些都是动态确定的,可能看起来有点复杂,所以我们将依次查看每个。

make_margins(在 make_margins.js 中)

我们可以看到边距对象考虑了图表左侧,右侧,顶部和底部的一些空间(分别为 x.left,x.right,y.top,y.bottom),标题,按钮和轴。

我们还看到轴边距在第 21 行更新。

我们为什么要做这个?除非我们指定刻度数,刻度标签刻度尺寸和刻度标签字体大小,否则我们无法计算轴所需的大小。即使这样,我们仍然需要猜测刻度标签和刻度线之间的空间。因此,使用我们的数据制作一些虚拟轴更容易,查看相应的 svg 元素有多大,然后返回大小。

实际上我们只需要 y 轴的宽度和 x 轴的高度,这是存储在 axes.y 和 axes.x 中的。

设置默认边距后,我们计算 max_drawing_space(make_margins.js 中的第 29-34 行)

make_buttons(在 make_buttons.js 中)

该函数为所有按钮创建一个组,然后为每个按钮创建一个组,该组又存储一个圆和文本元素。第 37-55 行计算按钮的位置。它通过查看每个按钮长度的文本是否长于允许我们绘制的空间(第 75 行)来实现此目的。如果是这样,它会将按钮放下一行并更新边距。

make_title(在 make_title.js 中)

make_title 类似于 make_buttons,因为它会自动将图表的标题分成多行,如果需要则可以连字符。它有点 hacky,因为它没有 TeX 的连字方案的复杂性,但它足够好。如果我们需要更多的行,则更新边距。

通过设置按钮,标题和边距,我们可以制作轴。

make_axes(在 make_axes.js 中)

make_axes 的逻辑反映了用于计算虚拟轴所需空间的逻辑。然而,在这里,它增加了轴之间变化的过渡。

最后是我们的散点图

完成所有这些设置后,我们终于可以制作散点图了。由于我们的数据集可能有不同的点数,我们需要考虑到这一点并相应地利用 d3 的进入和退出事件。获取现有点的数量在第 40 行中完成。如果我们有更多数据,或者将额外元素转换到角落,然后在有太多数据的情况下删除它们,则第 45-59 行中的 if 语句会添加更多圆元素。

一旦我们知道我们有正确数量的元素,我们就可以将所有剩余元素转换到正确的位置(第 64 行)

最后,我们在第 67 行和第 68 行添加工具提示。工具提示功能在 make_tooltip.js