102 lines
1.9 KiB
Vue
102 lines
1.9 KiB
Vue
|
|
<script setup>
|
|||
|
|
import { ref, onMounted, computed } from 'vue'
|
|||
|
|
|
|||
|
|
const props = defineProps({
|
|||
|
|
src: {
|
|||
|
|
type: String,
|
|||
|
|
required: true
|
|||
|
|
},
|
|||
|
|
alt: {
|
|||
|
|
type: String,
|
|||
|
|
default: '长图'
|
|||
|
|
},
|
|||
|
|
sliceHeight: {
|
|||
|
|
type: Number,
|
|||
|
|
default: 600
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const imgLoaded = ref(false)
|
|||
|
|
const naturalWidth = ref(0)
|
|||
|
|
const naturalHeight = ref(0)
|
|||
|
|
const containerWidth = ref(0)
|
|||
|
|
|
|||
|
|
const handleLoad = (e) => {
|
|||
|
|
imgLoaded.value = true
|
|||
|
|
naturalWidth.value = e.target.naturalWidth
|
|||
|
|
naturalHeight.value = e.target.naturalHeight
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleContainerResize = (el) => {
|
|||
|
|
containerWidth.value = el.getBoundingClientRect().width
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const slices = computed(() => {
|
|||
|
|
if (!imgLoaded.value) return []
|
|||
|
|
const count = Math.ceil(naturalHeight.value / props.sliceHeight)
|
|||
|
|
const arr = []
|
|||
|
|
for (let i = 0; i < count; i++) {
|
|||
|
|
arr.push({
|
|||
|
|
top: i * props.sliceHeight,
|
|||
|
|
height: Math.min(props.sliceHeight, naturalHeight.value - i * props.sliceHeight)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
return arr
|
|||
|
|
})
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<div
|
|||
|
|
class="long-pic-img-split"
|
|||
|
|
@resize="handleContainerResize($event.target)"
|
|||
|
|
>
|
|||
|
|
<!-- 用于获取尺寸 -->
|
|||
|
|
<img
|
|||
|
|
:src="src"
|
|||
|
|
:alt="alt"
|
|||
|
|
@load="handleLoad"
|
|||
|
|
class="img-hidden"
|
|||
|
|
>
|
|||
|
|
|
|||
|
|
<!-- 正常分段显示,宽度100%,不会被放大 -->
|
|||
|
|
<img
|
|||
|
|
v-for="(item, idx) in slices"
|
|||
|
|
:key="idx"
|
|||
|
|
:src="src"
|
|||
|
|
:alt="`${alt}-${idx + 1}`"
|
|||
|
|
class="split-img"
|
|||
|
|
:style="{
|
|||
|
|
height: `${item.height}px`,
|
|||
|
|
objectPosition: `center ${-item.top}px`,
|
|||
|
|
}"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.long-pic-img-split {
|
|||
|
|
width: 100%;
|
|||
|
|
max-width: 100%;
|
|||
|
|
overflow: hidden;
|
|||
|
|
margin: 10px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.img-hidden {
|
|||
|
|
position: absolute;
|
|||
|
|
width: 100%;
|
|||
|
|
opacity: 0;
|
|||
|
|
pointer-events: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.split-img {
|
|||
|
|
display: block;
|
|||
|
|
width: 100% !important;
|
|||
|
|
max-width: 100% !important;
|
|||
|
|
object-fit: cover;
|
|||
|
|
object-position: top center;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 0;
|
|||
|
|
}
|
|||
|
|
</style>
|