Vue+FusionCharts 动态获取数据生成甘特图

话不多说先上图
Vue+FusionCharts 动态获取数据生成甘特图_第1张图片

效果就是这个效果,好不好看另说,反正基本功能是有了。可以根据后台传入的数据列表动态生成甘特图。

2020年5月22日-新需求来了

1.甘特图显示在数据列表下方
2.甘特图时间轴保持一致

回看上面的图确实有问题啊,每个项目进度条似乎都一样!

具体实现逻辑看最下方

完成图

Vue+FusionCharts 动态获取数据生成甘特图_第2张图片

2020年6月5日-新需求

国家节假日和周末不显示颜色
说明:
1、要注意工作日(周一至周五)可能是国家节假日,周末可能补班
2、下面代码中都有注释,说的很详细了哦

完成图

Vue+FusionCharts 动态获取数据生成甘特图_第3张图片

先说说为什么选FusionCharts来做甘特图吧

前几天在网上百度了一圈,发现echarts都没有甘特图的官方实例,highcharts倒是有,不过那图不忍直视。

偶然间发现这个可以做甘特图,进官网一看发现图挺美观的,而且官方还提供了多种甘特图实例,还集成了不同的前端框架,真是天助我也!

FusionCharts官网:https://www.fusioncharts.com/

API:https://www.fusioncharts.com/dev/chart-attributes/

一、在Vue中集成FusionCharts

先在Vue项目中装插件

npm install fusioncharts vue-fusioncharts --save

二、main.js文件中全局引入

// 必须引入 vue-fusioncharts 和 fusioncharts
import VueFusionCharts from 'vue-fusioncharts';
import FusionCharts from 'fusioncharts/core';
// 可选,引入扁平画主题
import FusionTheme from 'fusioncharts/themes/es/fusioncharts.theme.fusion'
    
/* 重点: 想显示图形,必须引入对应图形类型模块 */
//比如 想做个饼图,需要引入pie2d模块
import Pie2D from 'fusioncharts/viz/pie2d'
//我要做的是甘特图,那么我得引入gantt  不知道就去官方示例js代码的type中查看
import gantt from 'fusioncharts/viz/gantt'

/* 引入完成下一步就需要放入Vue中,如下 */
Vue.use(VueFusionCharts, FusionCharts,FusionTheme, Pie2D, gantt);// 添加多个类型图形,就在后面添加上
    

三、在需要显示的页面中使用官方提供的组件

官方简单甘特图例子:https://www.fusioncharts.com/charts/gantt-charts/simple-gantt-chart?framework=vue

Vue+FusionCharts 动态获取数据生成甘特图_第4张图片

上面图中有不同前端框架使用的例子 

官方提供的组件和数据


vue中的data数据

type: "gantt",
                        width: "100%",
                        // height: "30%",  //高度
                        dataFormat: "json",
                        dataSource: {
                            chart: {
                                dateformat: "mm/dd/yyyy",
                                caption: "Event Planning Process",
                                theme: "fusion",
                                canvasborderalpha: "40",
                                ganttlinealpha: "50"
                            },
                            tasks: {
                                color: "#5D62B5",
                                task: [
                                    {
                                        start: "03/07/2018",
                                        end: "03/17/2018"
                                    },
                                    {
                                        start: "03/14/2018",
                                        end: "03/28/2018"
                                    },
                                    {
                                        start: "03/15/2018",
                                        end: "03/31/2018"
                                    },
                                    {
                                        start: "04/02/2018",
                                        end: "04/12/2018"
                                    },
                                    {
                                        start: "04/12/2018",
                                        end: "04/30/2018"
                                    },
                                    {
                                        start: "04/20/2018",
                                        end: "05/06/2018"
                                    },
                                    {
                                        start: "04/30/2018",
                                        end: "05/10/2018"
                                    },
                                    {
                                        start: "04/30/2018",
                                        end: "05/25/2018"
                                    },
                                    {
                                        start: "05/04/2018",
                                        end: "06/05/2018"
                                    }
                                ]
                            },
                            processes: {
                                headertext: "Task",
                                headeralign: "left",
                                fontsize: "14",
                                isbold: "0",
                                align: "left",
                                process: [
                                    {
                                        label: "Define event goals"
                                    },
                                    {
                                        label: "Source venue options"
                                    },
                                    {
                                        label: "Finalize speaker reach out list"
                                    },
                                    {
                                        label: "Compose sponsorship strategy"
                                    },
                                    {
                                        label: "Reach out to sponsors"
                                    },
                                    {
                                        label: "Create social media campaign"
                                    },
                                    {
                                        label: "Reach out to blogs for backlinks"
                                    },
                                    {
                                        label: "Optimize SEO ranking"
                                    },
                                    {
                                        label: "Publish event lead up vlog series"
                                    }
                                ]
                            },
                            categories: [
                                {
                                    category: [
                                        {
                                            start: "03/05/2018",
                                            end: "03/31/2018",
                                            label: "March"
                                        },
                                        {
                                            start: "04/01/2018",
                                            end: "04/30/2018",
                                            label: "April"
                                        },
                                        {
                                            start: "05/01/2018",
                                            end: "05/31/2018",
                                            label: "May"
                                        },
                                        {
                                            start: "06/01/2018",
                                            end: "06/10/2018",
                                            label: "June"
                                        }
                                    ]
                                },
                                {
                                    category: [
                                        {
                                            start: "03/05/2018",
                                            end: "03/11/2018",
                                            label: "W 1"
                                        },
                                        {
                                            start: "03/12/2018",
                                            end: "03/18/2018",
                                            label: "W 2"
                                        },
                                        {
                                            start: "03/19/2018",
                                            end: "03/25/2018",
                                            label: "W 3"
                                        },
                                        {
                                            start: "03/26/2018",
                                            end: "04/01/2018",
                                            label: "W 4"
                                        },
                                        {
                                            start: "04/02/2018",
                                            end: "04/08/2018",
                                            label: "W 5"
                                        },
                                        {
                                            start: "04/09/2018",
                                            end: "04/15/2018",
                                            label: "W 6"
                                        },
                                        {
                                            start: "04/16/2018",
                                            end: "04/22/2018",
                                            label: "W 7"
                                        },
                                        {
                                            start: "04/23/2018",
                                            end: "04/29/2018",
                                            label: "W 8"
                                        },
                                        {
                                            start: "04/30/2018",
                                            end: "05/06/2018",
                                            label: "W 9"
                                        },
                                        {
                                            start: "05/07/2018",
                                            end: "05/13/2018",
                                            label: "W 10"
                                        },
                                        {
                                            start: "05/14/2018",
                                            end: "05/20/2018",
                                            label: "W 11"
                                        },
                                        {
                                            start: "05/21/2018",
                                            end: "05/27/2018",
                                            label: "W 12"
                                        },
                                        {
                                            start: "05/28/2018",
                                            end: "06/03/2018",
                                            label: "W 13"
                                        },
                                        {
                                            start: "06/04/2018",
                                            end: "06/10/2018",
                                            label: "W 14"
                                        }
                                    ]
                                }
                            ]
                        }

引入了数据和组件,那么现在在Vue界面就可以看见图形了

基本介绍就是这样了,大家可以去试试了。

---------------分--------------------割-------------------线---------------

我的需求

好,现在我来说说我的需求。现在页面的数据是写死的,不能动态变化,而且我需要的不止一个甘特图,有多少个项目就要显示几个图

首先,甘特图的显示是由官方主键来控制的,我的要求是根据项目数量动态生成多个图表。于是我在外层加了个v-for循环。


每一个图对应下方一个对象数据,我在方法里面组装好json数据,赋值给myChart,循环就ok了

myChart需要的基本格式如下

{
    type: "gantt",
    width: "100%",
    height: "100%",
    dataFormat: "json",
    dataSource:{}
},
    {
    type: "gantt",
    width: "100%",
    height: "100%",
    dataFormat: "json",
    dataSource:{}
},
    {
    type: "gantt",
    width: "100%",
    height: "100%",
    dataFormat: "json",
    dataSource:{}
}

贴图显示,不变的数据就直接写死,变化的就定义对象和数组赋值
Vue+FusionCharts 动态获取数据生成甘特图_第5张图片


我贴出组装json数据的代码,有需要的小伙伴自行查看
具体内容在 chartsShow()方法里

	data() {
            return {
                msgShow: true,
                match: "",
                pageSize: 0,
                pageNumber: 0,
                total: 0,
                devProgress: "devProgress",
                list: [],
                myChart: [],
                //2020年 周末补班日期
                weekendWorkDateArr: [
                    // "2020-06-28", "2020-09-27", "2020-10-10"
                ],
                //2020年 节假日
                vacationArr: [
                    // "2020-06-25", "2020-06-26", "2020-06-27", "2020-10-01",
                    // "2020-10-02", "2020-10-03", "2020-10-04", "2020-10-05",
                    // "2020-10-06", "2020-10-07", "2020-10-08"
                ],

            }
        },
    methods:{
    	// 日期,在原有日期基础上,增加days天数,默认增加1天
            jiraAddDate(date, days) {
                if (days === undefined || days === '') {
                    days = 1;
                }
                date = new Date(date);
                date.setDate(date.getDate() + days);
                var month = date.getMonth() + 1; //月份从0开始所以需要+1
                var day = date.getDate();

                return date.getFullYear() + '-' + this.getFormatDate(month) + '-' + this.getFormatDate(day);
            },
            // 日期 月份/天 的显示,如果是1位数,则在前面加上'0'
            getFormatDate(arg) {
                if (arg === undefined || arg === '') {
                    return '';
                }
                var re = arg + '';
                if (re.length < 2) {
                    re = '0' + re;
                }

                return re;
            },
            /* 判断当天是否为周末 */
            isWeekEnd(date) {
                return "天一二三四五六".charAt(new Date(date).getDay()) === "天" || "天一二三四五六".charAt(new Date(date).getDay()) === "六";
            },

            /* 时间格式化 */
            formatTime(dateVal) {
                let year = dateVal.getFullYear(),
                    month = dateVal.getMonth() + 1,
                    day = dateVal.getDate();
                if (month < 10) {
                    month = `0${month}`
                }
                if (day < 10) {
                    day = `0${day}`
                }
                return `${year}-${month}-${day}`
            },
            /*   * 传入两个日期,得出范围内所有日期    传入yyyy-mm-dd 格式 */
            generateFun(startTime, endTime) {
                startTime = new Date(startTime);
                endTime = new Date(endTime);
                let timeStamp = Math.ceil((endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60 * 24)),//判断两个日期相差多少天
                    timeArr = [];
                for (let index = 1; index <= timeStamp; index++) {
                    const element = startTime.setTime((1000 * 60 * 60 * 24) + startTime.getTime());
                    timeArr.push(this.formatTime(new Date(element)))
                }
                return timeArr;
            },
            //计算日期天数差的函数,通用
            dateDiff(firstDate, secondDate) {
                firstDate = new Date(firstDate);
                secondDate = new Date(secondDate);
                var diff = Math.abs(firstDate.getTime() - secondDate.getTime());
                return parseInt(diff / (1000 * 60 * 60 * 24));
            },
            //日期加减计算
            addDate(date, days) {
                var d = new Date(date);
                d.setDate(d.getDate() + days);
                var m = d.getMonth() + 1;
                return d.getFullYear() + '-' + m + '-' + d.getDate();
            },
            //甘特图展示
            chartsShow() {
                let self = this;

                var listArr = [];
                var q = 0;
                var tempListArr = [];
                tempListArr = self.list;
                for (var k = 0; k < tempListArr.length; k++) {
                    if (tempListArr[k].name.search("常规版本") !== -1) {//只需要常规版本
                        listArr[q++] = tempListArr[k];
                    }
                }
                var myChartArr = [];//定义空数组用来装每个图数据对象

                var timeLineStart;
                var timeLineEnd;//甘特图时间轴结束日期
                for (let w = 0; w < listArr.length; w++) {
                    timeLineStart = listArr[w].starDate;
                    timeLineEnd = listArr[w].releaseDate;
                    break;
                }

                //甘特图时间轴开始日期
                for (let e = 0; e < listArr.length; e++) {
                    if (new Date(listArr[e].starDate) <= new Date(timeLineStart)) {
                        timeLineStart = listArr[e].starDate;
                    }
                    if (new Date(listArr[e].releaseDate) >= new Date(timeLineEnd)) {
                        timeLineEnd = listArr[e].releaseDate;
                    }
                }
                var chartsStartTime = self.$options.methods.addDate(timeLineStart, -7);
                var chartsEndTime = self.$options.methods.addDate(timeLineEnd, 1);
                var days = self.$options.methods.dateDiff(chartsStartTime, chartsEndTime);//开始到结束总共多少天

                for (var i = 0; i < listArr.length; i++) {
                    //这里存在问题 日期格式yyyy-mm-dd    月份和天数可能为单数
                    var starDate = listArr[i].starDate;//版本启动日期    需求结束时间
                    var frozenDate = listArr[i].frozenDate;//版本冻结日期
                    var releaseDate = listArr[i].releaseDate;//版本上线
                    var name = listArr[i].name;//版本名称,即甘特图名称

                    var categoriesArr = [];//甘特图dataSource下的categories数据数组
                    var taskArr = [];//甘特图dataSource下的tasks中task数组
                    var categoryArr = [];//甘特图dataSource下的categories中category数组

                    /* categoryArr  里面的时间要动态生成啊  且动态变化 */
                    for (var j = 0; j < days; j++) {
                        var time = self.$options.methods.addDate(chartsStartTime, j);
                        var labelTime = time.substring(5);// 将 yyyy-mm-dd 变为 mm-dd

                        //版本名称下方时间轴的日期显示
                        if (i === 0){
                            categoryArr.push({
                                "start":time,
                                "end":time,
                                "label":labelTime,
                            });
                        } else {
                            //第二个及以下的图不显示日期
                            categoryArr.push({
                                "start":time,
                                "end":time,
                                "label":" ",
                            });
                        }
                    }

                    categoriesArr.push({
                        "category":categoryArr,
                    });

                    let weekendWorkDateArr = self.weekendWorkDateArr;//周末补班日期
                    let vacationArr = self.vacationArr;//国家节假期

                    var demandDevEndTime = self.jiraAddDate(releaseDate, -1);
                    let tempDateArr = this.generateFun(starDate, demandDevEndTime);
                    /*-------------------------控制颜色显示----------------------------*/
                    //需求收集
                    taskArr.push({
                        "start":chartsStartTime,//需求收集开始时间  启动时间前7天
                        "end":self.$options.methods.addDate(starDate, -1),//需求收集结束时间
                        "color":"#409EFF",//显示颜色
                        "processid":"xqsj"
                    });
                    //版本启动
                    taskArr.push({
                        "start":self.$options.methods.addDate(starDate, -1),//版本启动时间
                        "end":starDate,//版本启动时间
                        "processid":"bbqd"
                    });
                    //循环每个日期    需求开发阶段
                    for (var v = 0; v < tempDateArr.length; v++) {
                        //  周末
                        if (self.isWeekEnd(tempDateArr[v])) {

                            if (weekendWorkDateArr !== 0) {
                                //   不是补班日期
                                if ( weekendWorkDateArr.indexOf(tempDateArr[v]) === -1 ) {

                                    taskArr.push({
                                        "start":self.$options.methods.addDate(tempDateArr[v], -1),
                                        "end": tempDateArr[v],
                                        "color":"#FFFFFF",
                                        "processid":"xqkf"
                                    });

                                } else {
                                    //  是补班日期
                                    taskArr.push({
                                        "start":self.jiraAddDate(tempDateArr[v], -1),
                                        "end": tempDateArr[v],
                                        "color":"#41B883",
                                        "processid":"xqkf"
                                    });
                                }
                            } else {
                                //纯周末  没有补班日
                                taskArr.push({
                                    "start":self.$options.methods.addDate(tempDateArr[v], -1),
                                    "end":tempDateArr[v],
                                    "color":"#FFFFFF",
                                    "processid":"xqkf"
                                });
                            }
                        }
                        //是周一到周五
                        if (!self.isWeekEnd(tempDateArr[v])) {
                            //节假日不为空
                            if (vacationArr !== 0) {
                                //  不在国家节假日内    判断节假日数组中是否包含该日期
                                if (vacationArr.indexOf(tempDateArr[v]) === -1) {

                                    taskArr.push({
                                        "start":self.$options.methods.addDate(tempDateArr[v], -1),
                                        "end":tempDateArr[v],
                                        "color":"#41B883",
                                        "processid":"xqkf"
                                    });

                                } else {
                                    //   在国家节假日内
                                    taskArr.push({
                                        "start":self.$options.methods.addDate(tempDateArr[v], -1),
                                        "end":tempDateArr[v],
                                        "color":"#FFFFFF",
                                        "processid":"xqkf"
                                    });

                                }
                            } else {
                                taskArr.push({
                                    "start":self.$options.methods.addDate(tempDateArr[v], -1),
                                    "end":tempDateArr[v],
                                    "color":"#41B883",
                                    "processid":"xqkf"
                                });
                            }
                        }
                    }
                    //需求冻结
                    taskArr.push({
                        "start":self.$options.methods.addDate(frozenDate, -1),//活动冻结期
                        "end":releaseDate,//活动冻结期结束时间(版本上线日期)
                        "color":"#E22018",//显示颜色
                        "processid":"xqdj"
                    });
                    //需求上线
                    taskArr.push({
                        "start":self.$options.methods.addDate(releaseDate, -1),//版本上线日期
                        "end":releaseDate,//版本上线日期
                        "color":"#FFD801",//显示颜色
                        "processid":"xqsx"
                    });
                    /*-------------------------控制颜色显示----------------------------*/

                    //甘特图需要的json数据格式
                    myChartArr.push({
                        "type":"gantt",//图类型
                        "width":"100%",//宽度
                        "dataFormat":"json",//数据格式
                        "dataSource":{
                            "categories":categoriesArr,//控制甘特图时间轴日期的显示
                            "processes":{
                                "width":"100%",
                                "headertext":"",
                                "headeralign":"left",
                                "fontsize":"14",
                                "align":"center",
                                "process":[
                                    { "label":"需求收集",  "id":"xqsj" },
                                    { "label":"版本启动",  "id":"bbqd" },
                                    { "label":"需求开发",  "id":"xqkf" },
                                    { "label":"需求冻结",  "id":"xqdj" },
                                    { "label":"需求上线",  "id":"xqsx" }
                                ],//图左侧5个子任务的名称
                            },
                            "tasks":{
                                "color":"#5D62B5",
                                "task":taskArr,//控制中间日期显示的范围、颜色
                            },
                            "chart":{
                                "dateformat":"yyyy-mm-dd",//时间格式
                                "caption":name,//版本名称,即甘特图名称
                                "theme":"fusion",
                                "canvasborderalpha":"40",
                                "ganttlinealpha":"50",
                            },
                        },//数据源
                    });

                }
                self.myChart = myChartArr;
            }
     }

新图实现逻辑

1.直接把循环的主键拷贝到表格主键下方,对应的数据直接拷过来放到对应位置
2.时间轴:获取所有版本中的最早和最晚的日期
Vue+FusionCharts 动态获取数据生成甘特图_第6张图片
因为之前每个版本的图相对独立,日期获取的是当前版本的数据。现在我只想把时间轴变长一点,就先拿所有版本中的最早最晚的日期,然后获取总天数。这些数据在循环外面提前准备好,循环内部就直接拿来使用,这样就不用去拿对应版本的日期了。

加油!你肯定也可以的!^ _ ^

你可能感兴趣的:(Vue+FusionCharts 动态获取数据生成甘特图)