使用 Echarts 实现项目进度甘特图

 Echarts 功能十分强大,可以实现多种图表效果,下面简单介绍下最近使用 Eharts 实现的一个项目进度甘特图。

下面是实现的效果:

目录

一.概览 Echarts 基本内容

1.官网文档

2.查看示例

二.需求分析

1.数据系列(series)

2.标线 (markLine)

3.数据对象结构

4.“超时”、“按时”划分

三.引入并配置 Echarts

1.坑

2.具体操作

四.说明


一.概览 Echarts 基本内容

1.官网文档

首先基本的前端搭建必须的,然后应该大致浏览一下 Echarts 官网 文档 专题下的 教程 和 配置项手册,如果不是要实现特别复杂的效果和功能,这些内容基本就足够了。

2.查看示例

只看文字内容比较抽象,因为要做甘特图,可以先去 实例 中找一个甘特图研究下,看看别人是怎么实现的。你会发现Echarts官网好像只能在 实例 下找到官方示例图,别急,操作一番就可以看其他无私的贡献者发布的图表了。

点击官网页面右上角 “EN”,切换为英文版,

在 Get Started 下 点击 Gallery,

这样就能看到其他开发者贡献的 Demo 了,

点击 展开筛选,筛选你要找的图表类型。

下面这个图表(点击这里查看该图表Demo)和我们要实现的效果还是有几分类似的:

当然细节还得自己研究修改一下。

二.需求分析

从文章开头的图表效果来看,横坐标刻度值为时间,纵坐标为 “方案”、“纲要”、“成果” 三个项目阶段类目,每个阶段类目中包含按时完成(蓝色柱状图)和超时完成(红色柱状图)两种系列的数据,另外还有垂直于 x 时间坐标轴的 “计划开始时间”和“有效期”两条时间标线。结合查阅官网文档和demo,应该有以下初步结论:

1.数据系列(series)

每个阶段类目中实际应该有三种系列(series)的数据的,即应该有 开始时间、按时完成时间和超时完成时间三种系列,且三种系列的柱状图是堆叠在一起的。

2.标线 (markLine)

“计划开始时间” markLine 可以放在在 开始时间series 中,“有效期”markLine可以在 按时完成 或 超时完成 series 中。

3.数据对象结构

这里比较容易理解的传值结构,应该是传入 三个时间段 和 两个刻度值,类似下面这种结构:

/**
 * 存储阶段进度的对象
 */
var stageProgress = {
	// 方案 实际时间段
	fangAnTimeBucket: ['2017-01-01', '2017-03-01'],
	// 纲要 实际时间段
	gangYaoTimeBucket: ['2017-02-26', '2017-08-29'],
	// 成果 实际时间段
	chengGuoTimeBucket: ['2017-08-29', '2017-12-06'],
	// 计划开始时间
	scheduledStartTime: '2016-12-22',
	// 有效截止日期
	validTime: '2017-05-10'
};

4.“超时”、“按时”划分

这里要求三个阶段实际时间段的首尾可以不连续,即三个阶段之间没有影响,所以,是否超时就取决于 有效期 与 阶段实际时间段 之间的关系了。比如,有效期在阶段实际时间段开始和结束时间之间,那么该阶段是超时的,但是该阶段的柱状图应该是蓝色红色共存的;有效期在阶段实际时间段结束时间之后,那么该阶段按时完成,应该都是蓝色的;有效期在阶段实际时间段开始时间之前,那么该阶段超时完成,应该都是红色的。

其实主要是第四点需要计算一下,其他 参考一下 配置项手册基本没有太大问题。

三.引入并配置 Echarts

1.坑

用新不用旧,但是经过我的测试,Echarets4.x 透明堆叠不起效果,即设置了 series 为 bar ,且 开始时间、按时完成时间、按时完成时间 三个 series 设置了 相同的 stack 后,开始时间 柱状图并不能起到遮盖其他系列柱状图的效果,于是尝试使用3.x 版本,是可以起到柱条堆叠辅助隐藏的效果的。(请同学们注意!!!评论区的seuedu同学指出,在4.x版本中,series里配置z属性可以覆盖,但本人未进行验证,请大家自行验证下!!!

若果需要兼容 IE8 的话,那么你需要定制下载  Echarts(我在实际测试中发现,这个定制下载即使选中 兼容IE8 ,下载下来的js仍让无法兼容 IE8,真的是让人脑壳痛)。

2.具体操作

在你的页面中,放置一个 div,作为放置图表的容器,需要为它指定宽高。

<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="content"></div>

控制图表的 js 代码基本结构如下:

// 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));

        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data:['销量']
            },
            xAxis: {
                data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        };

        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);

下面是实现本文开头图表效果的 js,方法说明和需要注意的点基本都写在注释里了:

/**
 * 存储阶段进度时间段的对象
 */
var stageProgress = {
// 			// 方案 实际时间段
// 			fangAnTimeBucket: ['2017-01-01', '2017-03-01'],
// 			// 纲要 实际时间段
// 			gangYaoTimeBucket: ['2017-02-26', '2017-08-29'],
// 			// 成果 实际时间段
// 			chengGuoTimeBucket: ['2017-08-29', '2017-12-06'],
// 			// 计划开始时间
// 			scheduledStartTime: '2016-12-22',
// 			// 有效截止日期
// 			validTime: '2017-05-10'

	// 		// 方案 实际时间段
	// 		fangAnTimeBucket: ['2017-01-01', '2017-01-20'],
	// 		// 纲要 实际时间段
	// 		gangYaoTimeBucket: ['2017-02-07', '2017-02-28'],
	// 		// 成果 实际时间段
	// 		chengGuoTimeBucket: ['2017-02-15', '2017-03-20'],
	// 		// 计划开始时间
	// 		scheduledStartTime: '2017-01-01',
	// 		// 有效截止日期
	// 		validTime: '2017-02-20'

	// 方案 实际时间段
	fangAnTimeBucket: ['2017-11-23', '2017-11-28'],
	// 纲要 实际时间段
	gangYaoTimeBucket: ['2017-11-25', '2017-11-30'],
	// 成果 实际时间段
	chengGuoTimeBucket: ['2017-12-06', '2017-12-12'],
	// 计划开始时间
	scheduledStartTime: '2017-11-23',
	// 有效截止日期
	validTime: '2017-12-02'
};

/**
 * 横坐标轴时间刻度可选值
 * 这里 month和year 没有考虑平闰年之分
 */
var timeInterval = {
	day: 3600 * 1000 * 24,
	month: 3600 * 1000 * 24 * 31,
	year: 3600 * 1000 * 24 * 31 * 12,
};

/**
 * 时间坐标轴标签单位应该精确到哪一位
 */
var xAxisLabelUnit = {
	year: false,
	month: false,
	day: false
}

/**
 * 获取合适的横坐标时间刻度间隔
 */
function getProperTimeAxisInterval() {
	xAxisLabelUnit.year = false;
	xAxisLabelUnit.month = false;
	xAxisLabelUnit.day = false;

	var timeDataArray = getXAxisData();
	var begin = getTimeMilliseconds(timeDataArray[timeDataArray.length - 1]);
	console.log("begin " + begin);
	var periodMillis = getTimeMilliseconds(timeDataArray[timeDataArray.length - 1]) - getTimeMilliseconds(timeDataArray[0]);
	console.log("periodMillis " + periodMillis);
	var years = periodMillis / timeInterval.year;
	console.log("years " + years);
	var months = periodMillis / timeInterval.month;
	console.log("months " + months);
	var days = periodMillis / timeInterval.day;
	console.log("days " + days);

	if (months <= 1) {
		xAxisLabelUnit.day = true;
		return timeInterval.day * 2;
	} else if (months <= 16) {
		xAxisLabelUnit.month = true;
		return timeInterval.month;
	} else i
实现多层甘特图可以通过使用echarts的gantt组件,结合vue的组件化实现。 首先,在vue项目中安装echarts: ``` npm install echarts --save ``` 然后,在vue组件中引入echarts: ```javascript import echarts from 'echarts' ``` 接着,在vue组件中定义一个gantt组件,并在其中使用echarts: ```vue <template> <div class="gantt-chart"></div> </template> <script> export default { name: 'GanttChart', props: { data: { type: Array, required: true }, height: { type: String, default: '500px' } }, mounted() { this.initChart() }, methods: { initChart() { const chart = echarts.init(document.querySelector('.gantt-chart')) chart.setOption({ tooltip: { formatter: function (params) { return params.marker + params.name + ': ' + new Date(params.start).toLocaleDateString() + ' - ' + new Date(params.end).toLocaleDateString() } }, grid: { top: 10, left: 100, bottom: 30, right: 30 }, xAxis: { min: new Date(2021, 0, 1), max: new Date(2022, 0, 1) }, yAxis: { type: 'category', data: ['Layer 1', 'Layer 2', 'Layer 3'] }, series: [{ type: 'gantt', data: this.data, barWidth: 20, label: { show: true, formatter: function (params) { return params.name } } }] }) } } } </script> ``` 在上述代码中,我们定义了一个名为GanttChart的vue组件,该组件接收两个props:data和height,其中data是一个数组,包含了多层甘特图的数据,height是图表的高度,默认为500px。 在mounted方法中,我们调用了initChart方法,该方法使用echarts.init初始化了一个echarts实例,并使用setOption方法设置了图表的各种配置项,包括tooltip、grid、xAxis、yAxis和series。 其中,series中的type属性设置为gantt,表示使用gantt组件,data属性设置为props中传入的data数组,barWidth属性设置为20,表示一个甘特图的宽度为20像素,label的formatter属性设置为params.name,表示在每个甘特图上显示其名称。 最后,在vue组件中使用该组件: ```vue <template> <div class="gantt-chart-wrapper"> <gantt-chart :data="ganttData" :height="'600px'" /> </div> </template> <script> import GanttChart from './GanttChart.vue' export default { name: 'App', components: { GanttChart }, data() { return { ganttData: [ { name: 'Task 1', start: new Date(2021, 0, 1), end: new Date(2021, 3, 1), y: 0 }, { name: 'Task 2', start: new Date(2021, 3, 1), end: new Date(2021, 6, 1), y: 0 }, { name: 'Task 3', start: new Date(2021, 6, 1), end: new Date(2021, 9, 1), y: 1 }, { name: 'Task 4', start: new Date(2021, 9, 1), end: new Date(2022, 0, 1), y: 2 } ] } } } </script> ``` 在上述代码中,我们在App组件中使用GanttChart组件,并传入了ganttData作为props的data属性,该数组包含了4个甘特图,分别属于三个不同的层级。其中,y属性表示当前甘特图所属的层级,从0开始计数。我们还为GanttChart组件设置了一个高度为600px。 通过上述代码,我们就可以在vue中实现多层甘特图了。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值