import { gsap } from "gsap";

/**
 * 画布动画管理器
 * 负责处理画布平移、缩放等动画效果
 */
export class AnimationManager {
	/**
	 * 创建动画管理器
	 * @param {fabric.Canvas} canvas fabric.js画布实例
	 * @param {Object} options 配置选项
	 */
	constructor(canvas, options = {}) {
		this.canvasManager = options.canvasManager;
		this.canvas = canvas;
		this.currentZoom = options.currentZoom;

		// 动画相关属性
		this._zoomAnimation = null;
		this._panAnimation = null;
		this._lastWheelTime = 0;
		this._lastWheelProcessTime = 0; // 上次处理wheel事件的时间
		this._wheelEvents = [];

		// 检测设备类型，Mac设备使用更短的节流时间确保响应性
		this._isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
		this._wheelThrottleTime = this._isMac
			? options.wheelThrottleTime || 8 // Mac设备使用更短的节流时间
			: options.wheelThrottleTime || 30;

		this._accumulatedWheelDelta = 0; // 累积滚轮增量
		this._wheelAccumulationTimeout = null; // 滚轮累积超时

		// Mac设备使用更短的累积时间窗口，确保及时响应
		this._wheelAccumulationTime = this._isMac ? 60 : 120; // 滚轮累积时间窗口(毫秒)

		// 添加新的状态跟踪变量
		this._wasPanning = false; // 是否有平移动画正在进行
		this._wasZooming = false; // 是否有缩放动画正在进行
		this._combinedAnimation = null; // 组合动画引用

		// Mac特有的动画优化变量 - 使用最小防抖机制
		if (this._isMac) {
			this._lastMacAnimationTime = 0; // 上次Mac动画时间
			this._macAnimationCooldown = 2; // 最小的动画冷却时间，确保最大响应性
		}

		// 初始化GSAP默认配置
		gsap.defaults({
			ease: options.defaultEase || (this._isMac ? "power2.out" : "power2.out"), // Mac使用简单高效的缓动
			duration: options.defaultDuration || (this._isMac ? 0.3 : 0.3), // Mac使用标准持续时间
			overwrite: "auto", // 自动覆盖同一对象上的动画
		});
	}

	/**
	 * 使用 GSAP 实现平滑缩放动画
	 * @param {Object} point 缩放中心点 {x, y}
	 * @param {Number} targetZoom 目标缩放值
	 * @param {Object} options 动画选项
	 */
	animateZoom(point, targetZoom, options = {}) {
		if (!this.canvas) return;

		// 限制缩放范围
		targetZoom = Math.min(Math.max(targetZoom, 0.1), 20);

		// 当前缩放值
		const currentZoom = this.canvas.getZoom();

		// 如果变化太小，直接应用缩放
		if (Math.abs(targetZoom - currentZoom) < 0.01) {
			this._applyZoom(point, targetZoom);
			return;
		}

		// 停止任何进行中的缩放动画
		if (this._zoomAnimation) {
			// 不是直接 kill，而是获取当前进度值作为新的起点
			const currentProgress = this._zoomAnimation.progress();
			const currentZoomValue = this._zoomAnimation.targets()[0].value;
			this._zoomAnimation.kill();
			this._zoomAnimation = null;

			// 从当前过渡中的值开始新动画，而不是从最初的值
			const zoomObj = { value: currentZoomValue };
			const currentVpt = [...this.canvas.viewportTransform];

			// 计算过渡动画持续时间 - 根据当前值到目标值的距离比例
			const progressRatio =
				Math.abs(targetZoom - currentZoomValue) / Math.abs(targetZoom - currentZoom);
			const duration = options.duration || 0.3 * progressRatio;

			// 计算缩放后目标位置需要的修正，保持缩放点不变
			const animOptions = {
				value: targetZoom,
				duration: duration,
				ease: options.ease || "power2.out",
				onUpdate: () => {
					// 更新缩放值显示
					this.currentZoom.value = Math.round(zoomObj.value * 100);

					// 计算过渡中的变换矩阵
					const zoom = zoomObj.value;
					const scale = zoom / currentZoomValue;
					const currentScaleFactor = scale;

					// 应用变换
					const vpt = this.canvas.viewportTransform;
					vpt[0] = currentVpt[0] * scale;
					vpt[3] = currentVpt[3] * scale;

					// 应用平移修正以保持缩放点
					const adjustX = (1 - currentScaleFactor) * point.x;
					const adjustY = (1 - currentScaleFactor) * point.y;
					vpt[4] = currentVpt[4] * scale + adjustX;
					vpt[5] = currentVpt[5] * scale + adjustY;
					this.canvas.setViewportTransform(vpt);
					this.canvas.renderAll();
				},
				onComplete: () => {
					this._zoomAnimation = null;

					// 确保最终状态准确
					this._applyZoom(point, targetZoom, true);
				},
			};

			// 启动 GSAP 动画
			this._zoomAnimation = gsap.to(zoomObj, animOptions);
			return;
		}

		// 如果没有正在进行的动画，创建新的缩放动画
		const zoomObj = { value: currentZoom };
		const currentVpt = [...this.canvas.viewportTransform];

		// 计算缩放后目标位置需要的修正，保持缩放点不变
		const scaleFactor = targetZoom / currentZoom;
		const invertedScaleFactor = 1 / scaleFactor;

		// 这个数学公式确保缩放点在屏幕上的位置保持不变
		const dx = point.x - point.x * invertedScaleFactor;
		const dy = point.y - point.y * invertedScaleFactor;

		// 创建动画配置
		const animOptions = {
			value: targetZoom,
			duration: options.duration || 0.3,
			ease: options.ease || (this._isMac ? "expo.out" : "power2.out"), // Mac使用更平滑的缓动
			onUpdate: () => {
				// 更新缩放值显示
				this.currentZoom.value = Math.round(zoomObj.value * 100);

				// 计算过渡中的变换矩阵
				const zoom = zoomObj.value;
				const scale = zoom / currentZoom;
				const currentScaleFactor = scale;

				// 应用变换
				const vpt = this.canvas.viewportTransform;
				vpt[0] = currentVpt[0] * scale;
				vpt[3] = currentVpt[3] * scale;

				// 应用平移修正以保持缩放点
				const adjustX = (1 - currentScaleFactor) * point.x;
				const adjustY = (1 - currentScaleFactor) * point.y;
				vpt[4] = currentVpt[4] * scale + adjustX;
				vpt[5] = currentVpt[5] * scale + adjustY;
				this.canvas.setViewportTransform(vpt);
				this.canvas.renderAll();
			},
			onComplete: () => {
				this._zoomAnimation = null;

				// 确保最终状态准确
				this._applyZoom(point, targetZoom, true);
			},
		};

		// 启动 GSAP 动画
		this._zoomAnimation = gsap.to(zoomObj, animOptions);
	}

	/**
	 * 应用缩放（内部使用）
	 * @private
	 */
	_applyZoom(point, zoom, skipUpdate = false) {
		if (!skipUpdate) {
			this.currentZoom.value = Math.round(zoom * 100);
		}
		this.canvas.zoomToPoint(point, zoom);
	}

	/**
	 * 使用 GSAP 实现平滑平移动画
	 * @param {Object} targetPosition 目标位置 {x, y}
	 * @param {Object} options 动画选项
	 */
	animatePan(targetPosition, options = {}) {
		if (!this.canvas) return;

		// 停止任何进行中的平移动画
		if (this._panAnimation) {
			this._panAnimation.kill();
		}

		const currentVpt = [...this.canvas.viewportTransform];
		const position = {
			x: -currentVpt[4],
			y: -currentVpt[5],
		};

		// 计算平移距离
		const dx = targetPosition.x - position.x;
		const dy = targetPosition.y - position.y;

		// 如果距离太小，直接应用平移
		if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {
			this._applyPan(targetPosition.x, targetPosition.y);
			return;
		}

		// 创建动画配置
		const animOptions = {
			x: targetPosition.x,
			y: targetPosition.y,
			duration: options.duration || 0.3,
			ease: options.ease || (this._isMac ? "circ.out" : "power2.out"), // Mac使用更柔和的缓动
			onUpdate: () => {
				this._applyPan(position.x, position.y);
			},
			onComplete: () => {
				this._panAnimation = null;
				// 确保最终位置准确
				this._applyPan(targetPosition.x, targetPosition.y);
			},
		};

		// 启动 GSAP 动画
		this._panAnimation = gsap.to(position, animOptions);
	}

	/**
	 * 应用平移（内部使用）
	 * @private
	 */
	_applyPan(x, y) {
		if (!this.canvas) return;

		const vpt = this.canvas.viewportTransform;
		vpt[4] = -x;
		vpt[5] = -y;
		this.canvas.setViewportTransform(vpt);
		this.canvas.renderAll();
	}

	/**
	 * 使用动画平移到指定元素
	 * @param {Object} elementId 元素ID
	 */
	panToElement(elementId) {
		if (!this.canvas) return;

		const obj = this.canvas.getObjects().find((obj) => obj.id === elementId);
		if (!obj) return;

		const zoom = this.canvas.getZoom();
		const center = obj.getCenterPoint();

		// 计算目标中心位置
		const targetX = center.x * zoom - this.canvas.width / 2;
		const targetY = center.y * zoom - this.canvas.height / 2;

		// 动画平移
		this.animatePan(
			{ x: targetX, y: targetY },
			{
				duration: 0.6,
				ease: this._isMac ? "back.out(0.3)" : "power3.out", // Mac使用轻微回弹效果
			}
		);
	}

	/**
	 * 重置缩放（带平滑动画）
	 * @param {Boolean} animated 是否使用动画
	 * @param {Boolean} adaptive 是否自适应缩放
	 */
	async resetZoom(animated = true, adaptive = false) {
		const { canvasViewWidth, canvasViewHeight, canvasWidth, canvasHeight } = this.canvasManager.getCanvasSize();
		const scaleX = canvasViewWidth / canvasWidth * 0.8
		const scaleY = canvasViewHeight / canvasHeight * 0.8
		const scale = Math.min(scaleX, scaleY, 1)
		const panX = canvasViewWidth / 2 - canvasWidth * scale / 2
		const panY = canvasViewHeight / 2 - canvasHeight * scale / 2

		return new Promise((resolve) => {
			if (animated) {
				// 停止任何进行中的动画
				if (this._zoomAnimation) {
					this._zoomAnimation.kill();
				}
				if (this._panAnimation) {
					this._panAnimation.kill();
				}

				const center = {
					x: this.canvas.width / 2,
					y: this.canvas.height / 2,
				};

				// 获取当前变换矩阵
				const currentVpt = [...this.canvas.viewportTransform];
				const currentZoom = this.canvas.getZoom();

				// 创建一个对象来动画整个视图变换
				const viewTransform = {
					zoom: currentZoom,
					panX: currentVpt[4],
					panY: currentVpt[5],
				};

				// 使用GSAP同时动画缩放和平移
				gsap.to(viewTransform, {
					zoom: scale,
					panX: panX,
					panY: panY,
					duration: 0.5,
					ease: this._isMac ? "back.out(0.2)" : "power3.out", // Mac使用轻微回弹效果
					onUpdate: () => {
						// 更新缩放显示值
						this.currentZoom.value = Math.round(viewTransform.zoom * 100);

						// 应用新的变换
						const vpt = this.canvas.viewportTransform;
						vpt[0] = viewTransform.zoom;
						vpt[3] = viewTransform.zoom;
						vpt[4] = viewTransform.panX;
						vpt[5] = viewTransform.panY;
						this.canvas.setViewportTransform(vpt);
						this.canvas.renderAll();
					},
					onComplete: () => {
						// 确保最终状态准确
						this.canvas.setViewportTransform([scale, 0, 0, scale, panX, panY]);
						this.currentZoom.value = scale * 100;
						this._zoomAnimation = null;
						this._panAnimation = null;
						resolve();
					},
				});
			} else {
				this.canvas.setViewportTransform([scale, 0, 0, scale, panX, panY]);
				this.currentZoom.value = scale * 100;
				resolve();
			}
		});
	}

	/**
	 * 处理鼠标滚轮缩放
	 * @param {Object} opt 事件对象
	 */
	handleMouseWheel(opt) {
		const now = Date.now();
		let delta = opt.e.deltaY;

		// 记录事件用于计算速度和惯性
		this._wheelEvents.push({
			delta: delta,
			point: { x: opt.e.offsetX, y: opt.e.offsetY },
			time: now,
			hasPanAnimation: this._wasPanning,
			hasZoomAnimation: this._wasZooming,
		});

		// 保留最近的事件记录
		if (this._wheelEvents.length > 10) {
			this._wheelEvents.shift();
		}

		// 检查是否是第一个事件或者距离上次处理已经过了足够时间
		const isFirstEvent = !this._wheelAccumulationTimeout;
		const timeSinceLastProcess = now - (this._lastWheelProcessTime || 0);

		if (isFirstEvent || timeSinceLastProcess > this._wheelAccumulationTime) {
			// 立即处理第一个事件或长时间没有处理的事件，确保响应性
			this._processAccumulatedWheel(opt);
			this._lastWheelProcessTime = now;

			// 清理之前的累积
			this._accumulatedWheelDelta = 0;

			// 如果有pending的timeout，清除它
			if (this._wheelAccumulationTimeout) {
				clearTimeout(this._wheelAccumulationTimeout);
				this._wheelAccumulationTimeout = null;
			}
		} else {
			// 累积后续事件
			this._accumulatedWheelDelta += delta;

			// 如果正在累积中，清除之前的定时器
			if (this._wheelAccumulationTimeout) {
				clearTimeout(this._wheelAccumulationTimeout);
			}

			// 设置新的定时器，处理累积的事件
			this._wheelAccumulationTimeout = setTimeout(() => {
				this._processAccumulatedWheel(opt);
				this._lastWheelProcessTime = Date.now();

				// 清理
				this._accumulatedWheelDelta = 0;
				this._wheelAccumulationTimeout = null;
			}, this._wheelThrottleTime);
		}

		opt.e.preventDefault();
		opt.e.stopPropagation();
	}

	/**
	 * 处理累积的滚轮事件并应用缩放
	 * @private
	 * @param {Object} lastOpt 最后一个滚轮事件
	 */
	_processAccumulatedWheel(lastOpt) {
		if (!this._wheelEvents.length) return;

		const now = Date.now();

		// Mac设备的轻量防抖检查 - 进一步减少冷却时间，确保响应性
		if (this._isMac && now - this._lastMacAnimationTime < this._macAnimationCooldown) {
			// 如果距离上次动画时间太短，只延迟很短时间，不阻塞太久
			if (this._wheelAccumulationTimeout) {
				clearTimeout(this._wheelAccumulationTimeout);
			}
			this._wheelAccumulationTimeout = setTimeout(
				() => {
					this._processAccumulatedWheel(lastOpt);
				},
				Math.min(this._macAnimationCooldown, 3)
			); // 最多延迟3ms
			return;
		}

		const currentZoom = this.canvas.getZoom();

		// 分析滚轮事件模式，计算平均增量、速度和加速度
		let sumDelta = 0;
		let count = 0;
		let earliestTime = now;
		let latestTime = 0;
		let point = {
			x: lastOpt.e.offsetX,
			y: lastOpt.e.offsetY,
		};

		// 判断是否在事件收集期间有平移或缩放动画
		let hadPanAnimation = false;
		let hadZoomAnimation = false;

		// 计算平均增量和速度
		this._wheelEvents.forEach((event) => {
			sumDelta += event.delta;
			count++;
			earliestTime = Math.min(earliestTime, event.time);
			latestTime = Math.max(latestTime, event.time);

			// 使用最后记录的点作为缩放中心
			if (event.time > latestTime) {
				point = event.point;
			}

			// 检查是否有动画状态
			if (event.hasPanAnimation) hadPanAnimation = true;
			if (event.hasZoomAnimation) hadZoomAnimation = true;
		});

		// 计算平均增量
		const avgDelta = sumDelta / count;

		// 计算滚动速度 - 基于事件频率和时间跨度
		const timeSpan = latestTime - earliestTime + 1; // 避免除以零
		const eventsPerSecond = (count / timeSpan) * 1000;

		// 速度系数: 速度越快，缩放越敏感
		let speedFactor = Math.min(3, Math.max(0.5, eventsPerSecond / 10));

		// 计算缩放因子，应用速度系数
		// 针对Mac设备优化：Mac触控板的deltaY值通常较小，需要适度增加敏感度
		let zoomFactorBase = 0.999;
		if (this._isMac) {
			// Mac设备的触控板需要适度的敏感度，避免过度反应
			zoomFactorBase = 0.995; // 适度降低基数，增加缩放敏感度

			// 检测是否为触控板滚动（小幅度、高频次的特征）
			const avgAbsDelta = Math.abs(avgDelta);
			if (avgAbsDelta < 50 && count > 2) {
				// 触控板滚动，适度增加敏感度
				speedFactor *= 1.6; // 适度增加敏感度倍数
				zoomFactorBase = 0.993; // 进一步调整基数
			}
		}

		const zoomFactor = zoomFactorBase ** (avgDelta * speedFactor);
		let targetZoom = currentZoom * zoomFactor;

		// 限制缩放范围
		targetZoom = Math.min(Math.max(targetZoom, 0.1), 20);

		// 根据滚动速度和缩放幅度计算动画持续时间
		// 速度快时缩短动画时间，缩放幅度大时延长动画时间
		const zoomRatio = Math.abs(targetZoom - currentZoom) / currentZoom;

		let duration;
		if (this._isMac) {
			// Mac设备使用平衡的动画时间控制
			if (speedFactor > 2) {
				// 快速操作：快速但平滑
				duration = Math.min(0.18, Math.max(0.08, (zoomRatio * 0.3) / Math.sqrt(speedFactor)));
			} else if (speedFactor > 1.2) {
				// 中等速度：标准响应
				duration = Math.min(0.25, Math.max(0.1, (zoomRatio * 0.4) / Math.sqrt(speedFactor)));
			} else {
				// 慢速精确操作：确保平滑
				duration = Math.min(0.3, Math.max(0.12, (zoomRatio * 0.5) / Math.sqrt(speedFactor)));
			}
		} else {
			duration = Math.min(0.5, Math.max(0.15, (zoomRatio * 0.8) / Math.sqrt(speedFactor)));
		}

		// 根据滚动速度选择不同的缓动效果
		let easeType;
		if (this._isMac) {
			// Mac设备使用更简单、性能更好的缓动函数
			// 避免复杂的指数和回弹效果，减少计算量
			if (speedFactor > 2) {
				// 快速滚动：使用简单的缓出效果
				easeType = "power2.out";
			} else if (speedFactor > 1.2) {
				// 中等速度：使用平滑的缓出
				easeType = "power1.out";
			} else {
				// 慢速精确操作：使用线性过渡
				easeType = "power1.out";
			}
		} else {
			// 非Mac设备保持原有的缓动
			easeType = speedFactor > 1.5 ? "power1.out" : "power2.out";
		}

		// 根据是否有其他动画正在进行，选择合适的动画方法
		if (hadPanAnimation || this._wasPanning) {
			// 如果有平移动画，使用组合动画以保持平滑过渡
			this.animateCombinedTransform(point, targetZoom, {
				duration: duration,
				ease: easeType,
			});
		} else {
			// 如果没有其他动画，使用标准缩放动画
			this.animateZoom(point, targetZoom, {
				duration: duration,
				ease: easeType,
			});
		}

		// 更新Mac设备的最后动画时间
		if (this._isMac) {
			this._lastMacAnimationTime = now;
		}

		// 清理事件记录
		this._wheelEvents = [];
	}

	/**
	 * 计算并应用拖动结束后的惯性效果
	 * @param {Array} positions 拖动过程中记录的位置数组
	 * @param {Boolean} isTouchDevice 是否是触摸设备
	 */
	applyInertiaEffect(positions, isTouchDevice) {
		if (!positions || positions.length <= 1) return;

		const lastPos = positions[positions.length - 1];
		const firstPos = positions[0];
		const deltaTime = lastPos.time - firstPos.time;

		if (deltaTime <= 0) return;

		// 计算速度向量 (像素/毫秒)
		const velocityX = (lastPos.x - firstPos.x) / deltaTime;
		const velocityY = (lastPos.y - firstPos.y) / deltaTime;
		const speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);

		// 仅当速度足够大时应用惯性效果
		if (speed > 0.2) {
			// 计算惯性距离，基于速度和衰减因子
			const decayFactor = 300; // 调整此值以改变惯性效果的强度
			const inertiaDistanceX = velocityX * decayFactor;
			const inertiaDistanceY = velocityY * decayFactor;

			// 计算目标位置
			const vpt = this.canvas.viewportTransform;
			const currentPos = {
				x: -vpt[4],
				y: -vpt[5],
			};

			const targetPos = {
				x: currentPos.x - inertiaDistanceX,
				y: currentPos.y - inertiaDistanceY,
			};

			// 应用惯性动画，速度越大，动画时间越长
			const animationDuration = Math.min(1.2, Math.max(0.6, speed * 2));

			// 应用惯性动画
			this.animatePan(targetPos, {
				duration: animationDuration, // 动态计算持续时间
				ease: this._isMac ? "quart.out" : "power3.out", // Mac使用更自然的减速效果
			});
		}
	}

	/**
	 * 平滑过渡停止所有动画
	 * 用于在需要中断当前动画时提供更自然的过渡，而不是硬性中断
	 * @param {Object} options 过渡选项
	 */
	smoothStopAnimations(options = {}) {
		const duration = options.duration || 0.15; // 默认短暂过渡时间

		// 处理缩放动画
		if (this._zoomAnimation) {
			const zoomObj = this._zoomAnimation.targets()[0];
			const currentZoom = this.canvas.getZoom();

			// 创建短暂的过渡动画到当前值
			gsap.to(zoomObj, {
				value: currentZoom,
				duration: duration,
				ease: this._isMac ? "circ.out" : "power1.out", // Mac使用更平滑的缓动
				onUpdate: () => {
					this.currentZoom.value = Math.round(zoomObj.value * 100);
					this.canvas.renderAll();
				},
				onComplete: () => {
					if (this._zoomAnimation) {
						this._zoomAnimation.kill();
						this._zoomAnimation = null;
					}
				},
			});
		}

		// 处理平移动画
		if (this._panAnimation) {
			const panObj = this._panAnimation.targets()[0];
			const vpt = this.canvas.viewportTransform;
			const currentPos = { x: -vpt[4], y: -vpt[5] };

			// 创建短暂的过渡动画到当前位置
			gsap.to(panObj, {
				x: currentPos.x,
				y: currentPos.y,
				duration: duration,
				ease: this._isMac ? "circ.out" : "power1.out", // Mac使用更平滑的缓动
				onUpdate: () => {
					this._applyPan(panObj.x, panObj.y);
				},
				onComplete: () => {
					if (this._panAnimation) {
						this._panAnimation.kill();
						this._panAnimation = null;
					}
				},
			});
		}
	}

	/**
	 * 设置画布交互动画
	 * 为对象交互添加流畅的动画效果
	 */
	setupInteractionAnimations() {
		if (!this.canvas) return;

		// 启用对象旋转的流畅动画
		this._setupRotationAnimation();
	}

	/**
	 * 设置旋转动画
	 * @private
	 */
	_setupRotationAnimation() {
		if (!fabric) return;

		// 保存原始旋转方法
		const originalRotate = fabric.Object.prototype.rotate;
		const isMac = this._isMac; // 保存Mac检测结果

		// 覆盖旋转方法以添加动画
		fabric.Object.prototype.rotate = function (angle) {
			const currentAngle = this.angle || 0;

			if (Math.abs(angle - currentAngle) > 0.1) {
				gsap.to(this, {
					angle: angle,
					duration: 0.3,
					ease: isMac ? "back.out(0.3)" : "power2.out", // Mac使用轻微回弹
					onUpdate: () => {
						this.canvas && this.canvas.renderAll();
					},
				});
				return this;
			}

			// 如果角度差异很小，使用原始方法
			return originalRotate.call(this, angle);
		};
	}

	/**
	 * 处理滚轮缩放，同时兼容正在进行的平移动画
	 * @param {Object} point 缩放中心点
	 * @param {Number} targetZoom 目标缩放值
	 * @param {Object} options 动画选项
	 */
	animateCombinedTransform(point, targetZoom, options = {}) {
		if (!this.canvas) return;

		// 限制缩放范围
		targetZoom = Math.min(Math.max(targetZoom, 0.1), 20);

		// 当前状态
		const currentZoom = this.canvas.getZoom();
		const currentVpt = [...this.canvas.viewportTransform];
		const currentPos = { x: -currentVpt[4], y: -currentVpt[5] };

		// 如果有正在进行的动画，先停止它们
		if (this._combinedAnimation) {
			this._combinedAnimation.kill();
			this._combinedAnimation = null;
		}

		if (this._zoomAnimation) {
			this._zoomAnimation.kill();
			this._zoomAnimation = null;
		}

		if (this._panAnimation) {
			this._panAnimation.kill();
			this._panAnimation = null;
		}

		// 创建一个统一的变换对象来动画
		const transform = {
			zoom: currentZoom,
			panX: currentVpt[4],
			panY: currentVpt[5],
			progress: 0, // 用于动画进度跟踪
		};

		// 获取平移目标位置（如果有的话）
		let panTarget = { x: currentPos.x, y: currentPos.y };
		if (this._wasPanning) {
			// 如果之前有平移动画，尝试获取平移的目标位置
			const vpt = this.canvas.viewportTransform;
			panTarget = {
				x: currentPos.x,
				y: currentPos.y,
			};
		}

		// 计算新的变换矩阵，同时考虑平移和缩放
		const scaleFactor = targetZoom / currentZoom;

		// 创建动画
		this._combinedAnimation = gsap.to(transform, {
			zoom: targetZoom,
			progress: 1,
			duration: options.duration || 0.3,
			ease: options.ease || (this._isMac ? "expo.out" : "power2.out"), // Mac使用更平滑的缓动
			onUpdate: () => {
				// 计算当前动画阶段的混合变换
				const currentScaleFactor = transform.zoom / currentZoom;

				// 应用缩放
				const vpt = this.canvas.viewportTransform;
				vpt[0] = currentVpt[0] * (transform.zoom / currentZoom);
				vpt[3] = currentVpt[3] * (transform.zoom / currentZoom);

				// 平滑混合平移和缩放调整
				const adjustX = (1 - currentScaleFactor) * point.x;
				const adjustY = (1 - currentScaleFactor) * point.y;

				// 如果存在平移目标，进行插值
				if (this._wasPanning) {
					const t = transform.progress;
					const interpolatedX = currentPos.x * (1 - t) + panTarget.x * t;
					const interpolatedY = currentPos.y * (1 - t) + panTarget.y * t;

					// 结合缩放和平移的调整
					vpt[4] = -interpolatedX * currentScaleFactor + adjustX;
					vpt[5] = -interpolatedY * currentScaleFactor + adjustY;
				} else {
					// 只有缩放，保持中心点
					vpt[4] = currentVpt[4] * currentScaleFactor + adjustX;
					vpt[5] = currentVpt[5] * currentScaleFactor + adjustY;
				}

				// 更新缩放值显示
				this.currentZoom.value = Math.round(transform.zoom * 100);
				this.canvas.setViewportTransform(vpt);
				this.canvas.renderAll();
			},
			onComplete: () => {
				this._combinedAnimation = null;
				this._zoomAnimation = null;
				this._panAnimation = null;
				this._wasPanning = false;
				this._wasZooming = false;

				// 确保最终状态准确
				this._applyZoom(point, targetZoom, true);
			},
		});
	}

	/**
	 * 清理资源
	 */
	dispose() {
		if (this._zoomAnimation) {
			this._zoomAnimation.kill();
			this._zoomAnimation = null;
		}

		if (this._panAnimation) {
			this._panAnimation.kill();
			this._panAnimation = null;
		}

		this._wheelEvents = [];
		this.canvas = null;
		this.currentZoom = null;
	}
}
