ensure comparison container size matches image display size and respects parent
This commit is contained in:
parent
ccf84eb031
commit
92208b0513
@ -72,7 +72,12 @@
|
||||
class="comparison-image original-image"
|
||||
:style="{ clipPath: `inset(0 ${100 - splitPosition}% 0 0)` }"
|
||||
>
|
||||
<img :src="uploadedImageUrl" alt="Original" />
|
||||
<img
|
||||
ref="originalImageRef"
|
||||
:src="uploadedImageUrl"
|
||||
alt="Original"
|
||||
@load="adjustContainerSize"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 去背景后的图片(显示右侧部分) -->
|
||||
@ -80,7 +85,12 @@
|
||||
class="comparison-image result-image"
|
||||
:style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }"
|
||||
>
|
||||
<img :src="resultImageUrl" alt="Result" />
|
||||
<img
|
||||
ref="resultImageRef"
|
||||
:src="resultImageUrl"
|
||||
alt="Result"
|
||||
@load="adjustContainerSize"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 拖动竖线 -->
|
||||
@ -160,7 +170,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, nextTick, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import axios from 'axios'
|
||||
import { t } from '@/shared/i18n'
|
||||
@ -204,8 +214,81 @@ const dragCounter = ref(0)
|
||||
const processing = ref(false)
|
||||
const splitPosition = ref(0) // 分割线位置(百分比),0表示最左边,默认只显示结果图
|
||||
const comparisonContainerRef = ref<HTMLElement | null>(null)
|
||||
const originalImageRef = ref<HTMLImageElement | null>(null)
|
||||
const resultImageRef = ref<HTMLImageElement | null>(null)
|
||||
const isDraggingSplitLine = ref(false)
|
||||
|
||||
// 调整容器大小以匹配图片实际显示尺寸
|
||||
const adjustContainerSize = () => {
|
||||
nextTick(() => {
|
||||
if (!comparisonContainerRef.value) return
|
||||
|
||||
// 使用原图或结果图的尺寸(它们应该相同)
|
||||
const img = originalImageRef.value || resultImageRef.value
|
||||
if (!img) return
|
||||
|
||||
// 获取父元素 preview-section 的实际可用尺寸
|
||||
const container = comparisonContainerRef.value
|
||||
const previewSection = container.closest('.preview-section') as HTMLElement
|
||||
if (!previewSection) return
|
||||
|
||||
const previewRect = previewSection.getBoundingClientRect()
|
||||
// 考虑 padding (12px * 2 = 24px)
|
||||
const maxAvailableWidth = Math.max(0, previewRect.width - 24)
|
||||
const maxAvailableHeight = Math.max(0, previewRect.height - 24)
|
||||
|
||||
if (maxAvailableWidth <= 0 || maxAvailableHeight <= 0) return
|
||||
|
||||
// 等待图片加载完成
|
||||
if (!img.complete) {
|
||||
// 如果图片还没加载完成,等待加载完成后再计算
|
||||
// 使用 once: true 确保只触发一次
|
||||
img.addEventListener('load', adjustContainerSize, { once: true })
|
||||
return
|
||||
}
|
||||
|
||||
const naturalWidth = img.naturalWidth
|
||||
const naturalHeight = img.naturalHeight
|
||||
|
||||
if (naturalWidth === 0 || naturalHeight === 0) return
|
||||
|
||||
// 根据图片的自然尺寸和父元素的可用空间,计算合适的显示尺寸
|
||||
// 保持图片宽高比,同时确保不超过父元素的可用空间
|
||||
const scaleX = maxAvailableWidth / naturalWidth
|
||||
const scaleY = maxAvailableHeight / naturalHeight
|
||||
const scale = Math.min(scaleX, scaleY, 1) // 取较小的缩放比例,且不放大(不超过1)
|
||||
|
||||
const displayWidth = naturalWidth * scale
|
||||
const displayHeight = naturalHeight * scale
|
||||
|
||||
// 确保最终尺寸不超过父元素的可用空间(双重保险)
|
||||
const finalWidth = Math.min(displayWidth, maxAvailableWidth)
|
||||
const finalHeight = Math.min(displayHeight, maxAvailableHeight)
|
||||
|
||||
// 设置容器大小为计算出的尺寸
|
||||
comparisonContainerRef.value.style.width = `${finalWidth}px`
|
||||
comparisonContainerRef.value.style.height = `${finalHeight}px`
|
||||
})
|
||||
}
|
||||
|
||||
// 监听图片加载完成
|
||||
watch([uploadedImageUrl, resultImageUrl], () => {
|
||||
adjustContainerSize()
|
||||
}, { immediate: true })
|
||||
|
||||
// 监听窗口大小变化
|
||||
const handleResize = () => {
|
||||
adjustContainerSize()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
// 触发文件选择
|
||||
const triggerFileInput = () => {
|
||||
if (fileInputRef.value) {
|
||||
@ -306,6 +389,11 @@ const resetUpload = () => {
|
||||
if (fileInputRef.value) {
|
||||
fileInputRef.value.value = ''
|
||||
}
|
||||
// 重置容器大小
|
||||
if (comparisonContainerRef.value) {
|
||||
comparisonContainerRef.value.style.width = ''
|
||||
comparisonContainerRef.value.style.height = ''
|
||||
}
|
||||
}
|
||||
|
||||
// 选择历史记录项
|
||||
@ -920,17 +1008,19 @@ h1 {
|
||||
.comparison-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.comparison-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
/* 固定尺寸,避免子元素高度计算错误 */
|
||||
width: min(90vw, calc(100vh - 200px));
|
||||
height: min(90vw, calc(100vh - 200px));
|
||||
/* 容器大小由 JavaScript 动态设置,匹配图片实际显示尺寸 */
|
||||
/* 同时设置 max-width 和 max-height 作为安全限制,确保不超过父元素 */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
@ -957,6 +1047,7 @@ h1 {
|
||||
|
||||
img {
|
||||
display: block;
|
||||
/* 图片限制在容器内,不超过父元素 */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
@ -977,6 +1068,7 @@ h1 {
|
||||
|
||||
img {
|
||||
display: block;
|
||||
/* 图片限制在容器内,不超过父元素 */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
@ -996,6 +1088,7 @@ h1 {
|
||||
|
||||
img {
|
||||
display: block;
|
||||
/* 图片限制在容器内,不超过父元素 */
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user