|
|
@@ -209,12 +209,58 @@ export class CanvasPhotoEditor {
|
|
|
return
|
|
|
}
|
|
|
if (e.target !== this.canvas) return
|
|
|
- // ==========================================
|
|
|
- // 🔥 页面拖拽排序:按下时记录
|
|
|
- // ==========================================
|
|
|
const rect = this.canvas.getBoundingClientRect()
|
|
|
const mouseX = (e.clientX - rect.left - this.drawOffsetX) / this.scale
|
|
|
const mouseY = (e.clientY - rect.top - this.drawOffsetY) / this.scale
|
|
|
+ //判断是否点击在标引上
|
|
|
+
|
|
|
+ let isLine = this.indexingLineList.findIndex(item => {
|
|
|
+ let points = item.points || [];
|
|
|
+
|
|
|
+ // 点数量不足2个,直接不匹配
|
|
|
+ if (points.length < 2) return false;
|
|
|
+
|
|
|
+ // 遍历所有相邻两点,判断鼠标是否在任意一段上
|
|
|
+ for (let i = 0; i < points.length - 1; i++) {
|
|
|
+ const p1 = points[i];
|
|
|
+ const p2 = points[i + 1];
|
|
|
+
|
|
|
+ // 只要有一段满足,就返回 true
|
|
|
+ if (this.isPointOnLine(mouseX, mouseY, p1.x, p1.y, p2.x, p2.y)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 所有线段都不满足
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ this.isLineDel = false
|
|
|
+ if (isLine != -1) {//选中已生成标引
|
|
|
+ // 阻止事件冒泡和默认行为,避免鼠标事件持续触发
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ this.isLineDel = true
|
|
|
+ return ElMessageBox.confirm("确定删除当前选中标引?", "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ }).then(async () => {
|
|
|
+ this.indexingLineList.splice(isLine, 1);
|
|
|
+ this.indexingLineList = [...this.indexingLineList];
|
|
|
+ this.drawAllPages()
|
|
|
+ ElMessage({
|
|
|
+ type: "success",
|
|
|
+ message: "删除成功",
|
|
|
+ });
|
|
|
+ this.saveHistory()
|
|
|
+ this.isLineDel = false
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.isLineDel = false
|
|
|
+ }
|
|
|
+ // ==========================================
|
|
|
+ // 🔥 页面拖拽排序:按下时记录
|
|
|
+ // ==========================================
|
|
|
if (this.dragPageData.drawing) {
|
|
|
this.dragPageData.end = { x: mouseX, y: mouseY }
|
|
|
this.drawAllPages()
|
|
|
@@ -411,50 +457,6 @@ export class CanvasPhotoEditor {
|
|
|
const mouseY = (e.clientY - rect.top - this.drawOffsetY) / this.scale
|
|
|
const PhotoIndex = this.getPhotoPositionInPage(e)
|
|
|
console.log('indexingLineList', this.indexingLineList)
|
|
|
- let isLine = this.indexingLineList.findIndex(item => {
|
|
|
- let points = item.points || [];
|
|
|
-
|
|
|
- // 点数量不足2个,直接不匹配
|
|
|
- if (points.length < 2) return false;
|
|
|
-
|
|
|
- // 遍历所有相邻两点,判断鼠标是否在任意一段上
|
|
|
- for (let i = 0; i < points.length - 1; i++) {
|
|
|
- const p1 = points[i];
|
|
|
- const p2 = points[i + 1];
|
|
|
-
|
|
|
- // 只要有一段满足,就返回 true
|
|
|
- if (this.isPointOnLine(mouseX, mouseY, p1.x, p1.y, p2.x, p2.y)) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 所有线段都不满足
|
|
|
- return false;
|
|
|
- });
|
|
|
- this.isLineDel = false
|
|
|
- if (isLine != -1) {//选中已生成标引
|
|
|
- // 阻止事件冒泡和默认行为,避免鼠标事件持续触发
|
|
|
- e.stopPropagation();
|
|
|
- e.preventDefault();
|
|
|
- this.isLineDel = true
|
|
|
- return ElMessageBox.confirm("确定删除当前选中标引?", "提示", {
|
|
|
- confirmButtonText: "确定",
|
|
|
- cancelButtonText: "取消",
|
|
|
- type: "warning",
|
|
|
- }).then(async () => {
|
|
|
- this.indexingLineList.splice(isLine, 1);
|
|
|
- this.indexingLineList = [...this.indexingLineList];
|
|
|
- this.drawAllPages()
|
|
|
- ElMessage({
|
|
|
- type: "success",
|
|
|
- message: "删除成功",
|
|
|
- });
|
|
|
- this.saveHistory()
|
|
|
- this.isLineDel = false
|
|
|
- });
|
|
|
- } else {
|
|
|
- this.isLineDel = false
|
|
|
- }
|
|
|
console.log('indexing', this.indexing, PhotoIndex, isLine)
|
|
|
if (PhotoIndex.itemIndex == -1) {
|
|
|
ElMessage.error("请选中对应的图片进行标引操作!");
|
|
|
@@ -739,7 +741,7 @@ export class CanvasPhotoEditor {
|
|
|
* @param {number} r 允许的误差范围(线宽容错)
|
|
|
* @return {boolean}
|
|
|
*/
|
|
|
- isPointOnLine(px, py, x1, y1, x2, y2, r = 10) {
|
|
|
+ isPointOnLine(px, py, x1, y1, x2, y2, r = 20) {
|
|
|
// 1. 计算点到线段的垂直距离
|
|
|
const A = px - x1;
|
|
|
const B = py - y1;
|
|
|
@@ -988,7 +990,7 @@ export class CanvasPhotoEditor {
|
|
|
ctx.clip();
|
|
|
//添加说明文字
|
|
|
// 3. 绘制文字(基于图片实际区域居中,且在裁剪区内)
|
|
|
- const text = photo && photo.name || '说明文字';
|
|
|
+ const text = photo && photo.id? photo.name : '说明文字';
|
|
|
// 文字居中坐标:图片实际显示区域的正中心
|
|
|
|
|
|
// 文字样式(适配缩放)
|
|
|
@@ -1311,10 +1313,48 @@ resizePageAndReflow(pages, pageIndex, itemValue) {
|
|
|
const wrapperWidth = this.scrollWrapper.clientWidth
|
|
|
const wrapperHeight = this.scrollWrapper.clientHeight
|
|
|
|
|
|
- // 计算居中坐标偏移
|
|
|
- this.drawOffsetX = (wrapperWidth - totalWidth) / 2
|
|
|
- this.drawOffsetY = (wrapperHeight - totalHeight) / 2
|
|
|
+ // 1. 计算所有页面的总占用尺寸(横向排列:总宽度 = 单页宽 * 页数 + 页边距;高度 = 单页高)
|
|
|
+ const singlePageWidth = this.pageWidth + 2 * this.pageMargin; // 单页宽(含边距)
|
|
|
+ const singlePageHeight = this.pageHeight + 2 * this.pageMargin; // 单页高(含边距)
|
|
|
+ const totalPagesWidth = singlePageWidth * this.pages.length; // 所有页面总宽度
|
|
|
+ const totalPagesHeight = singlePageHeight; // 纵向仅单页高度(横向排列)
|
|
|
+
|
|
|
+ // 2. 获取画布可视区域尺寸
|
|
|
+ const canvasViewWidth = this.canvas.width || this.scrollWrapper.clientWidth;
|
|
|
+ const canvasViewHeight = this.canvas.height || this.scrollWrapper.clientHeight;
|
|
|
+
|
|
|
+ // 3. 计算自适应缩放比例(保证所有页面完整显示)
|
|
|
+ const scaleByWidth = canvasViewWidth / totalPagesWidth; // 按宽度适配的缩放比
|
|
|
+ const scaleByHeight = canvasViewHeight / totalPagesHeight; // 按高度适配的缩放比
|
|
|
+ const fitScale = Math.min(scaleByWidth, scaleByHeight, this._scaleMax); // 取最小值且不超过最大缩放
|
|
|
+
|
|
|
+ // 4. 重置缩放比例
|
|
|
+ this._scale = Math.max(fitScale, this._scaleMin); // 不低于最小缩放
|
|
|
+
|
|
|
+ // 5. 计算居中偏移量(让所有页面在画布中居中)
|
|
|
+ // 总内容的实际显示宽度/高度(缩放后)
|
|
|
+ const renderedTotalWidth = totalPagesWidth * this._scale;
|
|
|
+ const renderedTotalHeight = totalPagesHeight * this._scale;
|
|
|
+
|
|
|
+ // 居中偏移:(画布尺寸 - 内容尺寸) / 2
|
|
|
+ this.drawOffsetX = (canvasViewWidth - renderedTotalWidth) / 2;
|
|
|
+ this.drawOffsetY = (canvasViewHeight - renderedTotalHeight) / 2;
|
|
|
+
|
|
|
+ // 6. 重置临时状态(拖拽/标引/页面移动)
|
|
|
+ this.isDragging = false;
|
|
|
+ this.dragPageData = {
|
|
|
+ drawing: false,
|
|
|
+ index: -1,
|
|
|
+ start: null,
|
|
|
+ end: null,
|
|
|
+ movedIndex: -1,
|
|
|
+ };
|
|
|
+ this.tempArrow = { start: null, end: null, drawing: false };
|
|
|
+ this.indexingNum = 0; // 重置标引状态
|
|
|
|
|
|
+ // 7. 重置选中状态(可选,根据需求)
|
|
|
+ this.selectedPageIndex = -1;
|
|
|
+ this.selectedPageItem = { index: -1, pageIndex: -1 };
|
|
|
this.drawAllPages() // 重置位置时重绘一次
|
|
|
}
|
|
|
|
|
|
@@ -1442,7 +1482,7 @@ resizePageAndReflow(pages, pageIndex, itemValue) {
|
|
|
});
|
|
|
this.currentIndex++;
|
|
|
console.log("saveHistory", this.history, this.currentIndex);
|
|
|
- if (this.history.length > 5) {
|
|
|
+ if (this.history.length > 20) {
|
|
|
this.history.shift(); // 删除最早的一条
|
|
|
this.currentIndex--;
|
|
|
}
|
|
|
@@ -1582,7 +1622,7 @@ resizePageAndReflow(pages, pageIndex, itemValue) {
|
|
|
|
|
|
// 文字
|
|
|
ctx.fillStyle = "#000";
|
|
|
- const text = photo.name || "说明文字";
|
|
|
+ const text = photo.id?photo.name:"说明文字";
|
|
|
this.drawCenteredTextWithEllipsis(
|
|
|
ctx, text,
|
|
|
coord.x + coord.width / 2,
|
|
|
@@ -1752,7 +1792,7 @@ resizePageAndReflow(pages, pageIndex, itemValue) {
|
|
|
|
|
|
// 文字
|
|
|
ctx.fillStyle = "#000";
|
|
|
- const text = photo.name || "说明文字";
|
|
|
+ const text = photo.id?photo.name:"说明文字";
|
|
|
this.drawCenteredTextWithEllipsis(
|
|
|
ctx, text,
|
|
|
coord.x + coord.width / 2,
|