officialAccount/compontent/public/photohuadong.vue

249 lines
6.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view
class="carousel"
@touchstart="onTouchStart"
@touchmove.prevent="onTouchMove"
@touchend="onTouchEnd"
>
<view
v-for="(img, i) in visibleImages"
:key="img"
class="carousel-item"
:style="itemStyle(i)"
>
<image :src="img" mode="aspectFill" class="carousel-image" />
<view class="font" :style="i==1?{fontWeight:600}:{}" >{{img.includes('0') ? imageName[0] : (img.includes('1') ? imageName[1] : imageName[2])}} </view>
</view>
<view
class="carousel-item"
:style="leftCopyStyle"
key="left-copy"
>
<image :src="leftCopyImage" mode="aspectFill" class="carousel-image" />
</view>
<view
class="carousel-item"
:style="rightCopyStyle"
key="right-copy"
>
<image :src="rightCopyImage" mode="aspectFill" class="carousel-image" />
</view>
</view>
</template>
<script setup>
import { ref, computed,watch } from 'vue';
const emit = defineEmits(['updateCenterIndex'])
const images = ref([
'https://www.focusnu.com/media/directive/index/three/0.png',
'https://www.focusnu.com/media/directive/index/three/1.png',
'https://www.focusnu.com/media/directive/index/three/2.png',
])
const imageName = ref([
"长者入住",
"机构加盟",
"员工入驻",
])
const len = images.value.length
const startX = ref(0)
const position = ref(0)
const isDragging = ref(false)
const enableTransition = ref(false)
const dragDirection = ref(0)
const imageSpacing = 220
const centerIndex = computed(() => {
return mod(Math.floor(position.value), len)
})
const leftIndex = computed(() => mod(centerIndex.value - 1, len))
const rightIndex = computed(() => mod(centerIndex.value + 1, len))
const visibleImages = computed(() => [
images.value[leftIndex.value],
images.value[centerIndex.value],
images.value[rightIndex.value],
])
const leftCopyImage = computed(() => images.value[leftIndex.value])
const rightCopyImage = computed(() => images.value[rightIndex.value])
function mod(n, m) {
return ((n % m) + m) % m
}
function onTouchStart(e) {
if (enableTransition.value) enableTransition.value = false
isDragging.value = true
startX.value = e.touches[0].clientX
dragDirection.value = 0
}
function onTouchMove(e) {
if (!isDragging.value) return
const currentX = e.touches[0].clientX
const delta = currentX - startX.value
dragDirection.value = delta > 0 ? 1 : -1
position.value -= delta / imageSpacing
startX.value = currentX
}
function onTouchEnd() {
if (!isDragging.value) return
isDragging.value = false
enableTransition.value = true
position.value = Math.round(position.value)
}
function itemStyle(i) {
const floorPos = Math.floor(position.value)
const offset = position.value - floorPos // [-1, 1)
const absOff = Math.abs(offset) // 0 → 1
// 计算水平偏移
const baseX = (i - 1) * imageSpacing
const translateX = baseX - offset * imageSpacing
// 透明度和 zIndex保持原来逻辑不变
let opacity = 0.5
let zIndex = 1
if (i === 1) {
opacity = 1 - 0.5 * absOff
zIndex = 3
} else if ((i === 2 && offset >= 0) || (i === 0 && offset < 0)) {
opacity = 0.5 + 0.5 * absOff
zIndex = 2
}
// ← 这里是关键:统一用 absOff 计算 scale
let scale = 0.8
if (i === 1) {
// 中心项目offset 0 时放到 1.1offset 1 时收到 0.8
scale = 1.1 - 0.3 * absOff
} else if ((i === 2 && offset >= 0) || (i === 0 && offset < 0)) {
// 侧边项目offset 0 时 0.8offset 1 时 1.1
scale = 0.8 + 0.3 * absOff
}
return {
transform: `translate(-50%, -50%) translateX(${translateX}rpx) scale(${scale})`,
opacity,
zIndex,
transition: enableTransition.value
? 'transform 0.3s ease, opacity 0.3s ease'
: 'none',
}
}
const leftCopyStyle = computed(() => {
const show = dragDirection.value === 1
const floorPos = Math.floor(position.value)
const offset = position.value - floorPos
const translateX = 2.2 * imageSpacing - offset * imageSpacing
let scale = 0.8
let opacity = 0.5
let zIndex = 2
if (offset < 0) {
const posOffset = -offset
scale = 0.8 + 0.5 * posOffset
opacity = 0.5 + 0.5 * posOffset
}
return {
transform: `translate(-50%, -50%) translateX(${translateX}rpx) scale(${scale})`,
opacity,
zIndex,
pointerEvents: 'none',
position: 'absolute',
top: '40%',
left: '50%',
opacity: show ? 0.5 : 0,
willChange: 'transform, opacity',
transition: enableTransition.value
? 'transform 0.3s ease, opacity 0.3s ease'
: 'none',
}
})
const rightCopyStyle = computed(() => {
const show = dragDirection.value === 1
const floorPos = Math.floor(position.value)
const offset = position.value - floorPos
const translateX = -2.2 * imageSpacing - offset * imageSpacing
let scale = 0.8
let opacity = 0.5
let zIndex = 2
if (offset >= 0) {
scale = 0.8 + 0.5 * offset
opacity = 0.5 + 0.5 * offset
}
return {
transform: `translate(-50%, -50%) translateX(${translateX}rpx) scale(${scale})`,
opacity,
zIndex,
pointerEvents: 'none',
position: 'absolute',
top: '40%',
left: '50%',
opacity: show ? 0.5 : 0,
willChange: 'transform, opacity',
transition: enableTransition.value
? 'transform 0.3s ease, opacity 0.3s ease'
: 'none',
}
})
// 3. 监听 centerIndex 的变化,一旦改变就 emit
watch(centerIndex, (newIdx) => {
// console.log("???",newIdx)
emit('updateCenterIndex', newIdx)
})
</script>
<style scoped>
.carousel {
position: relative;
width: 90%;
height: 650rpx;
display: flex;
justify-content: center;
overflow: hidden;
}
.carousel-item {
position: absolute;
width: 300rpx;
height: 450rpx;
top: 40%;
left: 50%;
margin: 0;
backface-visibility: hidden;
will-change: transform, opacity;
}
.carousel-image {
width: 100%;
height: 100%;
border-radius: 12rpx;
user-select: none;
touch-action: pan-y;
pointer-events: none;
}
.font{
width: 100%;
display: flex;
justify-content: center;
margin-top: 20rpx;
}
</style>