<template>
<div class="movie-list-component">
<view class="list-container">
<scroll-view id="contentScroll" class="scroll-view" :scroll-with-animation="true" :scroll-left="scrollLeft"
:scroll-x="true" style="width: 100%;" @scroll="onScroll" @touchstart="onTouchStart" @touchend="onTouchEnd">
<div class="movie-item seat"></div>
<view :data-id="item.id" @click="selectMovie" :id="`movieItem${item.id}`" class="movie-item"
:class="{ active: modelValue == item.id }" v-for="( item, index ) in list " :key="index">
<div class="img-container">
<image class="img" :src="item?.image" alt="" />
</div>
<!-- <div class="point-container"></div> -->
</view>
<div class="movie-item seat1"></div>
</scroll-view>
</view>
</div>
</template>
<script setup lang="ts">
import Taro from "@tarojs/taro";
import { onMounted, ref, reactive, toRefs, watch } from "vue";
const props = defineProps({
// 子组件接收父组件传递过来的值
list: {
type: Array<any>,
required: true,
},
modelValue: {
type: Number,
required: true,
},
});
//使用父组件传递过来的值
const { list, modelValue } = toRefs(props);
const emit = defineEmits(["onchangeMovie"]);
const clientWidths = ref(0)
const isSwitchingMovie = ref(false)
onMounted(() => {
list?.value.map((item, index) => {
if (item.id === modelValue?.value) {
list?.value.unshift(list?.value.splice(index, 1)[0]);
}
});
});
const scrollLeft = ref(0);
//选择电影
const selectMovie = (e) => {
isSwitchingMovie.value = true; // 点击切换电影时设置为true
let offsetLeft = e.currentTarget.offsetLeft;
let { id } = e.currentTarget.dataset;
if (!id) {
id = list.value[0].id;
}
if (modelValue.value === id) {
return;
}
emit("onchangeMovie", id);
getRect(id, offsetLeft);
};
//滚动事件处理函数
const onScroll = (e) => {
if (isSwitchingMovie.value) {
return; // 如果处于切换电影状态,不执行滚动事件逻辑
}
requestAnimationFrame(() => {
const contentScroll = Taro.createSelectorQuery();
contentScroll.select("#contentScroll").boundingClientRect();
contentScroll.exec((res) => {
const clientWidth = res[0].width;
clientWidths.value = clientWidth;
// 执行其他逻辑
});
const { scrollLeft } = e.detail;
const currentIndex = Math.round(scrollLeft / (clientWidths.value / 4));
const index = currentIndex >= list.value.length ? list.value.length - 1 : currentIndex;
const id = list.value[index]?.id;
if (modelValue.value !== id) {
emit("onchangeMovie", id);
}
});
};
// 触摸开始事件,用于标记点击切换电影状态开始
const onTouchStart = () => {
isSwitchingMovie.value = true;
};
// 触摸结束事件,用于标记点击切换电影状态结束
const onTouchEnd = () => {
isSwitchingMovie.value = false;
};
//计算电影item的偏移量
const getRect = async (id, offsetLeft) => {
const eleId = `#movieItem${id}`;
const contentScrollWidth: any = await getContentScrollWidth("#contentScroll");
const query = Taro.createSelectorQuery();
query.select(eleId).boundingClientRect();
query.selectViewport().scrollOffset();
query.exec(async (res) => {
//获取item的宽度de 一半
const subhalfwidth = res[0].width / 2;
//需要scrollview 移动的距离是
const juli = offsetLeft - contentScrollWidth / 2 + subhalfwidth;
scrollLeft.value = juli;
});
};
// 获取ScrollView的宽度
const getContentScrollWidth = (ele) => {
return new Promise((resolve) => {
const query = Taro.createSelectorQuery();
query.select(ele).boundingClientRect();
query.selectViewport().scrollOffset();
query.exec((res) => {
const width = res[0].width;
resolve(width);
});
});
};
</script>
<style lang="scss">
.movie-list-component {
display: flex;
flex-direction: column;
.list-container {
display: flex;
flex-direction: column;
justify-content: center;
height: 350px;
.scroll-view {
width: 100%;
height: 320px;
white-space: nowrap;
position: relative;
.movie-item {
display: inline-block;
position: relative;
margin-left: 25px;
// display: flex;
// justify-content: center;
// align-items: center;
border-radius: 18px;
// overflow: hidden;
width: 146px;
height: 218px;
transition: width 0.8s;
transition: height 0.8s;
.img-container {
border-radius: 8px;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
z-index: 2;
// border: 5px #ffffff solid;
.img {
width: 100%;
height: 100%;
}
}
}
.movie-item.active {
// width: 180px !important;
// height: 270px !important;
transform: scale(1.1);
transition: transform 0.8s ease;
.img-container {
border-radius: 10px;
border: 3px #ffffff solid;
}
// .point-container {
// z-index: 1;
// height: 30px;
// width: 30px;
// background: #5232B7;
// // border-radius: 7px;
// position: absolute;
// bottom: -15px;
// left: 50%;
// margin-left: -15px;
// transform: rotate(45deg);
// }
}
.seat {
display: inline-block;
width: 50%;
height: 290px;
margin-left: -100px;
}
.seat1 {
display: inline-block;
width: 36%;
height: 290px;
// margin-left: 50px;
}
}
}
}
</style>
以上代码是滑动的组件