使用echarts折线图时,设置最大值过大的问题

617 阅读1分钟

在使用echarts折线图时,设置最大值超出Y轴的数据,会导致看着很别扭,经过长久的百度得出了结果。

    //通过这个函数可以算出Y轴的平均值

    nice(span, splitNumber, round) {
			let val = span / splitNumber;
			var exponent = Math.floor(Math.log(val) / Math.LN10);
			var exp10 = Math.pow(10, exponent);
			var f = val / exp10; // 1 <= f < 10

			var nf;

			if (round) {
				if (f < 1.5) {
					nf = 1;
				} else if (f < 2.5) {
					nf = 2;
				} else if (f < 4) {
					nf = 3;
				} else if (f < 7) {
					nf = 5;
				} else {
					nf = 10;
				}
			} else {
				if (f < 1) {
					nf = 1;
				} else if (f < 2) {
					nf = 2;
				} else if (f < 3) {
					nf = 3;
				} else if (f < 5) {
					nf = 5;
				} else {
					nf = 10;
				}
			}

			val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
			// 20 is the uppper bound of toFixed.

			const step = exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;

			let result;
			for (let i = splitNumber - 3; i < splitNumber + 3; i++) {
				result = step * i;
				if (result > span) break;
			}
			return result.toFixed(1);
		},

全部代码

<template>
	<view class="myChartBox">
		<view class="myChartTitle">
			<text></text>
			<text>{{ titleObj.明细项目 }}</text>
			<text>(单位:{{ titleObj.单位 }})</text>
		</view>
		<scroll-view :scroll-x="true" class="myChartScroll"><view id="myChart"></view></scroll-view>
	</view>
</template>

<script>
import * as echarts from 'echarts';
import { mapState } from 'vuex';
export default {
	props: ['curTableData', 'newArr'],
	data() {
		return {
			option: {
				tooltip: {
					show: true,
					trigger: 'axis'
					// confine: true, // 该属性可使tooltip一直处于容器中
					// transitionDuration: 0,
					// position: function(point, params, dom, rect, size) {
					// 	dom.style.transform = 'translateZ(0)';
					// }, //该属性解决ios手机滑动出现白条问题
					// axisPointer: {
					// 	// 坐标轴指示器,坐标轴触发有效
					// 	type: 'line', // 默认为直线,可选为:'line' | 'shadow'
					// 	shadowStyle: {
					// 		// 阴影指示器样式设置
					// 		width: 'auto', // 阴影大小
					// 		color: 'rgba(150,150,150,0.3)' // 阴影颜色
					// 	}
					// },
					// formatter: function(params) {
					// 	//对显示数据进行格式化
					// 	let result = `<span style="color:#fff; float: left; ">${params[0].name}</span>`;
					// 	params.forEach(function(item) {
					// 		if (item.data >= 0) {
					// 			result += `
					//                    <br/><span style="background: ${item.color}; width: 5px; height: 5px; border-radius: 50%; float: left; margin: 7px 3px;"></span><span style='color:${
					// 				item.color
					// 			};float: left;'>${item.seriesName}:${item.data}</span>`;
					// 		}
					// 	});
					// 	return result;
					// }
				},
				legend: {
					data: ['A设备', 'B设备', 'C设备']
				},
				grid: {
					left: '10%',
					right: '15%',
					bottom: '0%',
					containLabel: true
				},
				xAxis: {
					type: 'category',
					boundaryGap: false,
					data: ['2010-11-22 19:30:01', '2010-11-22 19:30:01', '2010-11-22 19:30:01', '2010-11-22 19:30:01', '2010-11-22 19:30:01', '2010-11-22 19:30:01'],
					axisTick: {
						show: false
					},
					axisLine: {
						show: true,
						lineStyle: {
							color: '#E6E6E6' //Y轴线条颜色
						}
					},
					axisLabel: {
						textStyle: {
							color: '#999999' //Y轴字体颜色
						},
						rotate: -40
						// formatter: (value, index) => {
						// 	const time = value.split(' ');
						// 	return `${time[0]} \n ${time[1]}`;
						// }
					}
				},
				yAxis: {
					type: 'value',
					axisLine: {
						show: true,
						lineStyle: {
							color: '#E6E6E6' //Y轴线条颜色
						}
					},
					axisLabel: {
						textStyle: {
							color: '#999999' //Y轴字体颜色
						}
					}
				},
				series: [
					{
						name: 'A设备',
						type: 'line',
						data: [80, 150, 180, 50, 240, 100],
						smooth: true, //平滑
						symbolSize: 8,
						itemStyle: {
							normal: {
								lineStyle: {
									width: 4
								}
							}
						}
					},
					{
						name: 'B设备',
						type: 'line',
						data: [130, 60, 60, 220, 99, 55],
						smooth: true, //平滑
						symbolSize: 8,
						itemStyle: {
							normal: {
								lineStyle: {
									width: 4
								}
							}
						}
					},
					{
						name: 'C设备',
						type: 'line',
						data: [140, 88, 66, 230, 130, 22],
						smooth: true, //平滑
						symbolSize: 8,
						itemStyle: {
							normal: {
								lineStyle: {
									width: 4
								}
							}
						}
					}
				]
			},
			mychar: null,
			titleObj: {}
		};
	},
	computed: {
		...mapState(['mycharData'])
	},
	mounted() {
		this.$nextTick(() => {});
	},
	watch: {
		newArr: {
			handler(val) {
				this.init();
			},
			deep: true
		}
	},
	methods: {
		// 初始化数据
		init() {
			// 如果不为1 就不画
			if (this.newArr.是否数字 != 1) return;
			if (!this.mychar) {
				this.mychar = echarts.init(document.querySelector('#myChart'));
			}
			const series = [];
			const date = [];
			const legend = [];
			const arr = this.newArr.data;
			const obj = {};
			this.titleObj = arr[0];
			arr.forEach(item => {
				// date.push({
				// 	key: item.仪器,
				// 	time: item.检查日期
				// });
				date.push(item.检查日期);
				if (!obj[item['仪器']]) {
					obj[item['仪器']] = {
						key: item.仪器,
						children: []
					};
					legend.push(item.仪器);
				}
				obj[item['仪器']].children.push({
					num: item.检验结果,
					time: item.检查日期
				});
			});
			const arr2 = Object.values(obj);
			arr2.forEach(item => {
				series.push({
					name: item.key,
					type: 'line',
					data: this.update(item.children, date),
					smooth: true, //平滑
					symbolSize: 8,
					itemStyle: {
						normal: {
							lineStyle: {
								width: 4
							}
						}
					},
					markLine: {
						// symbol: ['none', 'none'], //去掉箭头
						symbol: 'none',
						data: [
							{
								name: '最小值',
								type: 'min',
								yAxis: this.titleObj.参考区间最小值,
								label: {
									position: 'middle',
									color: 'red',
									formatter: () => {
										return `最小值(${this.titleObj.参考区间最小值})`;
									}
								},
								lineStyle: {
									color: 'red'
								}
							},
							{
								name: '最小值',
								type: 'max',
								yAxis: this.titleObj.参考区间最大值,
								label: {
									position: 'middle',
									color: 'red',
									formatter: () => {
										return `最大值(${this.titleObj.参考区间最大值})`;
									}
								},
								lineStyle: {
									color: 'red'
								}
							}
						]
					}
				});
			});
			this.option.xAxis.data = date;
			this.option.series = series;
			this.option.legend.data = legend;
			this.option.yAxis = {
				type: 'value',
				axisLine: {
					show: true,
					lineStyle: {
						color: '#E6E6E6' //Y轴线条颜色
					}
				},
				axisLabel: {
					textStyle: {
						color: '#999999' //Y轴字体颜色
					}
				},
				max: extent => {
					const max = extent.max > arr[0].参考区间最大值 ? extent.max : arr[0].参考区间最大值;
					return this.nice(max, 5, true);
				}
			};
			this.mychar.setOption(this.option, true);
		},
		/**
		 * @param span series 中最大值与最小值的差值
		 * @param splitNumber 坐标轴分割段数
		 * @param round 折线图中需要传 true
		 * @returns {number} 处理后 max 的最后结果
		 */
		nice(span, splitNumber, round) {
			let val = span / splitNumber;
			var exponent = Math.floor(Math.log(val) / Math.LN10);
			var exp10 = Math.pow(10, exponent);
			var f = val / exp10; // 1 <= f < 10

			var nf;

			if (round) {
				if (f < 1.5) {
					nf = 1;
				} else if (f < 2.5) {
					nf = 2;
				} else if (f < 4) {
					nf = 3;
				} else if (f < 7) {
					nf = 5;
				} else {
					nf = 10;
				}
			} else {
				if (f < 1) {
					nf = 1;
				} else if (f < 2) {
					nf = 2;
				} else if (f < 3) {
					nf = 3;
				} else if (f < 5) {
					nf = 5;
				} else {
					nf = 10;
				}
			}

			val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
			// 20 is the uppper bound of toFixed.

			const step = exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;

			let result;
			for (let i = splitNumber - 3; i < splitNumber + 3; i++) {
				result = step * i;
				if (result > span) break;
			}
			return result.toFixed(1);
		},
		/**
		 * @param {Array} arr 每个仪器的数据
		 * @param {Array} nArr 时间
		 * @returns {Array} 每个仪器处理过后的数据
		 */
		update(arr, nArr) {
			const arrs = [...arr];
			nArr.forEach(time => {
				arrs.push({ num: null, time });
			});
			const obj = {};
			arrs.forEach(item => {
				if (!obj[item['time']]) {
					obj[item['time']] = {
						time: item.time,
						num: item.num
					};
				}
			});
			const newARR = Object.values(obj)
				.sort((a, b) => a.time.localeCompare(b.time))
				.map(item => item.num);
			return newARR;
		}
	}
};
</script>

<style scoped lang="scss">
.myChartBox {
	width: 100%;
	height: 100%;
	background-color: white;
	overflow: hidden;
	.myChartTitle {
		width: 750rpx;
		height: 80rpx;
		display: flex;
		align-items: center;
		font-size: 34rpx;
		color: #333;
		font-weight: bold;
		text:nth-child(1) {
			width: 8rpx;
			height: 28rpx;
			background-color: #3c74f6;
			margin: 0 10rpx 0 32rpx;
		}
		text:nth-child(3) {
			font-size: 24rpx;
			font-weight: 500;
			color: #999999;
		}
	}
	#myChart {
		width: 800rpx;
		// height: calc(100% - 80rpx);
		height: 100%;
	}
	.myChartScroll {
		width: 100%;
		height: calc(100% - 80rpx);
	}
}
</style>

很久之前百度到的,忘记出处了,怕忘记故此记录下