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"
|
class="comparison-image original-image"
|
||||||
:style="{ clipPath: `inset(0 ${100 - splitPosition}% 0 0)` }"
|
:style="{ clipPath: `inset(0 ${100 - splitPosition}% 0 0)` }"
|
||||||
>
|
>
|
||||||
<img :src="uploadedImageUrl" alt="Original" />
|
<img
|
||||||
|
ref="originalImageRef"
|
||||||
|
:src="uploadedImageUrl"
|
||||||
|
alt="Original"
|
||||||
|
@load="adjustContainerSize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 去背景后的图片(显示右侧部分) -->
|
<!-- 去背景后的图片(显示右侧部分) -->
|
||||||
@ -80,7 +85,12 @@
|
|||||||
class="comparison-image result-image"
|
class="comparison-image result-image"
|
||||||
:style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }"
|
:style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }"
|
||||||
>
|
>
|
||||||
<img :src="resultImageUrl" alt="Result" />
|
<img
|
||||||
|
ref="resultImageRef"
|
||||||
|
:src="resultImageUrl"
|
||||||
|
alt="Result"
|
||||||
|
@load="adjustContainerSize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 拖动竖线 -->
|
<!-- 拖动竖线 -->
|
||||||
@ -160,7 +170,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, nextTick, watch, onMounted, onUnmounted } from 'vue'
|
||||||
import { useMessage } from 'naive-ui'
|
import { useMessage } from 'naive-ui'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { t } from '@/shared/i18n'
|
import { t } from '@/shared/i18n'
|
||||||
@ -204,8 +214,81 @@ const dragCounter = ref(0)
|
|||||||
const processing = ref(false)
|
const processing = ref(false)
|
||||||
const splitPosition = ref(0) // 分割线位置(百分比),0表示最左边,默认只显示结果图
|
const splitPosition = ref(0) // 分割线位置(百分比),0表示最左边,默认只显示结果图
|
||||||
const comparisonContainerRef = ref<HTMLElement | null>(null)
|
const comparisonContainerRef = ref<HTMLElement | null>(null)
|
||||||
|
const originalImageRef = ref<HTMLImageElement | null>(null)
|
||||||
|
const resultImageRef = ref<HTMLImageElement | null>(null)
|
||||||
const isDraggingSplitLine = ref(false)
|
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 = () => {
|
const triggerFileInput = () => {
|
||||||
if (fileInputRef.value) {
|
if (fileInputRef.value) {
|
||||||
@ -306,6 +389,11 @@ const resetUpload = () => {
|
|||||||
if (fileInputRef.value) {
|
if (fileInputRef.value) {
|
||||||
fileInputRef.value.value = ''
|
fileInputRef.value.value = ''
|
||||||
}
|
}
|
||||||
|
// 重置容器大小
|
||||||
|
if (comparisonContainerRef.value) {
|
||||||
|
comparisonContainerRef.value.style.width = ''
|
||||||
|
comparisonContainerRef.value.style.height = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择历史记录项
|
// 选择历史记录项
|
||||||
@ -920,17 +1008,19 @@ h1 {
|
|||||||
.comparison-view {
|
.comparison-view {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comparison-container {
|
.comparison-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
/* 固定尺寸,避免子元素高度计算错误 */
|
/* 容器大小由 JavaScript 动态设置,匹配图片实际显示尺寸 */
|
||||||
width: min(90vw, calc(100vh - 200px));
|
/* 同时设置 max-width 和 max-height 作为安全限制,确保不超过父元素 */
|
||||||
height: min(90vw, calc(100vh - 200px));
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -957,6 +1047,7 @@ h1 {
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
|
/* 图片限制在容器内,不超过父元素 */
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: auto;
|
width: auto;
|
||||||
@ -977,6 +1068,7 @@ h1 {
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
|
/* 图片限制在容器内,不超过父元素 */
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: auto;
|
width: auto;
|
||||||
@ -996,6 +1088,7 @@ h1 {
|
|||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
|
/* 图片限制在容器内,不超过父元素 */
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user