测试echarts time配置项内容和展示

配置项如下
      /**
 * 存储阶段进度时间段的对象
 */
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 if (months <= 24) {
		xAxisLabelUnit.month = true;
		return timeInterval.month * 2;
	} else if (years <= 16) {
		xAxisLabelUnit.year = true;
		return timeInterval.year;
	}
}
 
/**
 * 获取横轴坐标数据源,这里横坐标只显示年月
 * 最小值取传入数据最小的时间再减小一个月
 * 最大值取传入数据最小的时间再增加一个月
 */
function getXAxisData() {
	var arr = new Array();
	arr = arr.concat(stageProgress.scheduledStartTime)
		.concat(stageProgress.fangAnTimeBucket)
		.concat(stageProgress.gangYaoTimeBucket)
		.concat(stageProgress.chengGuoTimeBucket)
		.concat(stageProgress.validTime).filter(function(item) {
			return item != "-";
		}).sort();
	console.log(arr);
	return arr;
}
 
/**
 * 更改日期字符串为相应月份的第一天
 * @param {Object} dateStr 日期字符串
 */
function changeDateToMonthFirstDay(dateStr) {
	var inputDate = new Date(dateStr);
	inputDate.setDate(1);
	var result = inputDate.getFullYear() + "-" +
		(inputDate.getMonth() >= 9 ? inputDate.getMonth() + 1 : "0" +
			(inputDate.getMonth() + 1)) + "-" + ("0" + 1);
	return result;
}
 
/**
 * 获取格式化的日期 YYYY-MM-dd
 */
function formatDateToStr(date) {
	var inputMonth = date.getMonth();
	var inputDate = date.getDate();
	var result = date.getFullYear() +
		"-" + (inputMonth >= 9 ? inputMonth + 1 : "0" + (inputMonth + 1)) +
		"-" + (inputDate >= 9 ? inputDate : "0" + (inputDate));
	return result;
}
 
var faOnTimeCompletionTime = getOnTimeCompletionTime('方案', stageProgress.fangAnTimeBucket[0], stageProgress.fangAnTimeBucket[
	1]);
var gyOnTimeCompletionTime = getOnTimeCompletionTime('纲要', stageProgress.gangYaoTimeBucket[0], stageProgress.gangYaoTimeBucket[
	1]);
var cgOnTimeCompletionTime = getOnTimeCompletionTime('成果', stageProgress.chengGuoTimeBucket[0], stageProgress.chengGuoTimeBucket[
	1]);
 
var faOverTimeCompletionTime = getOverTimeCompletionTime('方案', stageProgress.fangAnTimeBucket[0], stageProgress.fangAnTimeBucket[
	1]);
var gyOverTimeCompletionTime = getOverTimeCompletionTime('纲要', stageProgress.gangYaoTimeBucket[0], stageProgress.gangYaoTimeBucket[
	1]);
var cgOverTimeCompletionTime = getOverTimeCompletionTime('成果', stageProgress.chengGuoTimeBucket[0], stageProgress.chengGuoTimeBucket[
	1]);
 
/**
 * 时间数组
 */
var timeArray = {
	// 开始时间
	beginTimeArr: [
		getTimeMilliseconds(stageProgress.fangAnTimeBucket[0]),
		getTimeMilliseconds(stageProgress.gangYaoTimeBucket[0]),
		getTimeMilliseconds(stageProgress.chengGuoTimeBucket[0]),
	],
	// 按时完成时间
	onTimeCompletionTimeArr: [
		getTimeMilliseconds(faOnTimeCompletionTime),
		getTimeMilliseconds(gyOnTimeCompletionTime),
		getTimeMilliseconds(cgOnTimeCompletionTime),
	],
	// 超时完成时间
	overTimeCompletionTimeArr: [
		getTimeMilliseconds(faOverTimeCompletionTime),
		getTimeMilliseconds(gyOverTimeCompletionTime),
		getTimeMilliseconds(cgOverTimeCompletionTime),
	],
};

// 构建图表配置项
option = {
	tooltip: {
		trigger: 'axis',
		axisPointer: {
			type: 'shadow',
		},
 
		/**
		 * 也可以使用 formatter: '{b0}:<br />{a0}: {c0}<br />{a1}: {c1}<br />{a2}: {c2}',
		 * 但是这样当鼠标指向纵坐标的三个阶段中的某一个时,即使该阶段 没有按时完成,或者 没有超时,
		 * 也会显示 按时 或 超时 的 tooltip
		 */
		formatter: function(params) {
// 			console.log("params[0]" + JSON.stringify(params[0]));
// 			console.log("params[1]" + JSON.stringify(params[1]));
			console.log("params[2]" + JSON.stringify(params[2]));
			var info = params[0].axisValue + ":<br />";
			info += params[0].seriesName + ":" + getSeriesDateStr(params[0].data) + "<br />";
			info += "结束时间:" + (params[2].data != "-" && params[2].data != undefined && params[2].data != null&&!isNaN(params[2].data) ?
				getSeriesDateStr(params[2].data) :
				(!isNaN(params[1].data)&&params[1].data != undefined && params[1].data != null ? getSeriesDateStr(params[1].data) : "-"));
			return info;
		},
	},
 
	/**
	 * 右上角工具栏
	 */
	toolbox: {
		right: '3%',
		show: false,
		feature: {
			/**
			 * 数据视图
			 */
			// 			dataView:{
			// 				show:true,
			// 			},
			saveAsImage: {
				show: true
			}
		}
	},
 
	/**
	 * 图例
	 */
	legend: {
		data: ['按时完成', '超时完成'],
		tooltip: {
			show: true,
		},
		itemWidth: 15,
		itemHeight: 15,
		textStyle: {
			fontSize: 16,
			fontFamily: 'Microsoft YaHei',
		},
		itemGap: 120,
		padding: 10,
	},
 
	/**
	 * 直角坐标系内绘图网格
	 */
	grid: {
		left: '3%',
		right: '3%',
		bottom: '2%',
		/**
		 * grid 区域是否包含坐标轴的刻度标签。
		 */
		containLabel: true,
	},
 
	/**
	 * 横坐标
	 */
	xAxis: {
		// 		/**
		// 		 * 坐标轴指示器
		// 		 */
		// 		axisPointer: {
		// 			show: true,
		// 		},
 
		/**
		 * 时间轴,适用于连续的时序数据,与数值轴相比时间轴带有时间的格式化,
		 * 在刻度计算上也有所不同,例如会根据跨度的范围来决定使用月,星期,日还是小时范围的刻度。
		 */
		type: 'time',
 
		/**
		 * value 是一个包含 min 和 max 的对象,分别表示数据的最大最小值,这个函数应该返回坐标轴的最大值。
		 *
		 * 坐标轴刻度最小值。
		 */
		min: function(value) {
			return value.min + (getTimeMilliseconds(getProperTimeAxisBeginAndEndTime()[0]) - value.min);
		},
 
		/**
		 * value 是一个包含 min 和 max 的对象,分别表示数据的最大最小值,这个函数应该返回坐标轴的最大值。
		 *
		 * 坐标轴刻度最大值。
		 */
		max: function(value) {
			return value.max + (getTimeMilliseconds(getProperTimeAxisBeginAndEndTime()[1]) - value.max);
		},
		// 
		/**
		 * 设置坐标轴分割间隔
		 */
		interval: getProperTimeAxisInterval(),
		axisLine: {
			lineStyle: {
				color: '#BDC8CD',
				width: 1,
			},
		},
 
		/**
		 * 坐标轴刻度标签的相关设置。
		 */
		axisLabel: {
			showMinLabel: false,
			showMaxLabel: false,
			rotate: 35,
			margin: 12,
			fontSize: 16,
			color: '#1c2431',
			formatter: function(value, index) {
				var date = new Date(value);
				// var time = date.getFullYear() + "." + (date.getMonth() + 1) + "." + date.getDate();
				var time = date.getFullYear();
				if (xAxisLabelUnit.month) {
					time += "." + (date.getMonth() + 1);
				}
				if (xAxisLabelUnit.day) {
					time += "." + (date.getMonth() + 1) + '.' + date.getDate();
				}
				return time;
			},
		},
 
		/**
		 * 坐标轴刻度分割线
		 */
		splitLine: {
			show: false,
		},
	},
 
	/**
	 * 纵坐标
	 */
	yAxis: {
		type: 'category',
		data: ['方\n案', '纲\n要', '成\n果'],
		axisTick: {
			show: false,
		},
		axisLine: {
			lineStyle: {
				color: '#e9e9ea',
				width: 1,
			},
		},
		axisLabel: {
			fontWeight: 'bold',
			fontSize: 16,
			color: '#1c2431',
			fontFamily: 'Microsoft YaHei',
		},
		splitLine: {
			show: true,
			lineStyle: {
				color: '#eaeae9',
				width: 1,
			},
		},
	},
 
	/**
	 * 系列
	 */
	series: [{
		name: '开始时间',
		type: 'bar',
		stack: '时间',
		itemStyle: {
			normal: {
				barBorderColor: 'rgba(0,0,0,0)',
				color: 'rgba(0,0,0,0)'
			},
			emphasis: {
				barBorderColor: 'rgba(0,0,0,0)',
				color: 'rgba(0,0,0,0)'
			}
		},
		label: {
			normal: {
				formatter: function(params) {
					return getSeriesDateStr(params.value);
				},
				show: true,
				position: 'insideRight',
				fontSize: 16,
				color: '#1c2431',
				fontFamily: 'Microsoft YaHei',
				offset: [40, -20],
			}
		},
		data: timeArray.beginTimeArr,
 
		/**
		 * 标注线
		 */
		markLine: {
			lineStyle: {
				normal: {
					color: '#0f77e9',
				},
			},
			label: {
				normal: {
					fontWeight: 'bold',
					padding: 2,
					fontSize: 14,
					fontFamily: 'Microsoft YaHei',
					formatter: function(params) {
						return '计划开始时间 ' + getSeriesDateStr(params.value);
					},
				},
			},
			data: [{
				name: '计划开始时间',
				xAxis: getTimeMilliseconds(stageProgress.scheduledStartTime),
			}, ]
		},
	}, {
		name: '按时完成',
		type: 'bar',
		stack: '时间',
		itemStyle: {
			normal: {
				color: '#0f77e9'
			}
		},
		label: {
			normal: {
				formatter: function(params) {
					return getSeriesDateStr(params.value);
				},
				show: true,
				fontSize: 16,
				color: '#1c2431',
				position: 'right',
				fontFamily: 'Microsoft YaHei',
				offset: [-45, -20],
			}
		},
		data: timeArray.onTimeCompletionTimeArr,
		markLine: {
			lineStyle: {
				normal: {
					color: '#ff4747',
				},
 
			},
			label: {
				normal: {
					fontWeight: 'bold',
					padding: 2,
					fontSize: 14,
					fontFamily: 'Microsoft YaHei',
					formatter: function(params) {
						return '计划完成时间 ' + getSeriesDateStr(params.value);
					},
				},
			},
			data: [{
				name: '有效期',
				xAxis: getTimeMilliseconds(stageProgress.validTime),
			}, ]
		},
	}, {
		name: '超时完成',
		type: 'bar',
		stack: '时间',
		itemStyle: {
			normal: {
				color: '#ff4747'
			}
		},
		label: {
			normal: {
				formatter: function(params) {
					return getSeriesDateStr(params.value);
				},
				show: true,
				fontSize: 16,
				color: '#1c2431',
				offset: [-45, -20],
				position: 'right',
				fontFamily: 'Microsoft YaHei',
			}
		},
		data: timeArray.overTimeCompletionTimeArr,
		/**
		 * 柱状图宽度
		 */
		barWidth: 20,
	}, ]
};
 
/**
 * 时间对象转日期字符串 yyyy.MM.dd
 * @param {Object} timeObject 毫秒值或时间字符串
 */
function getSeriesDateStr(timeObject) {
	if (timeObject == "-") {
		return timeObject;
	}
	var date = new Date(timeObject);
	var dateStr = '';
	dateStr += date.getFullYear() + '.';
	dateStr += date.getMonth() + 1 + '.';
	dateStr += date.getDate();
	return dateStr;
};
 
/**
 * 获取阶段的计划内完成时间(蓝色柱状图值)
 * @param {Object} stage 阶段
 * @param {Object} stateBeginTime
 * @param {Object} stateCompletionTime
 */
function getOnTimeCompletionTime(stage, stageBeginTimeStr, stageCompletionTimeStr) {
	var validTimeMillis = getTimeMilliseconds(stageProgress.validTime);
	var stageBeginTimeMillis = getTimeMilliseconds(stageBeginTimeStr);
	var stageCompletionTimeMillis = getTimeMilliseconds(stageCompletionTimeStr);
	if (validTimeMillis <= stageBeginTimeMillis) {
		// 若阶段开始时间大于等于有效期,则项目超时完成,有效时间为'-'
		return '-';
	}
	if (validTimeMillis > stageBeginTimeMillis && validTimeMillis < stageCompletionTimeMillis) {
		// 若有效期介于阶段完成时间和阶段开始时间之间,则该阶段按时完后时间(实际该阶段是超时完成的)即蓝色柱状图的终值为有效期
		return stageProgress.validTime;
	}
	if (validTimeMillis >= stageCompletionTimeMillis) {
		// 若有效期大于等于阶段完成时间,则阶段按时完成
		return stageCompletionTimeStr;
	}
}
 
/**
 * 获取阶段内的超时完成时间(红色色柱状图值)
 * @param {Object} stage 阶段
 * @param {Object} stateBeginTime
 * @param {Object} stateCompletionTime
 */
function getOverTimeCompletionTime(stage, stageBeginTimeStr, stageCompletionTimeStr) {
	var validTimeMillis = getTimeMilliseconds(stageProgress.validTime);
	var stageBeginTimeMillis = getTimeMilliseconds(stageBeginTimeStr);
	var stageCompletionTimeMillis = getTimeMilliseconds(stageCompletionTimeStr);
 
	if (validTimeMillis < stageCompletionTimeMillis) {
		// 阶段完成时间大于有效期,则将阶段完成时间作为超时时间返回
		return stageCompletionTimeStr;
	}
 
	if (validTimeMillis >= stageCompletionTimeMillis) {
		// 阶段完成时间小于等于有效期,则阶段按时完成,超时时间应为'-'
		return '-';
	}
}
 
/**
 * 根据时间字符串获取对应的毫秒值
 * @param {Object} timeStr 时间字符串
 */
function getTimeMilliseconds(timeStr) {
	return (new Date(timeStr)).getTime();
}
 
/**
 *获取时间坐标轴的起始和结束值
 */
function getProperTimeAxisBeginAndEndTime() {
	var xAxis = getXAxisData();
	var begin = xAxis[0];
	var end = xAxis[xAxis.length - 1];
	var beginDate = new Date(begin);
	var endDate = new Date(end);
 
	if (xAxisLabelUnit.month) {
		beginDate.setDate(1);
		endDate.setMonth(endDate.getMonth() + 1);
		endDate.setDate(1);
	} else {
		var daysCount = getProperTimeAxisInterval() / timeInterval.day;
		console.log("daysCount " + daysCount);
		beginDate.setDate(beginDate.getDate() - daysCount);
		endDate.setDate(endDate.getDate() + daysCount);
	}
	var beArr = [formatDateToStr(beginDate), formatDateToStr(endDate)];
	console.log("beArr " + beArr);
	return beArr;
}
    
截图如下