wps图表中如何插入甘特图

by Déborah Mesquita

由DéborahMesquita

如何通过使用D3可视化数据集来构建类似甘特图的图表 (How to build a Gantt-like chart by using D3 to visualize a dataset)

When you finish learning about the basics of D3.js, usually the next step is to build visualizations with your dataset. Because of how D3 works, the way we organize the dataset can make our lives really easy or really hard.

当您学习完D3.js的基础知识后,通常下一步就是使用数据集构建可视化。 由于D3的工作方式,我们组织数据集的方式可以使我们的生活变得轻松或艰难。

In this article we will discuss different aspects of this building process. To illustrate these aspects, we will build a visualization that is similar to a Gantt chart.

在本文中,我们将讨论此构建过程的不同方面。 为了说明这些方面,我们将建立类似于甘特图的可视化效果。

The most important lesson I learned is that you need to build a dataset where each datapoint equals a data unity of your graph. Let’s dive into our case study to see how this works.

我学到的最重要的一课是, 您需要构建一个数据集,其中每个数据点都等于图形的数据单位 。 让我们深入研究案例研究以了解其工作原理。

The goal is to build a Gantt-like chart similar to the one below:

目标是建立类似于以下甘特图的图表:

As you can see, it’s not a Gantt chart because the tasks start and finish on the same day.

如您所见,它不是甘特图,因为任务在同一天开始和结束。

创建数据集 (Creating the dataset)

I extracted the data from minutes. For each text file, I received information about the projects and their statuses from meetings. At first, I structured my data like this:

我从几分钟提取数据。 对于每个文本文件,我从会议中收到有关项目及其状态的信息。 首先,我将数据结构如下:

{    "meetings": [{            "label": "1st Meeting",            "date": "09/03/2017",            "projects_presented": [],            "projects_approved": ["002/2017"],            "projects_voting_round_1": ["005/2017"],            "projects_voting_round_2": ["003/2017", "004/2017"]        },        {            "label": "2nd Meeting",            "date_start": "10/03/2017",            "projects_presented": ["006/2017"],            "projects_approved": ["003/2017", "004/2017"],            "projects_voting_round_1": [],            "projects_voting_round_2": ["005/2017"]        }    ]}

Let’s take a closer look at the data.

让我们仔细看看数据。

Each project has 4 statuses: presented, voting round 1, voting round 2 and approved. In each meeting, the status for the projects can or can not change. I structured the data by grouping them by meetings. This grouping gave us a lot of problems when we built the visualization. This was because we needed to pass data to nodes with D3. After I saw the Gantt chart that Jess Peter built here, I realized I needed to change my data.

每个项目都有4个状态:已presentedvoting round 1 voting round 2approved 。 在每次会议中,项目的状态都可以更改,也可以不更改。 我通过按会议对数据进行分组来构造数据。 建立可视化时,这种分组给我们带来了很多问题。 这是因为我们需要将数据传递到具有D3的节点。 看到Jess Peter 在这里建立的甘特图后,我意识到我需要更改数据。

What was the minimum information I wanted to display? What was the minimum node? Looking at the picture, it is the information of the project. So I changed the structure of the data to the following:

我想显示的最少信息是什么? 最小节点是多少? 看图片,这是项目的信息。 因此,我将数据的结构更改为以下内容:

{  "projects": [                  {                    "meeting": "1st Meeting",                    "type": "project",                    "date": "09/03/2017",                    "label": "Project 002/2017",                    "status": "approved"                  },                  {                    "meeting": "1st Meeting",                    "type": "project",                    "date": "09/03/2017",                    "label": "Project 005/2017",                    "status": "voting_round_1"                  },                  {                    "meeting": "1st Meeting",                    "type": "project",                    "date": "09/03/2017",                    "label": "Project 003/2017",                    "status": "voting_round_2"                  },                  {                    "meeting": "1st Meeting",                    "type": "project",                    "date": "09/03/2017",                    "label": "Project 004/2017",                    "status": "voting_round_2"                  }               ]}

And everything worked better after that. It's funny how the frustration disappeared after this simple change.

在那之后一切都变好了。 有趣的是,在进行了简单的更改后,挫折感消失了。

创建可视化 (Creating the visualization)

Now that we have the dataset, let’s start building the visualization.

现在我们有了数据集,让我们开始构建可视化。

创建x轴 (Creating the x-axis)

Each date should be displayed in the x-axis. To do that, define d3.timeScale() :

每个日期都应显示在x轴上。 为此,定义d3.timeScale()

var timeScale = d3.scaleTime()                .domain(d3.extent(dataset, d => dateFormat(d.date)))                .range([0, 500]);

The minimum and maximum values are given in the arrayd3.extent().

最小值和最大值在数组d3.extent()

Now that you have timeScale , you can call the axis.

现在有了timeScale ,您可以调用轴了。

var xAxis = d3.axisBottom()                .scale(timeScale)                .ticks(d3.timeMonth)                .tickSize(250, 0, 0)                .tickSizeOuter(0);

The ticks should be 250px long. You don’t want the outer tick. The code to display the axis is:

刻度线应为250px长。 您不需要外部刻度线。 显示轴的代码是:

d3.json("projects.json", function(error, data) {            chart(data.projects);});
function chart(data) {    var dateFormat = d3.timeParse("%d/%m/%Y");
var timeScale = d3.scaleTime()                   .domain(d3.extent(data, d => dateFormat(d.date)))                   .range([0, 500]);
var xAxis = d3.axisBottom()                  .scale(timeScale)                  .tickSize(250, 0, 0)                  .tickSizeOuter(0);
var grid = d3.select("svg").append('g').call(xAxis);}

If you plot this, you can see that there are many ticks. In fact, there are ticks for each day of the month. We want to display only the days that had meetings. To do that, we will set the tick values explicitly:

如果绘制此图,则可以看到有许多刻度线。 实际上,每月的每一天都有刻度。 我们只想显示开会的日期。 为此,我们将显式设置刻度值:

let dataByDates = d3.nest().key(d => d.date).entries(data);let tickValues = dataByDates.map(d => dateFormat(d.key));
var xAxis = d3.axisBottom()                .scale(timeScale)                .tickValues(tickValues)                .tickSize(250, 0, 0)                .tickSizeOuter(0);

Using d3.nest() you can group all the projects by date (see how handy it is to structure the data by projects?), and then get all the dates and pass it to the axis.

使用d3.nest()您可以按日期对所有项目进行分组(请参见按项目对数据进行结构化有多方便?),然后获取所有日期并将其传递给轴。

放置项目 (Placing the projects)

We need to place the projects along the y-axis, so let’s define a new scale:

我们需要沿y轴放置项目,所以让我们定义一个新的比例尺:

yScale = d3.scaleLinear().domain([0, data.length]).range([0, 250]);

The domain is the number of projects. The range is the size of each tick. Now we can place the rectangles:

域是项目数。 范围是每个刻度的大小。 现在我们可以放置矩形:

var projects = d3.select("svg")                   .append('g')                   .selectAll("this_is_empty")                   .data(data)                   .enter();
var innerRects = projects.append("rect")              .attr("rx", 3)              .attr("ry", 3)              .attr("x", (d,i) => timeScale(dateFormat(d.date)))              .attr("y", (d,i) => yScale(i))              .attr("width", 200)              .attr("height", 30)              .attr("stroke", "none")              .attr("fill", "lightblue");

selectAll(), data(), enter() and append() always get tricky. To use the enter() method (in order to create a new node from a datapoint), we need a selection. That’s why we need selectAll("this_is_empty)", even if we don’t have anyrect yet. I've used this name to clarify that we only need the empty selection. In other words, we use selectAll("this_is_empty)" to get an empty selection we can work on.

selectAll()data()enter()append()总是很棘手。 要使用enter()方法(为了从数据点创建新节点),我们需要进行选择。 这就是为什么我们需要selectAll("this_is_empty)" ,即使我们还没有任何rect 。 我用这个名字来说明我们只需要空选择。 换句话说,我们使用selectAll("this_is_empty)"来获得我们可以处理的空选择。

The variable projects has empty selections bounded to data, so we can use it to draw the projects in innerRects.

变量projects具有绑定到数据的空选择,因此我们可以使用它在innerRects绘制项目。

Now you can also add a label for each project:

现在,您还可以为每个项目添加标签:

var rectText = projects.append("text")                .text(d => d.label)                .attr("x", d => timeScale(dateFormat(d.date)) + 100)                .attr("y", (d,i) => yScale(i) + 20)                .attr("font-size", 11)                .attr("text-anchor", "middle")                .attr("text-height", 30)                .attr("fill", "#fff");

为每个项目着色 (Coloring each project)

We want the color of each rectangle to reflect the status of each project. To do that, let’s create another scale:

我们希望每个矩形的颜色反映每个项目的状态。 为此,让我们创建另一个音阶:

let dataByCategories = d3.nest().key(d => d.status).entries(data);let categories = dataByCategories.map(d => d.key).sort();
let colorScale = d3.scaleLinear()             .domain([0, categories.length])             .range(["#00B9FA", "#F95002"])             .interpolate(d3.interpolateHcl);

And then we can fill the rectangles with colors from this scale. Putting together everything we've seen so far, here is the code:

然后我们可以用此比例尺的颜色填充矩形。 将到目前为止我们所看到的所有内容放在一起,下面是代码:

d3.json("projects.json", function(error, data) {            chart(data.projetos);        });
function chart(data) {    var dateFormat = d3.timeParse("%d/%m/%Y");    var timeScale = d3.scaleTime()                   .domain(d3.extent(data, d => dateFormat(d.date)))                   .range([0, 500]);      let dataByDates = d3.nest().key(d => d.date).entries(data);    let tickValues = dataByDates.map(d => dateFormat(d.key));      let dataByCategories = d3.nest().key(d => d.status).entries(data);    let categories = dataByCategories.map(d => d.key).sort();    let colorScale = d3.scaleLinear()                 .domain([0, categories.length])                 .range(["#00B9FA", "#F95002"])                 .interpolate(d3.interpolateHcl);      var xAxis = d3.axisBottom()                .scale(timeScale)                .tickValues(tickValues)                .tickSize(250, 0, 0)                .tickSizeOuter(0);    var grid = d3.select("svg").append('g').call(xAxis);      yScale = d3.scaleLinear().domain([0, data.length]).range([0, 250]);      var projects = d3.select("svg")                   .append('g')                   .selectAll("this_is_empty")                   .data(data)                   .enter();      var barWidth = 200;      var innerRects = projects.append("rect")                  .attr("rx", 3)                  .attr("ry", 3)                  .attr("x", (d,i) => timeScale(dateFormat(d.date)) - barWidth/2)                  .attr("y", (d,i) => yScale(i))                  .attr("width", barWidth)                  .attr("height", 30)                  .attr("stroke", "none")                  .attr("fill", d => d3.rgb(colorScale(categories.indexOf(d.status))));      var rectText = projects.append("text")                  .text(d => d.label)                  .attr("x", d => timeScale(dateFormat(d.date)))                  .attr("y", (d,i) => yScale(i) + 20)                  .attr("font-size", 11)                  .attr("text-anchor", "middle")                  .attr("text-height", 30)                  .attr("fill", "#fff"); }

And with that we have the raw structure of our visualization.

这样,我们便有了可视化的原始结构。

Well done.

做得好。

创建可重复使用的图表 (Creating a reusable chart)

The result shows that there are no margins. Also, if we want to display this graph on another page, we need to copy the entire code. To solve these issues, let’s build a reusable chart and just import it. To learn more about charts, click here. To see a previous tutorial I wrote about reusable charts, click here.

结果表明没有边距。 另外,如果我们想在另一个页面上显示此图,则需要复制整个代码。 为了解决这些问题,让我们构建一个可重用的图表并将其导入。 要了解有关图表的更多信息,请单击此处 。 要查看我之前写的有关可重用图表的教程,请单击此处 。

The structure to create a reusable chart is always the same. I created a tool to generate one. In this graph, I want to set:

创建可重用图表的结构始终相同。 我创建了一个生成工具。 在此图中,我要设置:

  • The data (of course)数据(当然)
  • The values for width, height, and margins宽度,高度和边距的值
  • A time scale for the x value of the rectangles

    x的时间标度 矩形的值

  • A scale for the y value for the rectangles矩形的y值的比例
  • A scale for the color颜色的比例
  • The values for xScale, yScale , and colorScale

    xScaleyScalecolorScale

  • The values for the start and end of each task and the height of each bar每个任务的开始和结束的值以及每个条的高度

I then pass this to the function I've created:

然后,将其传递给我创建的函数:

chart: ganttAlikeChartwidth: 800height: 600margin: {top: 20, right: 100, bottom: 20, left:100}xScale: d3.scaleTime()yScale: d3.scaleLinear()colorScale: d3.scaleLinear()xValue: d => d.datecolorValue: d => d.statusbarHeight: 30barWidth: 100dateFormat: d3.timeParse("%d/%m/%Y")

Which gives me this:

这给了我这个:

function  ganttAlikeChart(){width = 800;height = 600;margin = {top: 20, right: 100, bottom: 20, left:100};xScale = d3.scaleTime();yScale = d3.scaleLinear();colorScale = d3.scaleLinear();xValue = d => d.date;colorValue = d => d.status;barHeight = 30;barWidth = 100;dateFormat = d3.timeParse("%d/%m/%Y");function chart(selection) { selection.each(function(data) {   var svg = d3.select(this).selectAll("svg").data([data]).enter().append("svg");   svg.attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom);  var gEnter = svg.append("g");  var mainGroup = svg.select("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");})}
[...]
return chart;}

Now we just need to fill this template with the code we created before. I also made some changes to the CSS and added a tooltip.

现在,我们只需要使用我们之前创建的代码来填充此模板。 我还对CSS进行了一些更改并添加了工具提示。

And that's it.

就是这样。

You can check out the entire code here.

您可以在此处查看整个代码。

Thanks for reading! ?

谢谢阅读! ?

Did you found this article helpful? I try my best to write a deep dive article each month, you can receive an email when I publish a new one.

您觉得这篇文章对您有帮助吗? 我每个月都会尽力写一篇深入的文章, 当我发布新文章时,您会收到一封电子邮件 。

翻译自: https://www.freecodecamp.org/news/d3-visualizations-with-datasets-how-to-build-a-gantt-like-chart-9c9afa9b8d9d/

wps图表中如何插入甘特图

wps图表中如何插入甘特图_如何通过使用D3可视化数据集来构建类似甘特图的图表...相关推荐

  1. r语言绘制精美pcoa图_「R」数据可视化5:PCA和PCoA图

    其实不论是PCoA还是PCA图均是用散点图来展示结果PCoA和PCA的结果,PCoA和PCA准确来讲是数据降维分析方法. 什么是PCA和PCoA 主成分分析(Principal components ...

  2. wps插入入html,WPS文字技巧—如何在WPS文字中快速插入域

    很多小伙伴经常用WPS文字做一些文档的处理,但对于有些不常用小工具,他们都不知道怎么用?特别是在域的应用上,更是一片空白,很多人几乎都没有用过. 下面我们就通过范例来给大家讲讲,什么叫做域?如何在WP ...

  3. 直方图 帕累托图_如何发现现象背后的关键因素?帕累托图,质量管理的利器...

    大家好: 无论在日常生活还是工作中,都会发生一些事情或者结果,是我们不希望发生的.我们也希望从根本上解决掉,但有时候却无从下手,比如本来打算用来看书的时间不知道去哪里了:本来打算存款的钱也不知道去哪里 ...

  4. puml绘制思维导图_强推:9款超好用思维导图APP

    思维导图是由英国著名教育学家东尼·博赞发明的一种思维利器,被誉为大脑的"瑞士军刀".运用思维导图,我们可以便捷地整理笔记.收集想法和统筹事项. 一. MindMaster 说起思维 ...

  5. jquery手写轮播图_用jQuery如何手写一个简单的轮播图?(附代码)

    用jQuery如何手写一个简单的轮播图?下面本篇文章通过代码示例来给大家介绍一下.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 用 jQuery 手写轮播图 先上个效果截图: 主要 ...

  6. svg 可视化操作_使用SVG和D3可视化浏览指标

    svg 可视化操作 本文是两篇系列文章中的第一篇,该系列文章演示了可视化技术,这些技术可以帮助您从数据中提取业务价值信息. 您将看到如何使用可伸缩矢量图形(SVG)和开放源代码的D3 JavaScri ...

  7. 计算机一级插入页码,计算机一级WPS考试:WPS文字中页码插入及排版技巧

    在工作或学习中,编辑完文档后,常常会对多页的文档进行页码的设置,不然装订或者阅读起来比较麻烦.而在WPS编辑文字,一点小技巧会达到事半功倍的效果,下面就为大家讲讲页码的插入以及排版的小技巧. 1.用A ...

  8. word中在插入空白页_例如,为了打印,在封面后面插入一页空白页

    在报告打印时,通常需要在第一页封面页(设为A页)后面插入一页空白页,好打印. 方法:在封面页A页末尾处,插入-(页面布局word2010)-分隔符-分页符-,再点一遍:分隔符-分页符:即连续点两次分页 ...

  9. native react 折线图_【详解】纯 React Native 代码自定义折线图组件(译)

    本文为 Marno 翻译,转载必须保留出处! 公众号[ Marno ],关注后回复 RN 加入交流群 React Native 优秀开源项目大全:http://www.marno.cn 一.前言 在移 ...

最新文章

  1. 实验一:使用ADO.NET方式读数据
  2. CSS使用浮动属性和边距设计3行3列定宽的布局实例
  3. AppWidgetServiceImpl: Widget Error: widget.host.callbacks is null
  4. CMU预训练模型最新综述:自然语言处理新范式—预训练、Prompt和预测
  5. 栈应用:后缀表达式求值
  6. [剑指Offer] 42.和为S的两个数字
  7. python shell怎么打开测试,python脚本第一篇,运行时间测试
  8. 更换Homebrew为中科大源
  9. 各部件作用计算机,计算机硬件有哪些部件,各部件的作用是什么?
  10. WPF教程(二)Binding
  11. java导出word图片格式_Java 导出带图片和列表的 Word
  12. 【Pixel刷机】记录一次Pixel 2 刷机, root
  13. android mvp mvvm ppt,Android中MVC MVP MVVM模式
  14. Method threw ‘java.lang.NullPointerException‘ exception. Cannot evaluate com.sun.proxy.xxx
  15. 源码分析RocketMQ顺序消息消费实现原理
  16. Modularity Based Community Detection with Deep Learning 阅读笔记
  17. 用python画微笑脸表情_“裂开了,苦涩了,翻白眼”!我用Python画出微信新出的表情包...
  18. Flutter中的多选按钮组件Checkbox
  19. EDM营销存在的六大问题
  20. 新品发布!—— ZStack Mini超融合一体机

热门文章

  1. 数据体系和专题分析实战。
  2. 通达信证券软件接口编程能赚钱吗?
  3. 自动驾驶、人工智能将把你的未来生活变成什么样?
  4. 怎样设置计算机u盘启动程序,怎样设置u盘启动|电脑设置u盘启动教程
  5. js指定服务器时间戳,js获取服务器时间戳
  6. linux的退出tail命令,Linux显示文件最后几行-Linux tail命令详解-Linux tail命令退出-嗨客网...
  7. highlight.js怎么识别br换行符
  8. 数字水印印刷防伪研究与应用现状
  9. 华为OD机试 - 热点网站统计(Java JS Python)
  10. 04. 禁止使用 TeamViewer ❀ 飞塔 (Fortinet6.0) 防火墙