|
@@ -86,6 +86,9 @@
|
|
|
<el-button v-if="cropMode" size="mini" @click="cancelRectCrop">取消</el-button>
|
|
<el-button v-if="cropMode" size="mini" @click="cancelRectCrop">取消</el-button>
|
|
|
<el-button v-if="cropMode" size="mini" type="primary" @click="applyRectCrop">应用</el-button>
|
|
<el-button v-if="cropMode" size="mini" type="primary" @click="applyRectCrop">应用</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div v-if="background.imageMode === imageModeList[3].value">
|
|
|
|
|
+ <el-checkbox v-model="lockScale">锁定比例</el-checkbox>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="setup-item">
|
|
<div class="setup-item">
|
|
@@ -191,6 +194,7 @@ export default {
|
|
|
startX: 0,
|
|
startX: 0,
|
|
|
startY: 0,
|
|
startY: 0,
|
|
|
type: '',
|
|
type: '',
|
|
|
|
|
+ aspectRatio: 1, // 锁定比例时的宽高比
|
|
|
},
|
|
},
|
|
|
cropMode: false,
|
|
cropMode: false,
|
|
|
crop: {
|
|
crop: {
|
|
@@ -232,6 +236,7 @@ export default {
|
|
|
{ label: '平铺', value: 'fill' },
|
|
{ label: '平铺', value: 'fill' },
|
|
|
{ label: '自定义', value: 'auto' },
|
|
{ label: '自定义', value: 'auto' },
|
|
|
],
|
|
],
|
|
|
|
|
+ lockScale: false, // 是否锁定比例(仅自定义模式)
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
@@ -341,11 +346,13 @@ export default {
|
|
|
dragStart(event, cursor, type) {
|
|
dragStart(event, cursor, type) {
|
|
|
if (this.cropMode) return;
|
|
if (this.cropMode) return;
|
|
|
const { clientX, clientY } = event;
|
|
const { clientX, clientY } = event;
|
|
|
|
|
+ const aspectRatio = this.imgData.height ? this.imgData.width / this.imgData.height : 1;
|
|
|
this.drag = {
|
|
this.drag = {
|
|
|
dragging: true,
|
|
dragging: true,
|
|
|
startX: clientX,
|
|
startX: clientX,
|
|
|
startY: clientY,
|
|
startY: clientY,
|
|
|
type,
|
|
type,
|
|
|
|
|
+ aspectRatio,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
document.querySelector('.el-dialog__wrapper').style.cursor = cursor;
|
|
document.querySelector('.el-dialog__wrapper').style.cursor = cursor;
|
|
@@ -377,6 +384,7 @@ export default {
|
|
|
if (!this.drag.dragging) return;
|
|
if (!this.drag.dragging) return;
|
|
|
const { clientX, clientY } = event;
|
|
const { clientX, clientY } = event;
|
|
|
const { startX, startY, type } = this.drag;
|
|
const { startX, startY, type } = this.drag;
|
|
|
|
|
+ const prevImgData = { ...this.imgData };
|
|
|
|
|
|
|
|
const widthDiff = clientX - startX;
|
|
const widthDiff = clientX - startX;
|
|
|
const heightDiff = clientY - startY;
|
|
const heightDiff = clientY - startY;
|
|
@@ -422,11 +430,57 @@ export default {
|
|
|
this.imgData.left = Math.min(this.maxWidth - this.imgData.width, Math.max(0, this.imgData.left + widthDiff));
|
|
this.imgData.left = Math.min(this.maxWidth - this.imgData.width, Math.max(0, this.imgData.left + widthDiff));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (this.shouldLockScale(type)) {
|
|
|
|
|
+ this.applyLockedScaleResize(type, prevImgData);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
this.drag.startX = clientX;
|
|
this.drag.startX = clientX;
|
|
|
this.drag.startY = clientY;
|
|
this.drag.startY = clientY;
|
|
|
this.syncImageDisplayRect();
|
|
this.syncImageDisplayRect();
|
|
|
},
|
|
},
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 判断在当前拖动类型下是否应该锁定比例调整尺寸
|
|
|
|
|
+ * @param {string} type 拖动类型
|
|
|
|
|
+ * @returns {boolean} 是否应该锁定比例调整尺寸
|
|
|
|
|
+ */
|
|
|
|
|
+ shouldLockScale(type) {
|
|
|
|
|
+ return this.background.imageMode === 'auto' && this.lockScale && type !== 'move';
|
|
|
|
|
+ },
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 在锁定比例的情况下调整尺寸,确保宽高比保持不变,并且不会超出边界
|
|
|
|
|
+ * @param {string} type 拖动类型
|
|
|
|
|
+ * @param {object} prevImgData 拖动前的图片数据,用于计算边界限制
|
|
|
|
|
+ */
|
|
|
|
|
+ applyLockedScaleResize(type, prevImgData) {
|
|
|
|
|
+ const ratio = this.drag.aspectRatio || 1;
|
|
|
|
|
+ if (!ratio) return;
|
|
|
|
|
+
|
|
|
|
|
+ let width = type === 'top' || type === 'bottom' ? this.imgData.height * ratio : this.imgData.width;
|
|
|
|
|
+ let height = width / ratio;
|
|
|
|
|
+
|
|
|
|
|
+ // 根据拖动方向计算允许的最大宽高,确保在锁定比例时不会超出边界
|
|
|
|
|
+ const widthLimit = type.includes('left')
|
|
|
|
|
+ ? prevImgData.left + prevImgData.width
|
|
|
|
|
+ : this.maxWidth - prevImgData.left;
|
|
|
|
|
+ const heightLimit = type.includes('top')
|
|
|
|
|
+ ? prevImgData.top + prevImgData.height
|
|
|
|
|
+ : this.maxHeight - prevImgData.top;
|
|
|
|
|
+ const maxWidthByHeight = heightLimit * ratio;
|
|
|
|
|
+ const safeWidth = Math.max(1, Math.min(width, widthLimit, maxWidthByHeight));
|
|
|
|
|
+
|
|
|
|
|
+ width = safeWidth;
|
|
|
|
|
+ height = width / ratio;
|
|
|
|
|
+
|
|
|
|
|
+ // 根据拖动方向计算新的 left 和 top,确保在锁定比例时图片位置调整合理
|
|
|
|
|
+ const left = type.includes('left') ? prevImgData.left + prevImgData.width - width : prevImgData.left;
|
|
|
|
|
+ const top = type.includes('top') ? prevImgData.top + prevImgData.height - height : prevImgData.top;
|
|
|
|
|
+
|
|
|
|
|
+ this.imgData.width = width;
|
|
|
|
|
+ this.imgData.height = height;
|
|
|
|
|
+ this.imgData.left = Math.min(this.maxWidth - width, Math.max(0, left));
|
|
|
|
|
+ this.imgData.top = Math.min(this.maxHeight - height, Math.max(0, top));
|
|
|
|
|
+ },
|
|
|
|
|
+ /**
|
|
|
* 鼠标抬起
|
|
* 鼠标抬起
|
|
|
*/
|
|
*/
|
|
|
mouseUp() {
|
|
mouseUp() {
|