目录
> d3在通过平稳过渡的添加交互式和动态元素方面表现出色,通过优雅的编程和语法增强视觉体验和用户参与。
>如何使我的D3可视化互动互动?
>在广泛的领域中,从新闻到新闻业到D3?商业科学。一些常见的用例包括创建交互式图,构建动态图表和图形,可视化复杂的网络以及创建自定义数据驱动的动画。
首页 web前端 js教程 与现代JavaScript和D3的交互式数据可视化

与现代JavaScript和D3的交互式数据可视化

Feb 15, 2025 am 09:41 AM

与现代JavaScript和D3的交互式数据可视化

>在本文中,我想带您完成我最近构建的示例项目 - a完全原始的使用D3库的可视化类型,该类型展示了这些组件中的每个组件如何累加以使D3一个很棒的图书馆。

D3代表数据驱动的文档。这是一个JavaScript库,可用于制作各种出色的数据可视化和图表。

>如果您曾经看过《纽约时报》中的任何出色的互动故事,那么您已经看到了D3的行动。您还可以在此处查看使用D3构建的一些很棒的项目。>

>学习曲线对于进入图书馆的启动非常陡峭,因为D3有一些特殊的怪癖,您可能从未见过。但是,如果您可以超越足够的D3学习的第一阶段,那么您很快就可以为自己构建一些非常酷的东西。

>

>有三个主要因素确实使D3在那里的任何其他库中脱颖而出:

  1. 灵活性。 D3允许您获取任何类型的数据,并将其与浏览器窗口中的形状直接关联。这些数据可以是绝对的>,允许大量有趣的用例创建完全原始的可视化。 优雅。在更新之间添加具有
  2. 平滑过渡>的交互式元素很容易。图书馆的书面形式是精美的
  3. ,一旦您掌握了语法,就可以很容易地保持代码清洁和整洁。> 社区。已经有一个庞大的生态系统,它已经使用了D3,他们很容易在线共享他们的代码。您可以使用bl.ocks.org和blockbuilder.org等网站快速查找其他人的预先编写代码,并将这些摘要直接复制到您自己的项目中。> 钥匙要点
  4. 代表数据驱动的文档的
  5. d3是一个强大的JavaScript库,用于创建多样化和交互式数据可视化,如它在纽约时报等平台中的广泛使用所证明的。
库提供了无与伦比的灵活性,使开发人员可以将任何类型的数据绑定到浏览器中的图形表示,从而在可视化设计中促进创造力。

> d3在通过平稳过渡的添加交互式和动态元素方面表现出色,通过优雅的编程和语法增强视觉体验和用户参与。

    >一个强大的开发人员社区支持D3,在Bl.ocks.org等平台上提供了丰富的共享代码和示例资源,可以利用这些代码和项目开发。 该教程详细介绍了收入分布创新可视化的创建,利用D3的功能动态操纵和呈现数据,根据实际数据值调整视觉元素(例如饼图半径)。
  • 该项目通过借贷和调整现有代码进行迭代开发,证明了D3的适应性和社区在编码中的重要性,然后转化为动态和交互式增强。
  • 最终的交互式可视化包括播放/暂停按钮和用于年度选择的滑块等功能,说明了如何使用D3来使数据可视化不仅提供信息,而且可以吸引。
  • 项目
  • 作为大学的经济学专业,我一直对收入不平等感兴趣。我上了几门关于这个主题的课程,这让我感到震惊,因为它应该完全理解。
  • >我开始使用Google的公共数据资源管理器探索收入不平等……>
  • 调整通货膨胀时,尽管每工业生产力一直在飙升,但家庭收入在40%的社会中保持了几乎恒定的。它确实是最高的20%,它获得了更多的好处(在该括号内,如果您看着前5%的前5%,那么差异更加令人震惊)。

    这是我想以令人信服的方式传播的信息,这为使用一些D3.js提供了绝佳的机会,所以我开始绘制一些想法。

    >

    素描

    因为我们正在与D3合作,所以我或多或少可以开始绘制我能想到的任何东西

    。制作简单的线图,条形图或气泡图非常容易,但是我想做一些不同的东西。 >我发现人们倾向于用作对不平等问题的担忧的最常见类比是“如果馅饼变大,那么还有更多事情要解决”。直觉是,如果GDP的总份额在很大程度上增加了,那么即使有些人获得了pie的较薄

    ,但它们仍然会更好地

    > 🎜>。但是,正如我们所看到的,馅饼完全有可能变得更大让人们总体上变得更少。 我可视化这些数据的第一个想法看起来像这样:

    的想法是,我们将拥有此脉动饼图,每个切片代表美国收入分配的五分之一。每个派片的面积与该人口的收入收入有关,图表的总面积将代表其总GDP。 但是,我很快遇到了一些问题。事实证明,人的大脑在区分不同区域的大小方面非常差。当我更具体地将其映射出来时,该消息并没有像应该如此明显的地方:>

    与现代JavaScript和D3的交互式数据可视化

    >在这里,实际上,最贫穷的美国人随着时间的流逝而变得更加富裕,这证实了似乎直觉上的真实。我再考虑这个问题,我的解决方案涉及保持每个弧的角度恒定的角度,每个弧的半径动态变化。

    这是在实践中最终寻找的方式:

    与现代JavaScript和D3的交互式数据可视化

    >我想指出,此图像仍然倾向于低估这里的效果。如果我们使用一个简单的条形图,效果将会更加明显:

    但是,我致力于做出独特的可视化,我想将此消息锤回回家,即

    pie 可以得到更大的> ,而ashare> share>它可以得到较小的。现在我有了我的主意,是时候用D3构建它了。>

    >借用代码

    >所以,现在我知道要构建什么,是时候进入该项目的真正肉了,然后开始编写一些代码

    >您可能会认为我会从头开始编写我的前几行代码行,但是您错了。这是D3,由于我们正在与D3合作,因此我们总是可以从社区中找到一些预先编写的代码,以使我们脱颖而出。>

    >我们正在创建全新的东西,但是它与常规饼图有很多共同点,因此我快速查看了bl.ocks.org,我决定使用Mike Bostock的经典实施, D3的创造者之一。该文件可能已经复制了数千次,而写它的人是带有JavaScript的真正向导,因此我们可以确定我们已经从一个不错的代码开始了。

    此文件写在D3 V3中,该文件现在已经过时了两个版本,因为版本5最终在上个月发布。 D3 V4的一个很大的变化是,库切换到使用平坦的名称空间,因此比例功能诸如d3.scale.ordinal()的编写一样,就像d3.scaleordinal()相反。在版本5中,最大的更改是,数据加载函数现在是按照承诺构造的,这使得更容易一次处理多个数据集。

    > 为了避免混乱,我已经遇到了创建此代码的更新V5版本的麻烦,我已将其保存在blockbuilder.org上。我还将语法转换为适合ES6惯例,例如将ES5匿名函数切换到箭头函数。

    这是我们已经开始的:

    >

    然后,我将这些文件复制到我的工作目录中,并确保我可以在自己的计算机上复制所有内容。如果您想自己跟随本教程,那么您可以从我们的GitHub仓库中克隆该项目。您可以从文件启动器.html中的代码开始。请注意,您将需要一台服务器(例如该服务器)来运行此代码,因为它依赖于Fetch API检索数据。

    >让我快速介绍此代码的工作原理。

    浏览我们的代码

    与现代JavaScript和D3的交互式数据可视化首先,我们在文件顶部声明了一些常数,我们将使用该常数来定义饼图的大小:

    >这使我们的代码超级重复使用,因为如果我们想使其更大或更小,那么我们只需要担心在此处更改这些值。

    >

    接下来,我们将SVG画布附加到屏幕上。如果您对SVG的了解不多,那么您可以将画布视为我们可以绘制形状的页面上的空间。如果我们尝试在该区域之外绘制SVG,那么它根本不会出现在屏幕上:>

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>我们正在用图表区域的ID抓住一个空的DIV,并致电D3.Select()。我们还使用d3.append()方法将SVG画布附加,并且使用d3.attr()方法为其宽度和高度设置了一些尺寸。

>我们还将SVG组元素附加到此画布上,这是一种特殊类型的元素,我们可以将其用于将元素构造在一起。这使我们可以使用组元素的转换属性将整个可视化转移到屏幕的中心。

之后,我们正在设置一个默认量表,我们将使用该量表来为我们的派的每一个分配新颜色:

>

接下来,我们有几行设置了D3的派布局:>

在D3中,布局是我们可以在一组数据中调用的特殊功能。一个布局函数以特定格式接收一系列数据,并使用一些自动生成的值吐出
<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
转换的数组

,然后我们可以用。 然后,我们需要定义一个可以用来绘制弧的路径生成器。路径生成器允许我们在Web浏览器中绘制路径SVG。 D3真正要做的就是将数据与屏幕上的形状相关联,但是在这种情况下,我们要定义更复杂的形状,而不是简单的圆或正方形。路径SVG通过定义在之间绘制线路的路由来工作,我们可以使用其D属性来定义。

这可能是:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>

d属性包含一个特殊的编码,可以让浏览器绘制我们想要的路径。如果您真的想知道此字符串的含义,则可以在MDN的SVG文档中找到它。对于D3中的编程,我们实际上不需要了解此特殊编码的任何信息,因为我们的发电机会为我们吐出D属性,我们只需要使用一些简单的参数来初始化。 对于弧线,我们需要为我们的路径发生器一个Innerradius和像素中的外段值,并且发电机将分类为我们计算每个角度的复杂数学:

>

对于我们的图表,我们为Innerradius使用了零值,这为我们提供了标准的饼图。但是,如果我们想绘制甜甜圈图,那么我们要做的就是插入一个小于我们的outerradius值的值。
<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>

>几次函数声明后,我们将使用d3.json()函数加载数据:>

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
在D3版本5.x中,呼叫d3.json()返回诺言,这意味着D3将获取它在我们给它的相对路径上找到的JSON文件的内容,并执行该功能加载后,我们将在The The The The The The The()方法中调用。然后,我们可以访问我们在回调的数据参数中查看的对象。>

>我们还在此处传递函数参考 - 类型 - 它将转换我们加载成数的所有值,我们可以稍后使用:>

>

<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
如果我们添加console.log(data);向我们的d3.json回调的口头声明,我们可以查看我们现在正在使用的数据:>

我们的数据在这里分为两个不同的数组,分别代表我们的苹果和橘子数据。
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>

>使用此行,我们将在单击我们的一个无线电按钮时切换我们正在查看的数据:

>

>我们还需要在可视化的第一次运行中调用update()函数,以传递初始值(带有“苹果”数组)。
<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>让我们看一下我们的update()函数在做什么。如果您是D3的新手,这可能会引起一些困惑,因为它是D3最困难的部分之一……>
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span>
</span>  <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span>
</span><span><span><span></svg</span>></span>
</span>
登录后复制
登录后复制
登录后复制
登录后复制

>首先,我们使用默认函数参数作为值。如果我们将参数传递到我们的update()函数(当我们第一次运行时),我们将使用该字符串,否则我们将从单击事件中获得所需的值我们的无线电输入。

然后,我们正在使用D3中的常规更新模式
<span>const arc = d3.arc()
</span>  <span>.innerRadius(0)
</span>  <span>.outerRadius(radius);
</span>
登录后复制
登录后复制
登录后复制
来处理我们的弧的行为。这通常涉及执行数据加入,退出旧元素,更新屏幕上的现有元素,并添加添加到我们数据中的新元素。在此示例中,我们不必担心退出元素,因为我们在屏幕上始终具有相同数量的饼片。

首先,有我们的数据加入:

>每次我们的可视化更新时,这都会将新的数据与我们的SVG在屏幕上关联。我们将数据(“苹果”或“橙色”的数组)传递到我们的PIE()布局函数中,该功能正在计算一些开始角度和端角,可用于绘制我们的弧线。现在,此路径变量包含屏幕上所有弧的特殊

虚拟选择

。 接下来,我们将更新数据数组中仍然存在的屏幕上的所有SVG。我们在此处添加了一个过渡 - D3库的绝妙功能 - 传播这些更新超过200毫秒:>

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>我们在d3.transition()呼叫上使用attrtwien()方法来定义D3应使用的自定义过渡,以更新其每个ARC的位置(使用D属性过渡)。如果我们试图将过渡到大多数属性添加过渡,但是我们需要这样做,但是我们需要这样做以在不同的路径之间过渡。 D3无法真正弄清楚如何在自定义路径之间过渡,因此我们使用Arctween()函数来让D3知道如何在每时每刻都应绘制我们的每条路径。

>

这是此功能的样子:

<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

我们在此处使用d3.interpaly()来创建所谓的插装器。当我们调用我们存储在I变量中的函数,值在0到1之间,我们将获得一个介于此之间的值。_current和a。在这种情况下,this._current是一个包含我们正在查看的PIE切片的开始和末端角度的对象,A表示我们正在更新为。

>一旦我们设置了插装器,我们就会更新this._current值,以包含我们在末尾所拥有的值(i(a)),然后我们正在返回一个将计算计算的函数基于此t值,我们的弧应包含的路径。我们的过渡将在其时钟的每个刻度上运行此函数(通过0到1之间的参数),此代码将意味着我们的过渡将在任何时间点都知道我们的弧线应在哪里绘制。

>

>最后,我们的update()函数需要添加在以前的数据阵列中没有的新元素:>

这个代码块将设置我们每个弧的初始位置,这是第一次运行此更新功能。此处的Enter()方法为我们提供了需要添加到屏幕中的所有元素,然后我们可以使用Attr()方法循环浏览这些元素,以设置每个元素的填充和位置弧。我们还为每个弧线提供了一个白色边框,这使我们的图表看起来有些整洁。最后,我们将这些弧的每一个的current属性设置为数据中的初始值,我们在arctween()函数中使用。
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>不用担心您是否无法完全遵循它的工作原理,因为它是D3中的一个相当高级的话题。这个库的伟大是,您不需要了解其所有内部工作,就可以用它创建一些强大的东西。只要您能理解需要更改的位,就可以抽象一些并不是完全必不可少的细节。

>

将我们带到了过程中的下一步……

适应代码

>现在我们在本地环境中有一些代码,并且我们了解它在做什么,我将切换我们正在查看的数据,以便它可以与我们感兴趣的数据一起使用。

>我已经包含了我们将在项目的数据/文件夹中使用的数据。由于此新的incomes.csv文件这次是CSV格式(这是可以使用Microsoft Excel打开的文件),因此我将使用d3.csv()函数,而不是D3.json( )函数:

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此函数基本上与D3.json()基本相同 - 将我们的数据转换为我们可以使用的格式。我还将type()initializer函数作为这里的第二个参数删除,因为这是我们旧数据的特定于。

>如果将Console.Log(Data)语句添加到D3.CSV回调的顶部,则可以看到我们正在使用的数据的形状:>

>我们有50个项目的数组,每个项目都代表我们的数据一年。然后,我们每年都有一个对象,其中五个收入组中的每个集团以及其他一些领域都有数据。我们可以在这里创建一个饼图,这是这些年之一,但是首先,我们需要稍微绕过我们的数据,以便以正确的格式。当我们想编写与D3连接的数据时,我们需要传递一个数组,每个项目都将绑定到SVG。
<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
回想一下,在我们的最后一个示例中,我们有一个数组,其中包含一个项目,适用于要在屏幕上显示的每个派。将此与我们目前拥有的东西进行比较,这是一个对象,其钥匙为1至5,代表我们要绘制的每个派。

> 为了解决此问题,我将添加一个称为repardata()的新函数以替换我们以前拥有的type()函数,该功能将在加载时迭代我们的每个数据:>

>每年,此功能将返回具有值数组的对象,我们将将其传递到我们的数据加入中。我们将这些值中的每一个都标记为名称字段,并且根据我们已经拥有的收入价值,我们为它们提供了数值。我们还在跟踪比较每年的平均收入。

>在这一点上,我们的数据格式可以使用:

>
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>我将在数据中的第一年生成图表,然后我会担心在剩下的几年中更新它。

>

>目前,我们的数据始于2015年,在1967年结束,因此我们需要扭转此数组,然后才能做其他任何事情:

<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

与普通饼图不同,对于我们的图形,我们要固定每个弧的角度,并且随着可视化更新的变化,半径更改。为此,我们将更改PIE布局上的Value()方法,以便每个派slice始终具有相同的角度:

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
接下来,每次可视化更新时,我们都需要更新半径。为此,我们需要提出一个可以使用的量表。比例尺是D3中的一个函数,在两个值之间采用

input 输入,我们作为域传递,然后在两个不同的值之间吐出>输出作为范围。这是我们将使用的规模:

>
<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>一旦我们可以访问数据,我们就会添加这个量表,我们说我们的投入应在0到我们数据集中最大的价值之间,这是去年最富有的群体的收入在我们的数据中(数据[49]。值[4]。值)。对于域,我们设置了我们的输出值应范围的间隔。

这意味着零的输入应给我们一个像素值为零,并且数据中最大值的输入应为我们提供宽度或高度值的一半值,以较小。 >

请注意,我们还在此处使用

平方的根刻度

。我们这样做的原因是,我们希望我们的馅饼切片区域与每个小组的收入成正比,而不是半径。由于区域=πr2>,我们需要使用平方根刻度来解释这一点。 然后,我们可以使用此量表来更新Update()函数中的ARC Generator的Outerradius值:>

>每当我们的数据更改时,这将编辑我们要用于每个弧线的半径值。

>当我们最初设置弧发生器时,我们还应该删除对Outerradius的呼叫,以便我们将其放在文件的顶部:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>

>最后,我们需要对此update()函数进行一些编辑,以便所有内容都与我们的新数据相匹配:>

>由于我们不再使用我们的收音机按钮,所以我只是通过致电我们要使用的年度对象:
<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>最后,我将删除我们为表单输入设置的事件侦听器。如果一切都计划在计划中,我们的数据中应该有一张漂亮的图表:>
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span>
</span>  <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span>
</span><span><span><span></svg</span>></span>
</span>
登录后复制
登录后复制
登录后复制
登录后复制

<span>const arc = d3.arc()
</span>  <span>.innerRadius(0)
</span>  <span>.outerRadius(radius);
</span>
登录后复制
登录后复制
登录后复制
使其动态

下一步是在不同年份之间拥有我们的可视化周期,以表明收入如何随着时间的流逝而变化。我们将通过添加呼叫JavaScript的setInterval()函数来做到这一点,我们可以用它来重复执行某些代码:

> 与现代JavaScript和D3的交互式数据可视化

>我们在此时间变量中设置了一个计时器,每200ms,此代码将运行step()函数,该函数将将我们的图表更新为明年的数据,并将计时器递增1。如果计时器它的价值为49(我们的数据中的最后一年),它将自身重置。现在,这为我们提供了一个不错的循环,它将连续运行:

与现代JavaScript和D3的交互式数据可视化

使事情更有用。我还将添加一些标签,这些标签为我们提供了原始数字。我将用以下方式替换文件正文中的所有HTML代码

<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>我们正在使用Bootstrap的网格系统在此处构建页面,这使我们可以将页面元素整洁地格式化为框。

然后,每当我们的数据更改时,我将使用jQuery更新所有这些:>

>我还将对我们文件顶部的CSS进行一些编辑,这将为我们提供每个弧的传奇,并以我们的标题为中心:>

<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
我们最终得到的是相当可观的东西:

<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>很难看到这些弧线随着时间的推移如何变化,所以我想添加一些网格线来显示我们数据第一年的收入分布的样子:>

与现代JavaScript和D3的交互式数据可视化>我正在使用array.foreach()方法来完成此操作,尽管我也可以再次使用D3的常规

常规更新模式

(join/exit/exit/extim/update/enter)。

>
<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>我还想添加一行以显示美国的平均收入,我每年都会更新。首先,我将首次添加平均线:

> >然后,我将在UPDATE()函数的末尾更新此版本。

>我应该注意,对于我们来说,在我们的第一个call to Update()之后,添加每个圆圈

很重要,因为否则它们最终会在每个圈子后面渲染
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span>
</span>  <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span>
</span><span><span><span></svg</span>></span>
</span>
登录后复制
登录后复制
登录后复制
登录后复制
>

>我们的弧路径(SVG层取决于将它们添加到屏幕的顺序,而不是通过其z索引)。

>在这一点上,我们有一些传达我们正在使用的数据,这些数据更清楚地:
<span>const arc = d3.arc()
</span>  <span>.innerRadius(0)
</span>  <span>.outerRadius(radius);
</span>
登录后复制
登录后复制
登录后复制
>

使其互动

作为最后一步,我希望我们添加一些控件,以使用户挖掘到特定年份。我想添加a

play/暂停

按钮,以及一年的滑块,允许用户选择特定的日期来查看。

与现代JavaScript和D3的交互式数据可视化>这是我用来将这些元素添加到屏幕上的HTML:>

>我们需要在这两个元素中添加一些事件听众,以设计我们要寻找的行为。

首先,我想定义我们的按钮的行为。我们需要替换提前为间隔编写的代码,以便我们使用按钮停止并启动计时器。我假设可视化始于“暂停”状态,我们需要按下此按钮以拉开序幕。
<span>const width = 540;
</span><span>const height = 540;
</span><span>const radius = Math.min(width, height) / 2;
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>每当我们的按钮单击时,我们的if/else block在这里将定义不同的行为,具体取决于我们的按钮是“播放”按钮还是“暂停”按钮。如果我们单击的按钮说“播放”,我们将按钮更改为“暂停”按钮,然后开始我们的间隔循环。另外,如果按钮是“暂停”按钮,我们将其文本更改为“ play”,我们将使用clearInterval()函数来阻止循环运行。

>

对于我们的滑块,我想使用jQuery UI库随附的滑块。我将其包含在我们的HTML中,并且我将写几行以将其添加到屏幕上:>

<span>const svg = d3.select("#chart-area")
</span>  <span>.append("svg")
</span>    <span>.attr("width", width)
</span>    <span>.attr("height", height)
</span>  <span>.append("g")
</span>    <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>在这里,我们使用幻灯片选项将事件侦听器连接到滑块。每当我们的滑块转移到另一个值时,我们都会将计时器更新到此新值,并且在当年的数据中运行了Update()函数。

>我们可以在Update()函数末尾添加此行,以便我们的滑块移动到我们的循环运行时正确的一年:

>我还将在我们的UpdateHtml()函数(每当我们的可视化更改时运行)添加一行,该功能可以根据数据中的当年调整标签的值
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

>我将向我们的CSS扔几行,以使一切看起来有些整洁:

<span>const pie = d3.pie()
</span>  <span>.value(d => d.count)
</span>  <span>.sort(null);
</span>
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
>我们拥有它 - 我们的成品 - 一个功能齐全的交互式数据可视化,一切都按预期工作。

<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span>
</span>  <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span>
</span><span><span><span></svg</span>></span>
</span>
登录后复制
登录后复制
登录后复制
登录后复制

希望,本教程展示了D3的真实力量,让您绝对创建任何您可以想象的东西。

>从头开始始终是一个艰难的过程,但是奖励值得。如果您想学习如何创建自己的自定义可视化,这里有一些在线资源,您可能会发现有帮助:与现代JavaScript和D3的交互式数据可视化>

  • > SitePoint的D3.js内容的概述
  • > D3主页上的图书馆简介。这是通过一些最基本的命令运行的,向您展示了如何在D3中进行第一个步骤。
  • >
  • >“让我们制作条形图” Mike Bostock(D3的创建者) - 向初学者展示了如何制作图书馆中最简单的图表之一。 Elijah Meeks($ 35)的
  • d3.js,这是一本可靠的介绍性教科书。 D3的Slack频道非常欢迎D3的新移民。它还有一个“学习材料”部分,并收集了大量资源。
  • >
  • >此在线Udemy课程(20美元),该课程涵盖了图书馆中的所有内容。这针对JavaScript开发人员,包括四个很酷的项目。
  • 在bl.ocks.org和blockbuilder.org。
  • D3 API参考,它对D3提供的所有内容提供了详尽的技术解释。
  • >不要忘记,如果您想查看我在文章中使用的代码的完成版本,那么您可以在我们的GitHub repo上找到它。
  • >
  • >与JavaScript和D3
  • >的交互式数据可视化的经常询问问题(常见问题解答)
  • > D3在交互式数据可视化中的意义是什么?
d3(代表数据驱动的文档)是一个JavaScript库,该库是广泛用于创建交互式数据可视化的JavaScript库。它允许您将任意数据绑定到文档对象模型(DOM),然后将数据驱动的转换应用于文档。 D3不是一个单层框架,它试图提供所有可以想象的功能。取而代之的是,它解决了问题的关键:根据数据有效操纵文档。这避免了专有表示形式,并具有非凡的灵活性,揭示了HTML,SVG和CSS等网络标准的全部功能。

> D3与其他JavaScript库有何不同?之所以独特,是因为它使您可以灵活地创建其他库无法使用的数据可视化。它使您可以直接操纵DOM,这意味着您可以完全控制可视化的最终外观。 D3还使用声明的方法,这意味着您定义了想要最终结果的外观,而D3算出了如何到达那里。

>

我可以将D3用于大数据集吗?是的,D3能够处理大型且复杂的数据集。它具有强大的数据操作功能,可让您以任何格式使用数据。 D3还具有用于从不同来源加载数据的内置功能,使其更容易与您的现有数据基础结构集成。>

>如何使我的D3可视化互动互动?

> d3提供了几种将交互性添加到可视化的方法。您可以使用事件侦听器响应诸如点击或鼠标运动之类的用户操作,并且可以使用过渡来对数据进行动画更改。 D3还支持缩放和平移,这对于探索大型数据集可能很有​​用。

>

>在广泛的领域中,从新闻到新闻业到D3?商业科学。一些常见的用例包括创建交互式图,构建动态图表和图形,可视化复杂的网络以及创建自定义数据驱动的动画。

我是否需要知道JavaScript来使用D3? ,对JavaScript有效使用D3是必要的。 D3是一个JavaScript库,因此您需要编写JavaScript代码来创建可视化。但是,D3的API旨在直观且易于学习,因此,即使您不是JavaScript专家,您仍然可以使用D3创建强大的可视化。是的,可以与其他JavaScript库或框架一起使用D3。例如,您可以使用D3来创建使用React或Angular。非常适合实时数据可视化。它具有灵活的数据更新机制,可让您在新数据进来时轻松更新可视化。这使D3成为仪表板或实时数据馈送等应用程序的绝佳选择。

>我如何学习D3? >

>有许多可用于学习D3的资源。 D3官方网站有大量的文档和示例,并且有许多在线教程和课程深度涵盖D3。练习也是关键 - 您使用D3越多,您的概念和API都会变得越舒适。

> d3?

是什么限制,而d3是一个强大的工具,它确实有一些局限性。它需要对JavaScript和Web标准有很好的了解,这可能是初学者的障碍。 D3还为开发人员留下了很多决定,如果您不确定从哪里开始,这可能会令人不知所措。最后,尽管D3能够处理大型数据集,但性能可能会成为一个非常大或复杂的可视化的问题。

以上是与现代JavaScript和D3的交互式数据可视化的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

See all articles