echart 移动端进行双指缩放时,当放大到最大级别后,手指没有离开屏幕,图表还会自动移动问题修复

31 阅读2分钟

echarts.min.js 源码修复

version: 6.0.0
格式化后搜索 zoom: function

未修复源码 zoom 缩放关键部分

zoom: function(t, e, n, i) {
	var r = this.range,
		o = r.slice(),
		a = t.axisModels[0];
	if (a) return a = (0 < (e = bI[e](null, [i.originX, i.originY], a, n, t)).signal ? e
		.pixelStart + e.pixelLength - e.pixel : e.pixel - e.pixelStart) / e.pixelLength * (
		o[1] - o[0]) + o[0], n = Math.max(1 / i.scale, 0), o[0] = (o[0] - a) * n + a, o[1] =
		(o[1] - a) * n + a, jC(0, o, [0, 100], 0, (t = this.dataZoomModel
		.findRepresentativeAxisProxy().getMinMaxSpan()).minSpan, t.maxSpan), this.range = o,
		r[0] !== o[0] || r[1] !== o[1] ? o : void 0
},

已修复源码

zoom: function(t, e, n, i) {
	/* t: dataZoomModel (当前缩放组件的模型) */
	/* e: coordSysType (坐标系类型,如 'grid') */
	/* n: api (ECharts 实例 API) */
	/* i: payload (包含缩放比例 scale 和 鼠标位置 originX/Y) */
	var r = this.range, // 当前视图百分比范围 [start, end]
		o = r.slice(), // 复制一份范围用于计算
		a = t.axisModels[0]; // 获取关联的轴模型
	if (a) {
		/* 计算缩放中心点 a (百分比 0-100) */
		/* bI[e](...) 根据像素位置 originX/Y 计算其在坐标轴上的位置比例 */
		// a = (0 < (e = bI[e](null, [i.originX, i.originY], a, n, t)).signal ? e.pixelStart + e.pixelLength - e.pixel : e.pixel - e.pixelStart) / e.pixelLength * (o[1] - o[0]) + o[0];
		
		/* 固定缩放中心点 a 为当前显示范围的中点 */
		a = (o[0] + o[1]) / 2;

		/* n: 缩放后的比例因子 (scale > 1 表示缩小视图/放大倍率) */
		n = Math.max(1 / i.scale, 0);
		
		/* s: 计算出的预期起始百分比 (start) */
		/* l: 计算出的预期结束百分比 (end) */
		var s = (o[0] - a) * n + a,
			l = (o[1] - a) * n + a;

		/* 防止遇到边界打断缩放 */
		if (s < 0) {
			l -= s;
			s = 0;
		}
		
		if (l > 100) {
			s -= l - 100;
			l = 100;
		}

		/* u: 获取配置中的最小/最大缩放范围 (minSpan/maxSpan/minValueSpan...) */
		var u = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(),
			h = Math.abs(l - s); // 预期范围的跨度
		
		/* 核心逻辑:如果缩放后的范围超出了 0-100 边界,或者违反了跨度约束,则直接放弃本次操作(返回空) */
		/* 这样可以防止 ECharts 内部通过平移来修正边界(即漂移/抖动) */
		if (
			s < -0.1 ||
			l > 100.1 ||
			(null != u.minSpan && h < u.minSpan) ||
			(null != u.maxSpan && h > u.maxSpan)
		) return;
		
		/* 如果符合条件,则更新当前范围并返回结果 */
		return o[0] = s, o[1] = l, this.range = o, o
	}
},

ps: 个人摸索,如有问题请告知 🙇