152 lines
3.3 KiB
Vue
152 lines
3.3 KiB
Vue
<script setup>
|
||
import { ref, onMounted, watch } from 'vue'
|
||
|
||
const props = defineProps({
|
||
src: {
|
||
type: String,
|
||
required: true
|
||
},
|
||
alt: {
|
||
type: String,
|
||
default: '图片'
|
||
},
|
||
maxHeight: {
|
||
type: Number,
|
||
default: 500
|
||
}
|
||
})
|
||
|
||
const isExpanded = ref(false)
|
||
const showExpand = ref(false)
|
||
// 标记图片是否已加载,防止@load重复触发
|
||
const isImageLoaded = ref(false)
|
||
|
||
// 核心:VuePress SSR适配,仅在浏览器端执行图片高度判断
|
||
const checkImageHeight = (img) => {
|
||
if (typeof window === 'undefined') return // 服务端直接返回
|
||
const naturalHeight = img.naturalHeight || img.offsetHeight
|
||
console.log(props.alt, naturalHeight, '图片实际高度')
|
||
showExpand.value = naturalHeight > props.maxHeight
|
||
isImageLoaded.value = true
|
||
}
|
||
|
||
// 图片加载完成触发
|
||
const handleImageLoad = (event) => {
|
||
if (isImageLoaded.value) return
|
||
checkImageHeight(event.target)
|
||
}
|
||
|
||
// 浏览器端挂载后,主动检查图片(解决@load未触发的边界情况)
|
||
onMounted(() => {
|
||
if (typeof window === 'undefined') return
|
||
const img = document.querySelector(`.responsive-image[src="${props.src}"]`)
|
||
if (img && img.complete) { // 图片已缓存完成,主动触发高度判断
|
||
checkImageHeight(img)
|
||
}
|
||
})
|
||
|
||
// 展开/收起切换
|
||
const toggleExpand = () => {
|
||
isExpanded.value = !isExpanded.value
|
||
}
|
||
|
||
// 监听展开状态,同步更新提示显示(兜底)
|
||
watch(isExpanded, (val) => {
|
||
if (!showExpand.value) return
|
||
showExpand.value = !val
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div class="image-container">
|
||
<div
|
||
class="image-wrapper"
|
||
:class="{ 'expanded': isExpanded }"
|
||
:style="{ maxHeight: !isExpanded ? `${maxHeight}px` : 'none' }"
|
||
>
|
||
<img
|
||
:src="src"
|
||
:alt="alt"
|
||
@load="handleImageLoad"
|
||
class="responsive-image"
|
||
loading="lazy"
|
||
>
|
||
</div>
|
||
|
||
<!-- 展开提示:仅图片高度超限时显示 -->
|
||
<div v-if="showExpand" class="expand-hint" @click="toggleExpand" v-show="!isExpanded">
|
||
<span>点击查看完整图片</span>
|
||
</div>
|
||
|
||
<!-- 收起提示:仅展开后显示 -->
|
||
<div class="collapse-hint" @click="toggleExpand" v-show="isExpanded">
|
||
<span>收起图片</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.image-container {
|
||
position: relative;
|
||
width: 100%;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.image-wrapper {
|
||
width: 100%;
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease-in-out;
|
||
position: relative;
|
||
}
|
||
|
||
/* 渐变遮罩:仅未展开时显示,提示有更多内容 */
|
||
.image-wrapper:not(.expanded)::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 80px;
|
||
background: linear-gradient(transparent, rgba(255,255,255,0.95));
|
||
pointer-events: none;
|
||
}
|
||
|
||
.image-wrapper.expanded::after {
|
||
display: none;
|
||
}
|
||
|
||
.responsive-image {
|
||
width: 100%;
|
||
height: auto;
|
||
display: block;
|
||
}
|
||
|
||
.expand-hint, .collapse-hint {
|
||
text-align: center;
|
||
padding: 8px;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
margin-top: 8px;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.expand-hint {
|
||
background: rgba(64, 158, 255, 0.1);
|
||
color: #409eff;
|
||
}
|
||
|
||
.expand-hint:hover {
|
||
background: rgba(64, 158, 255, 0.2);
|
||
}
|
||
|
||
.collapse-hint {
|
||
background: rgba(103, 194, 58, 0.1);
|
||
color: #67c23a;
|
||
}
|
||
|
||
.collapse-hint:hover {
|
||
background: rgba(103, 194, 58, 0.2);
|
||
}
|
||
</style>
|