|
|
@@ -26,7 +26,7 @@ export class CanvasPhotoEditor {
|
|
|
this.show = options.show || false // true 纯显示,不编辑
|
|
|
|
|
|
// 响应式数据
|
|
|
- this._layoutMode = 'single'//全局的页面布局
|
|
|
+ this._layoutMode = 'double'//全局的页面布局
|
|
|
this._pages = [{
|
|
|
list: [null],
|
|
|
layoutMode: this._layoutMode,//排版模式
|
|
|
@@ -62,6 +62,14 @@ export class CanvasPhotoEditor {
|
|
|
end: null, // { x, y }
|
|
|
drawing: false // 是否正在绘制
|
|
|
};
|
|
|
+ //修改pages页码
|
|
|
+ this.dragPageData = {
|
|
|
+ drawing: false,//是否正在绘制页面移动
|
|
|
+ index: -1,
|
|
|
+ start: null, // { x, y }
|
|
|
+ end: null, // { x, y }
|
|
|
+ movedIndex: -1,//移动到的索引位置
|
|
|
+ }
|
|
|
//标引状态
|
|
|
this.indexing = false//是否开启
|
|
|
this.indexingNum = 0 //0 未点击 1 已生成开始点位 2 结束点位已生成
|
|
|
@@ -187,17 +195,19 @@ export class CanvasPhotoEditor {
|
|
|
}
|
|
|
|
|
|
// --- 核心:拖拽仅改坐标,不重绘 ---
|
|
|
- handleMouseDown(e) {
|
|
|
+ async handleMouseDown(e) {
|
|
|
if (e.target !== this.canvas) return
|
|
|
// ==========================================
|
|
|
// 🔥 页面拖拽排序:按下时记录
|
|
|
// ==========================================
|
|
|
- // if (this.selectedPageIndex !== -1 && !this.indexing) {
|
|
|
- // this.isPageDragging = true
|
|
|
- // this.dragPageStartY = e.clientY
|
|
|
- // this.dragPageMoved = false
|
|
|
- // 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
|
|
|
+ if (this.dragPageData.drawing) {
|
|
|
+ this.dragPageData.end = { x: mouseX, y: mouseY }
|
|
|
+ this.drawAllPages()
|
|
|
+ return
|
|
|
+ }
|
|
|
// 记录拖拽起始状态
|
|
|
if (this.indexing) {
|
|
|
if (this.indexingNum == 0) return this.starIindexing(e)
|
|
|
@@ -206,20 +216,6 @@ export class CanvasPhotoEditor {
|
|
|
}
|
|
|
const pageIndex = this.getPageIndexByClick(e)
|
|
|
const oldPageIndex = this.selectedPageIndex; // 保存旧选中页
|
|
|
- // if(pageIndex == this.selectedPageIndex && pageIndex != -1){
|
|
|
- // 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
|
|
|
- // this.tempArrow.start = { x: mouseX, y: mouseY }
|
|
|
- // this.tempArrow.drawing = true;
|
|
|
- // return
|
|
|
- // }
|
|
|
- this.isDragging = true
|
|
|
- this.dragStartX = e.clientX
|
|
|
- this.dragStartY = e.clientY
|
|
|
- this.lastDrawOffsetX = this.drawOffsetX
|
|
|
- this.lastDrawOffsetY = this.drawOffsetY
|
|
|
- this.canvas.style.cursor = 'grabbing'
|
|
|
if (!this.show && pageIndex != undefined && pageIndex != -1 && (pageIndex !== this.selectedPageIndex || this._selectedPageItem.pageIndex != -1)) {
|
|
|
// 1. 清除旧页面的边框
|
|
|
// this.clearOldBorder(oldPageIndex);
|
|
|
@@ -232,22 +228,51 @@ export class CanvasPhotoEditor {
|
|
|
pageIndex: -1,
|
|
|
}
|
|
|
}
|
|
|
+ console.log('pageIndex', this.pages, this.selectedPageItem, pageIndex)
|
|
|
+ if(oldPageIndex == pageIndex == this.selectedPageIndex == this.selectedPageItem.pageIndex && pageIndex != -1 && this.selectedPageItem.index == -1){
|
|
|
+ if(this.indexingLineList.length){
|
|
|
+ await this.checkIndexing('修改页面排序将会清除所有标引是否继续?')
|
|
|
+ this.drawAllPages()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.dragPageData.start = { x: mouseX, y: mouseY }
|
|
|
+ this.dragPageData.drawing = true;
|
|
|
+ this.dragPageData.index = pageIndex;
|
|
|
+ this.dragPageData.movedIndex = pageIndex;
|
|
|
+ this.canvas.style.cursor = 'copy'
|
|
|
+ this.drawAllPages()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.isDragging = true
|
|
|
+ this.dragStartX = e.clientX
|
|
|
+ this.dragStartY = e.clientY
|
|
|
+ this.lastDrawOffsetX = this.drawOffsetX
|
|
|
+ this.lastDrawOffsetY = this.drawOffsetY
|
|
|
+ this.canvas.style.cursor = 'grabbing'
|
|
|
console.log('pageIndex', this.pages, this._selectedPageItem, this.selectedPageItem, pageIndex)
|
|
|
this.drawAllPages()
|
|
|
}
|
|
|
|
|
|
handleMouseMove(e) {
|
|
|
const drawing = this.tempArrow?.drawing
|
|
|
+ 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
|
|
|
if (this.indexing && drawing) {
|
|
|
- const { x, y, } = this.tempArrow?.start
|
|
|
- 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
|
|
|
this.tempArrow.end = {x: mouseX, y: mouseY }
|
|
|
this.drawAllPages()
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+ if(this.dragPageData.drawing){
|
|
|
+ let endIndex = Math.round(mouseX / this.pageWidth)
|
|
|
+ this.dragPageData.end = { x: mouseX, y: mouseY }
|
|
|
+ let newEndIndex = endIndex<0?0:endIndex>this.pages.length-1?this.pages.length-1:endIndex
|
|
|
+ if(newEndIndex != this.dragPageData.movedIndex){
|
|
|
+ this.dragPageData.movedIndex = newEndIndex
|
|
|
+ this.drawAllPages()
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
if (!this.isDragging) return
|
|
|
// 仅更新坐标偏移,不触发重绘(核心优化)
|
|
|
const deltaX = e.clientX - this.dragStartX
|
|
|
@@ -299,18 +324,33 @@ export class CanvasPhotoEditor {
|
|
|
console.log('handleMouseUp', this.isDragging)
|
|
|
this.isDragging = false
|
|
|
this.canvas.style.cursor = 'grab'
|
|
|
+ if(this.dragPageData.drawing){//鼠标释放左键时,移动页面到指定位置)
|
|
|
+ // 末尾必须加分号!!!
|
|
|
+ let newPagelist = this.moveItem(this.pages, this.dragPageData.index, this.dragPageData.movedIndex)
|
|
|
+ this.pages = newPagelist;
|
|
|
+ this.drawAllPages()
|
|
|
+ }
|
|
|
+ this.dragPageData.drawing = false
|
|
|
+ this.dragPageData.movedIndex = 0
|
|
|
// 松开鼠标后仅重绘一次,确认最终位置
|
|
|
// this.drawDragPreview()
|
|
|
// 选中页面(仅点击时重绘一次)
|
|
|
console.log('pageIndex', this.indexing, this.indexingNum)
|
|
|
}
|
|
|
-
|
|
|
+ moveItem(arr, fromIndex, toIndex) {
|
|
|
+ const newArr = [...arr]
|
|
|
+ const item = newArr.splice(fromIndex, 1)[0]
|
|
|
+ newArr.splice(toIndex, 0, item)
|
|
|
+ return newArr
|
|
|
+ }
|
|
|
handleMouseLeave() {
|
|
|
console.log('handleMouseLeave', this.isDragging)
|
|
|
this.isDragging = false
|
|
|
+ this.dragPageData.drawing = false
|
|
|
+ this.dragPageData.movedIndex = 0
|
|
|
this.canvas.style.cursor = 'grab'
|
|
|
// 离开画布后重绘一次
|
|
|
- // this.drawDragPreview()
|
|
|
+ this.drawDragPreview()
|
|
|
}
|
|
|
|
|
|
// --- 缩放逻辑(缩放必须重绘,无法通过坐标偏移实现)---
|
|
|
@@ -813,7 +853,7 @@ export class CanvasPhotoEditor {
|
|
|
ctx.strokeStyle = pageIndex === this.selectedPageIndex
|
|
|
? this.selectedPageColor
|
|
|
: '#dddddd'
|
|
|
- ctx.lineWidth = pageIndex === this.selectedPageIndex ? 4 / this.scale : 2 / this.scale
|
|
|
+ ctx.lineWidth = pageIndex === this.selectedPageIndex ? 4 * this.scale : 2 * this.scale
|
|
|
ctx.strokeRect(pageX, 0, this.pageWidth, this.pageHeight)
|
|
|
}
|
|
|
|
|
|
@@ -861,10 +901,13 @@ export class CanvasPhotoEditor {
|
|
|
})
|
|
|
})
|
|
|
ctx.restore()
|
|
|
- console.log('this.tempArrow', this.tempArrow)
|
|
|
+ console.log('this.tempArrow', this.selectedPageItem)
|
|
|
if(this.tempArrow.drawing && this.indexing){//绘制实时鼠标标引
|
|
|
this.drawInterimLine([this.tempArrow.start,this.tempArrow.end])
|
|
|
}
|
|
|
+ if(this.dragPageData.drawing && this.dragPageData.movedIndex){//绘制实时鼠标标引
|
|
|
+ this.drawPlusIcon(this.dragPageData.movedIndex)
|
|
|
+ }
|
|
|
this.drawGuideLineAll(true)//绘制标引
|
|
|
}
|
|
|
|
|
|
@@ -1643,10 +1686,10 @@ exportToPDF(paperType, name, fileType = 'pdf'){
|
|
|
this.exportPagesAsImages(paperType, name);
|
|
|
}
|
|
|
}
|
|
|
-async checkIndexing(){
|
|
|
+async checkIndexing(mes = '此操作将会清除所有标引是否继续?'){
|
|
|
let length = this.indexingLineList.length;
|
|
|
// try {
|
|
|
- if ( length && await ElMessageBox.confirm('此操作将会清除所有标引是否继续?', '提示') ) {
|
|
|
+ if ( length && await ElMessageBox.confirm(mes, '提示') ) {
|
|
|
this.saveHistory();
|
|
|
this.indexingLineList = [];
|
|
|
return true;
|
|
|
@@ -1656,4 +1699,52 @@ async checkIndexing(){
|
|
|
// }
|
|
|
return false
|
|
|
}
|
|
|
+//绘制移动page的目的地提示
|
|
|
+drawPlusIcon = (pageIndex) => {
|
|
|
+ const ctx = this.ctx;
|
|
|
+ const color = '#1677ff';
|
|
|
+ const lineWidth = 2;
|
|
|
+ const size = 60 * this.scale;
|
|
|
+ const r = 24 * this.scale
|
|
|
+ // 1. 保存当前上下文状态(避免污染)
|
|
|
+ ctx.save();
|
|
|
+
|
|
|
+ // 2. 应用和全量绘制一致的偏移/缩放(保证坐标对齐)
|
|
|
+ ctx.translate(this.drawOffsetX, this.drawOffsetY);
|
|
|
+ ctx.scale(this.scale, this.scale);
|
|
|
+ const pageX = (pageIndex * (this.pageWidth + this.pageMargin)) - this.pageMargin / 2;
|
|
|
+ const arcY = 0-(size/2)
|
|
|
+ // 蓝色圆形
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(pageX, arcY, r, 0, Math.PI * 2);
|
|
|
+ ctx.fillStyle = color;
|
|
|
+ ctx.fill();
|
|
|
+
|
|
|
+ // 白色加号
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(pageX - size / 3, arcY);
|
|
|
+ ctx.lineTo(pageX + size / 3, arcY);
|
|
|
+ ctx.moveTo(pageX, arcY - size / 3);
|
|
|
+ ctx.lineTo(pageX, arcY + size / 3);
|
|
|
+ ctx.strokeStyle = '#fff';
|
|
|
+ ctx.lineWidth = lineWidth;
|
|
|
+ ctx.lineCap = 'round';
|
|
|
+ ctx.fill();
|
|
|
+ ctx.stroke();
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.moveTo(pageX, 0);
|
|
|
+ ctx.lineTo(pageX, this.pageHeight);
|
|
|
+ ctx.strokeStyle = color;
|
|
|
+ ctx.lineWidth = this.pageMargin;
|
|
|
+ ctx.fill();
|
|
|
+
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.restore();
|
|
|
+ };
|
|
|
+ insertItemToArray(arr, item, toIndex) {
|
|
|
+ const newArr = [...arr]
|
|
|
+ newArr.splice(toIndex, 0, item)
|
|
|
+ return newArr
|
|
|
+ }
|
|
|
}
|