echarts 拖动markline,并计算中间区域的差值,标注红色虚线

在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<!-- 引入 echarts.js -->
		<script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts-en.common.js" rel="external nofollow">
		</script>
		<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
	</head>
	<body>
		<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
		<div id="main" style="width: 600px;height:400px;" class="mychart"></div>
		<script type="text/javascript">
			var id = "main";
			// 基于准备好的dom,初始化echarts实例
			var myChart = echarts.init(document.getElementById('main'));
			// 指定图表的配置项和数据
			var yName = '单位';
			var seriesData = [
				[0, 1],
				[1, 5],
				[2, 4],
				[3, 8],
				[4, 6]
			];
			var colors = ['#EE6666', '#48D1CC', '#FAC858', '#91CC75', '#EA7CCC',
				'#9A60B4', '#3BA272', '#FC8452', '#E53E71', '#5470C6'
			];
			var option = {
				color: colors,
				title: {
					text: "",
					textStyle: {
						// color: 'white',
						color: 'black',
						fontWeight: 400,
						fontSize: 16
					},
					left: 'center',
					top: '0%'
				},
				tooltip: {
					trigger: "axis",
					axisPointer: {
						lineStyle: {
							color: "#888888"
						}
					}
				},
				legend: {
					top: "30",
					x: "center",
					textStyle: {
						//color: "white",
						color: "black",
						fontSize: 12
					},
				},
				toolbox: {
					show: true,
					feature: {
						dataView: {
							readOnly: false
						},
						magicType: {
							type: ['line', 'bar']
						},
						restore: {},
						saveAsImage: {}
					}
				},
				grid: {
					top: '20%',
					bottom: '15%',
					left: '2%',
					right: '10%',
					containLabel: true
				},
				xAxis: [{
					id: 'x0',
					type: "category",
					boundaryGap: true,
					axisLabel: {
						textStyle: {
							//color: "#FFF",
							color: "black",
							fontSize: 12
						}
					},
					axisLine: {
						show: true,
						lineStyle: {
							//color: "black",
							color: "black"
						}
					},
					axisTick: {
						show: false
					},
				}, {
					axisPointer: {
						show: false
					},
					axisLine: {
						show: false
					},
					position: "bottom",
					offset: 20
				}],
				yAxis: [{
					id: '2',
					name: yName,
					nameTextStyle: {
						//color: '#FFF',
						color: "black",
						fontSize: 12,
					},
					type: "value",
					axisTick: {
						show: false
					},
					axisLine: {
						show: true,
						lineStyle: {
							color: "black"
						}
					},
					axisLabel: {
						formatter: '{value}',
						textStyle: {
							//color: "#FFF",
							color: 'black',
							fontSize: 12
						}
					},
					splitLine: {
						show: false
					}
				}],
				dataZoom: [{
					type: 'inside',
					xAxisIndex: 0,
					zoomLock: false,
					filterMode: 'empty',
				}],
				series: [{
					id: 'serie0',
					type: 'line',
					z: 1,
					data: seriesData,
					symbolSize: 10,
					symbol: 'circle',
					smooth: true,
					itemStyle: {
						normal: {
							color: '#EE6666'
							//color: 'rgba(0,245,255,0.9)' 蓝色
						}
					},
					emphasis: {
						focus: 'series'
					},
					markPoint: {
						symbol: 'pin',
						// 标记的数据,可以是最大值最小值也可以是自定义的坐标
						data: []
					},
				}, {
					id: 'vline',
					z: 2,
					data: seriesData,
					type: 'line',
					// 隐藏series
					symbolSize: 0,
					showSymbol: false,
					lineStyle: {
						width: 0,
						color: 'rgba(0, 0, 0, 0)'
					},
					markPoint: {
						symbol: 'pin',
						// 标记的数据,可以是最大值最小值也可以是自定义的坐标
						data: []
					},
				}]
			};

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

			//绘制垂直markLine
			myChart.setOption(getVlineOpt(0, 2));

			function getMarkAxis() {
				var result = new Object();
				var option = myChart.getOption();
				$.each(option.series, function(i, series) {
					if (series.id == 'vline') {
						var markLine = series.markLine;
						result['L1'] = markLine.data[0].xAxis;
						result['L2'] = markLine.data[1].xAxis;
						return false;
					}
				});
				return result;
			}

			function getVlineOpt(x1, x2, select) {
				if (x1 == null || x1 == undefined) {
					x1 = getMarkAxis()['L1'];
				}
				if (x2 == null || x2 == undefined) {
					x2 = getMarkAxis()['L2'];
				}
				var color1 = '#FFBE00';
				var color2 = '#FFBE00';
				if (select == 'L1') {
					color1 = '#111111';
				}
				if (select == 'L2') {
					color2 = '#111111';
				}

				var option = {
					series: [{
						id: 'vline',
						markLine: {
							symbol: 'none',
							silent: true,
							label: {
								show: true,
							},
							data: [{
								xAxis: x1,
								name: 'L1',
								lineStyle: {
									normal: {
										type: "dashed",
										width: 1,
										color: color1
									}
								}
							}, {
								xAxis: x2,
								name: 'L2',
								lineStyle: {
									normal: {
										type: "dashed",
										width: 1,
										color: color2
									}
								}
							}]
						},
						markPoint: {
							symbol: 'pin',
							// 标记的数据,可以是最大值最小值也可以是自定义的坐标
							data: []
						},
					}]
				};
				return option;
			}

			//绘制L值的graphic line
			var myHeight = myChart.getHeight() - 50;
			var myWidth = myChart.getWidth() - 50;
			
			myChart.setOption({
				graphic: {
					elements: [{
						type: 'rect',
						id: 'rect1',
						name: 'rect1',
						bottom: -myHeight,
						z: 10,
						invisible: true,
						shape: {
							width: 0,
							height: myHeight * 2
						},
						style: {
							fill: 'rgba(128,128,128,1)',
							stroke: 'rgba(128,128,128,1)',
							lineWidth: 6
						},
						// 转换坐标系上的点到像素坐标值
						position: [myChart.convertToPixel({
							xAxisId: 'x0'
						}, getMarkAxis()['L1']), 0],
						bouding: 'all',
						cursor: 'move',
						draggable: true,
						ondragstart: onLineDragStart,
						ondragend: onLineDragEnd
					}, {
						type: 'rect',
						id: 'rect2',
						name: 'rect2',
						bottom: -myHeight,
						z: 9,
						invisible: true,
						shape: {
							width: 0,
							height: myHeight * 2
						},
						style: {
							fill: 'rgba(128,128,128,1)',
							stroke: 'rgba(128,128,128,1)',
							lineWidth: 6
						},
						//转换坐标系上的点到像素坐标值
						position: [myChart.convertToPixel({
							xAxisId: 'x0'
						}, getMarkAxis()['L2']), 0],
						bouding: 'all',
						cursor: 'move',
						draggable: true,
						ondragstart: onLineDragStart,
						ondragend: onLineDragEnd
					}]
				}
			});

			//拖拽开始markline变色
			function onLineDragStart() {
				var graphicId = this.__ecGraphicId;
				if (graphicId == 'rect1') {
					myChart.setOption(getVlineOpt(null, null, 'L1'));
				} else if (graphicId == 'rect2') {
					myChart.setOption(getVlineOpt(null, null, 'L2'));
				}
			}

			//垂直线重新定位,拖拽结束markLine和graphic确定位置
			function onLineDragEnd() {
				//console.log(this.position);
				try {
					//转换像素坐标值到逻辑坐标系上的点,是convertToPixel的逆运算
					var x = getXAxis(this.position[0]);

					//markLine重新定位
					var vline_opt = {};
					var graphicId = this.__ecGraphicId;
					if (graphicId == 'rect1') {
						vline_opt = getVlineOpt(x, null);
					} else if (graphicId == 'rect2') {
						vline_opt = getVlineOpt(null, x);
					}
					myChart.setOption(vline_opt);

					//graphic重新定位
					var graph_opt = getGraphicOpt();
					myChart.setOption(graph_opt);


				} catch (e) {
					console.log('垂直线移动失败。');
					console.log(e);
				}
			}

			function getXAxis(Xpx) {
				var seriesData = getSeriesData(myChart, 'serie0');
				var x = myChart.convertFromPixel({
					xAxisId: 'x0'
				}, Xpx);
				if (x <= 0) {
					x = 0;
				} else if (x >= seriesData.length) {
					x = seriesData.length - 1;
				}
				return x;
			}

			function getSeriesData(myChart, serieId) {
				var data = [];
				try {
					var series = myChart.getOption().series;
					$.each(series, function(i, serie) {
						if (serie.id == serieId) {
							data = serie.data;
							return false;
						}
					});
				} catch (e) {
					console.log("获取数据失败。");
					console.log(e);
				}
				return data;
			}


			function onAreaDragEnd() {
				try {
					var x_start = getXAxis(this.position[0] - 5);
					var x_end = getXAxis(this.position[0] + this.shape.width + 5);

					//markLine重新定位
					var vline_opt = {};
					var result = getMarkAxis();
					if (result['L1'] < result['L2']) {
						vline_opt = getVlineOpt(x_start, x_end);
					} else {
						vline_opt = getVlineOpt(x_end, x_start);
					}
					myChart.setOption(vline_opt);

					//graphic重新定位
					var graph_opt = getGraphicOpt();
					myChart.setOption(graph_opt);

					//getX(id, x_start, x_end);
				} catch (e) {
					console.log('垂直线移动失败。');
					console.log(e);
				}
			}
			//graphic重新定位
			function getGraphicOpt() {
				var result = getMarkAxis();
				var option = {
					graphic: {
						elements: [{
								id: 'rect1',
								$action: 'merge',
								position: [myChart.convertToPixel({
									xAxisId: 'x0'
								}, result['L1']), 0]
							},
							{
								id: 'rect2',
								$action: 'merge',
								position: [myChart.convertToPixel({
									xAxisId: 'x0'
								}, result['L2']), 0]
							}
						]
					}
				};
				return option;
			}
			// 防止datazoom缩放,markline无法拖动
			myChart.on('dataZoom', (param) => {
				var graph_opt = getGraphicOpt();
				myChart.setOption(graph_opt);
			})
		</script>
	</body>
</html>
Echarts 中的 markline 组件默认是不能拖动的,但是我们可以通过监听鼠标事件和 markline 的位置属性,手动实现 markline拖动。 具体实现步骤如下: 1. 在 option 中定义 markline 组件,设置其相关属性,例如起点、终点、样式等。 2. 监听鼠标事件,当鼠标按下时,记录鼠标在图表中的位置和 markline 的起始位置。 3. 监听鼠标事件,当鼠标移动时,计算鼠标在图表中的位置与起始位置的差值,并将其加到 markline 的起始位置上。 4. 在 markline 上添加 draggable 属性,使其能够被拖动。同时,设置 label 的 position 为 'middle',以保证 label 文字显示在 markline 上方。 下面是一个示例代码: ``` option = { // 其他配置项 series: [{ type: 'line', data: [10, 20, 30, 40, 50], markLine: { silent: true, // 取消鼠标点击事件 symbol: 'none', label: { position: 'middle', formatter: 'Markline' }, lineStyle: { color: '#333' }, data: [{ yAxis: 30 }] } }] }; var chart = echarts.init(document.getElementById('main')); var markline = chart.getModel().getComponent('series', 0).getMarkLineModel(0); var start = null; chart.getZr().on('mousedown', function(params) { start = chart.convertFromPixel({ gridIndex: 0 }, [params.offsetX, params.offsetY]); }); chart.getZr().on('mousemove', function(params) { if (!start) { return; } var end = chart.convertFromPixel({ gridIndex: 0 }, [params.offsetX, params.offsetY]); var diff = end[1] - start[1]; markline.option.data[0].yAxis += diff; start = end; chart.setOption({ series: [{ markLine: markline.option }] }); }); chart.getZr().on('mouseup', function(params) { start = null; }); markline.option.label.show = true; markline.option.draggable = true; ``` 在上述代码中,我们首先定义了一个 markline,设置其样式和位置。然后监听了鼠标事件,当鼠标按下时,记录 markline 的起始位置。当鼠标移动时,计算鼠标位置与起始位置的差值,并将其加到 markline 的起始位置上,从而实现 markline拖动。在 markline 上添加了 draggable 属性,使其能够被拖动,同时设置 label 的 position 为 'middle',以保证 label 文字显示在 markline 上方。最后,我们将 markline 的 option 通过 setOption 方法设置到图表中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值