|
|
@@ -109,7 +109,14 @@
|
|
|
privateImages: [],
|
|
|
droppedImages: [],
|
|
|
selectedImage: null,
|
|
|
- baseCanvasData: null // 缓存基础内容的 Canvas 数据
|
|
|
+ baseCanvasData: null, // 缓存基础内容的 Canvas 数据
|
|
|
+ _isMoving: false, // 是否正在移动图片
|
|
|
+ _currentMoveImageId: null, // 当前正在移动的图片ID
|
|
|
+ _moveHandler: null, // 移动事件处理函数引用
|
|
|
+ _mouseUpHandler: null, // 鼠标释放事件处理函数引用
|
|
|
+ _dragOverHandler: null, // dragover事件处理函数引用
|
|
|
+ _dropHandler: null, // drop事件处理函数引用
|
|
|
+ _contextMenuHandler: null // contextmenu事件处理函数引用
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
|
@@ -139,7 +146,7 @@
|
|
|
mounted() {
|
|
|
// 组件挂载后自动渲染一次
|
|
|
this.$nextTick(() => {
|
|
|
- // this.renderToCanvas();
|
|
|
+ this.renderToCanvas();
|
|
|
});
|
|
|
|
|
|
// 保存组件实例引用,用于事件处理器
|
|
|
@@ -163,6 +170,21 @@
|
|
|
};
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
+ // 清理移动事件监听器
|
|
|
+ this._cancelMove();
|
|
|
+ // 清理 Canvas 事件监听器
|
|
|
+ const canvas = document.getElementById('outputCanvas');
|
|
|
+ if (canvas) {
|
|
|
+ if (this._dragOverHandler) {
|
|
|
+ canvas.removeEventListener('dragover', this._dragOverHandler);
|
|
|
+ }
|
|
|
+ if (this._dropHandler) {
|
|
|
+ canvas.removeEventListener('drop', this._dropHandler);
|
|
|
+ }
|
|
|
+ if (this._contextMenuHandler) {
|
|
|
+ canvas.removeEventListener('contextmenu', this._contextMenuHandler);
|
|
|
+ }
|
|
|
+ }
|
|
|
// 清理引用
|
|
|
if (window._aaComponentInstance === this) {
|
|
|
window._aaComponentInstance = null;
|
|
|
@@ -237,12 +259,24 @@
|
|
|
);
|
|
|
console.log('Canvas 位置:', canvas.getBoundingClientRect());
|
|
|
|
|
|
- canvas.addEventListener('dragover', (e) => {
|
|
|
+ // 先移除旧的事件监听器,防止重复绑定
|
|
|
+ if (this._dragOverHandler) {
|
|
|
+ canvas.removeEventListener('dragover', this._dragOverHandler);
|
|
|
+ }
|
|
|
+ if (this._dropHandler) {
|
|
|
+ canvas.removeEventListener('drop', this._dropHandler);
|
|
|
+ }
|
|
|
+ if (this._contextMenuHandler) {
|
|
|
+ canvas.removeEventListener('contextmenu', this._contextMenuHandler);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建事件处理函数并保存引用
|
|
|
+ this._dragOverHandler = (e) => {
|
|
|
e.preventDefault();
|
|
|
e.dataTransfer.dropEffect = 'copy';
|
|
|
- });
|
|
|
+ };
|
|
|
|
|
|
- canvas.addEventListener('drop', (e) => {
|
|
|
+ this._dropHandler = (e) => {
|
|
|
e.preventDefault();
|
|
|
console.log('触发 drop 事件');
|
|
|
const imageData = e.dataTransfer.getData('imageData');
|
|
|
@@ -252,13 +286,17 @@
|
|
|
console.log('解析后的数据:', data);
|
|
|
this.addImageToCanvas(data, e.offsetX, e.offsetY);
|
|
|
}
|
|
|
- });
|
|
|
+ };
|
|
|
|
|
|
- // 添加右键点击事件监听
|
|
|
- canvas.addEventListener('contextmenu', (e) => {
|
|
|
+ this._contextMenuHandler = (e) => {
|
|
|
e.preventDefault();
|
|
|
this.handleCanvasRightClick(e);
|
|
|
- });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加新的事件监听器
|
|
|
+ canvas.addEventListener('dragover', this._dragOverHandler);
|
|
|
+ canvas.addEventListener('drop', this._dropHandler);
|
|
|
+ canvas.addEventListener('contextmenu', this._contextMenuHandler);
|
|
|
},
|
|
|
|
|
|
// 处理拖拽开始
|
|
|
@@ -603,6 +641,15 @@
|
|
|
const image = this.droppedImages[imageIndex];
|
|
|
console.log('找到图片:', image);
|
|
|
|
|
|
+ // 如果已经在移动中,先移除旧的事件监听器
|
|
|
+ if (this._isMoving) {
|
|
|
+ this._cancelMove();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置移动状态标志
|
|
|
+ this._isMoving = true;
|
|
|
+ this._currentMoveImageId = imageId;
|
|
|
+
|
|
|
// 创建一个临时指示器
|
|
|
const indicator = document.createElement('div');
|
|
|
indicator.id = `move_indicator_${imageId}`;
|
|
|
@@ -625,9 +672,9 @@
|
|
|
message: '📍 移动鼠标调整位置,释放鼠标完成移动',
|
|
|
type: 'info'
|
|
|
});
|
|
|
- // this.showMessage('📍 移动鼠标调整位置,释放鼠标完成移动', 'info');
|
|
|
|
|
|
- const moveHandler = (e) => {
|
|
|
+ // 保存事件处理函数引用,用于后续移除
|
|
|
+ this._moveHandler = (e) => {
|
|
|
console.log('moveHandler 被调用,鼠标位置:', e.clientX, e.clientY);
|
|
|
const rect = canvas.getBoundingClientRect();
|
|
|
const scaleX = canvas.width / rect.width;
|
|
|
@@ -652,7 +699,7 @@
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const mouseUpHandler = (e) => {
|
|
|
+ this._mouseUpHandler = (e) => {
|
|
|
console.log(
|
|
|
'mouseUpHandler 被调用,位置:',
|
|
|
e.clientX,
|
|
|
@@ -667,9 +714,14 @@
|
|
|
// 确保只处理一次
|
|
|
if (indicator.parentNode) {
|
|
|
console.log('指示器仍在DOM中,移除事件监听器');
|
|
|
- document.removeEventListener('mousemove', moveHandler);
|
|
|
- document.removeEventListener('mouseup', mouseUpHandler);
|
|
|
+ document.removeEventListener('mousemove', this._moveHandler);
|
|
|
+ document.removeEventListener('mouseup', this._mouseUpHandler);
|
|
|
indicator.remove();
|
|
|
+ // 重置移动状态
|
|
|
+ this._isMoving = false;
|
|
|
+ this._currentMoveImageId = null;
|
|
|
+ this._moveHandler = null;
|
|
|
+ this._mouseUpHandler = null;
|
|
|
// 使用组件实例引用
|
|
|
const component = window._aaComponentInstance || this;
|
|
|
if (component) {
|
|
|
@@ -678,7 +730,6 @@
|
|
|
message: '图片已移动',
|
|
|
type: 'success'
|
|
|
});
|
|
|
- // component.showMessage('✅ 图片已移动', 'success');
|
|
|
}
|
|
|
} else {
|
|
|
console.log('指示器已不在DOM中');
|
|
|
@@ -687,10 +738,10 @@
|
|
|
|
|
|
// 确保事件只绑定一次
|
|
|
console.log('绑定事件监听器');
|
|
|
- document.removeEventListener('mousemove', moveHandler);
|
|
|
- document.removeEventListener('mouseup', mouseUpHandler);
|
|
|
- document.addEventListener('mousemove', moveHandler);
|
|
|
- document.addEventListener('mouseup', mouseUpHandler);
|
|
|
+ document.removeEventListener('mousemove', this._moveHandler);
|
|
|
+ document.removeEventListener('mouseup', this._mouseUpHandler);
|
|
|
+ document.addEventListener('mousemove', this._moveHandler);
|
|
|
+ document.addEventListener('mouseup', this._mouseUpHandler);
|
|
|
},
|
|
|
|
|
|
// 删除图片
|
|
|
@@ -705,6 +756,11 @@
|
|
|
// 删除控制菜单
|
|
|
this.safeRemoveElement(`menu_${imageId}`);
|
|
|
|
|
|
+ // 如果正在移动这张图片,取消移动状态
|
|
|
+ if (this._currentMoveImageId === imageId) {
|
|
|
+ this._cancelMove();
|
|
|
+ }
|
|
|
+
|
|
|
this.redrawCanvas();
|
|
|
this.$message({
|
|
|
showClose: true,
|
|
|
@@ -713,6 +769,28 @@
|
|
|
});
|
|
|
},
|
|
|
|
|
|
+ // 取消移动操作
|
|
|
+ _cancelMove() {
|
|
|
+ if (this._moveHandler) {
|
|
|
+ document.removeEventListener('mousemove', this._moveHandler);
|
|
|
+ }
|
|
|
+ if (this._mouseUpHandler) {
|
|
|
+ document.removeEventListener('mouseup', this._mouseUpHandler);
|
|
|
+ }
|
|
|
+ // 移除指示器
|
|
|
+ if (this._currentMoveImageId) {
|
|
|
+ const indicator = document.getElementById(`move_indicator_${this._currentMoveImageId}`);
|
|
|
+ if (indicator && indicator.parentNode) {
|
|
|
+ indicator.remove();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 重置状态
|
|
|
+ this._isMoving = false;
|
|
|
+ this._currentMoveImageId = null;
|
|
|
+ this._moveHandler = null;
|
|
|
+ this._mouseUpHandler = null;
|
|
|
+ },
|
|
|
+
|
|
|
// 渲染Canvas核心函数
|
|
|
async renderToCanvas() {
|
|
|
const targetElement = document.getElementById('captureTarget');
|
|
|
@@ -802,15 +880,23 @@
|
|
|
|
|
|
try {
|
|
|
const imgData = outputCanvas.toDataURL('image/png');
|
|
|
- const canvasWidth = outputCanvas.width;
|
|
|
- const canvasHeight = outputCanvas.height;
|
|
|
+ // 使用 Canvas 的 CSS 尺寸(显示尺寸),而不是内部像素尺寸
|
|
|
+ const canvasWidth = parseFloat(outputCanvas.style.width) || outputCanvas.width;
|
|
|
+ const canvasHeight = parseFloat(outputCanvas.style.height) || outputCanvas.height;
|
|
|
|
|
|
// 创建 PDF 实例,横向或纵向根据 Canvas 尺寸决定
|
|
|
const orientation = canvasWidth > canvasHeight ? 'l' : 'p';
|
|
|
- const pdf = new jsPDF(orientation, 'px', [canvasWidth, canvasHeight]);
|
|
|
+ // 使用 'mm' 单位,并根据 96 DPI 转换为毫米
|
|
|
+ // 96 DPI 下:1px = 25.4 / 96 mm ≈ 0.2646 mm
|
|
|
+ const DPI = 96;
|
|
|
+ const pxToMm = 25.4 / DPI;
|
|
|
+ const pdfWidth = canvasWidth * pxToMm;
|
|
|
+ const pdfHeight = canvasHeight * pxToMm;
|
|
|
+
|
|
|
+ const pdf = new jsPDF(orientation, 'mm', [pdfWidth, pdfHeight]);
|
|
|
|
|
|
// 将 Canvas 图片添加到 PDF
|
|
|
- pdf.addImage(imgData, 'PNG', 0, 0, canvasWidth, canvasHeight);
|
|
|
+ pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
|
|
|
|
|
|
// 获取 PDF 文件流并触发事件
|
|
|
const pdfBlob = pdf.output('blob');
|
|
|
@@ -824,7 +910,7 @@
|
|
|
droppedImages: this.droppedImages
|
|
|
});
|
|
|
|
|
|
- // // 保存 PDF
|
|
|
+ // 保存 PDF
|
|
|
// const timestamp = new Date()
|
|
|
// .toISOString()
|
|
|
// .slice(0, 19)
|