Taro+vue3 实现电影切换列表

1.需求

 我们在做类似于猫眼电影的小程序或者H5 的时候 我们会做到那种 左右滑动的电影列表,这种列表一般带有电影场次 

2.效果

3.说明

 这种效果在淘票票 猫眼电影上 都有的 ,一般电影类型的H5 或者小程序 这个是都有的 第一是好看 第二是客观性比较好

4.代码、

1.整体页面
<template><div class="movie-container-index"><Header></Header><div class="swiper-main"><image class="background-img-vague" :src="chooseMovice.posterUrl" style="height: 100%;"></image><div class="wrap"><MovieList :list="movieList" @onchangeMovie="MovieChange" :model-value="chooseMovice.movieId"></MovieList></div><div class="box"></div></div><div class="movie-detail"><div class="name">{{ chooseMovice.movieName }}</div><div class="center-detail"><div>{{ chooseMovice.movieType }}</div><div>{{ chooseMovice.duration }}</div></div><div class="cast">{{ chooseMovice.cast }}</div></div><div class="movie-time-container"><Filter v-if="timeList.length" :data="timeList" @onChanged="onTimeChanged"></Filter></div><div class="movie-arrgement-container" v-if="arrangementList.length && !loading"><Item v-for="(item, index) in arrangementList" :info="item" :key="index"></Item></div><template v-if="arrangementList.length === 0 && loading"><div style="padding:  0 15px;"><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton><nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animatedrow="1"></nut-skeleton></div></template><template v-if="arrangementList.length === 0 && !loading"><nut-empty description="暂无场次"></nut-empty></template></div>
</template>
<script setup>
import Header from './header.vue'
import MovieList from './movie-list.vue'
import Filter from './filter.vue'
import { ref, reactive, onMounted } from 'vue'
import Item from './item.vue'
const chooseMovice = ref({movieId: 12343,duration: 149,movieType: '剧情|历史|战争',cast: '吴京 易烊千玺 段奕宏 张涵予 朱亚文',posterUrl: "https://gw.alicdn.com/i1/O1CN01sSmj2b1daSm6IAUcs_!!6000000003752-0-alipicbeacon.jpg_480x480Q30s150.jpg",movieName: '长津湖之水门桥',})
const timeList = ref(["2024-01-09", "2024-01-10", "2024-01-13"])
const arrangementList = ref([])
const loading = ref(true)
const movieList = ref([{movieId: 12343,duration: 149,movieType: '剧情|历史|战争',cast: '吴京 易烊千玺 段奕宏 张涵予 朱亚文',movieName: '长津湖之水门桥',posterUrl: "https://gw.alicdn.com/i1/O1CN01sSmj2b1daSm6IAUcs_!!6000000003752-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "易烊千玺 田雨 陈哈琳 齐溪 公磊 许君聪 王宁 黄尧 巩金国",duration: 106,movieId: 147885,movieName: "奇迹·笨小孩",movieType: "剧情",posterUrl: "https://gw.alicdn.com/i1/O1CN013Ggc2s1Z8HwrwxAfn_!!6000000003149-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "张译,李晨,魏晨,曹炳琨,王骁,张子贤,杨新鸣",duration: 106,movieId: 147886,movieName: "三大队",movieType: "剧情,犯罪",posterUrl: "https://gw.alicdn.com/i4/O1CN01zQvWon1SuCCkUXTr8_!!6000000002306-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "岑珈其,梁朝伟,刘德华,蔡卓妍,任达华,陈家乐,白只,姜皓文,方中信,太保,钱嘉乐,周家怡",duration: 106,movieId: 147887,movieName: "金手指",movieType: "犯罪,剧情",posterUrl: "https://gw.alicdn.com/i4/O1CN01mdCwok1K4QV7FV8gv_!!6000000001110-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "李栋,大鹏,白客,庄达菲,王迅,孙艺洲,李乃文",duration: 106,movieId: 147888,movieName: "年会不能停!",movieType: "喜剧,剧情",posterUrl: "https://gw.alicdn.com/i1/O1CN01v6g8341QMBaLa2FhI_!!6000000001961-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "屈楚萧,张佳宁,傅菁,蒋昀霖,牛超,田壮壮,沙溢",duration: 106,movieId: 147889,movieName: "一闪一闪亮星星",movieType: "爱情,奇幻",posterUrl: "https://gw.alicdn.com/i4/O1CN01W8mzt61aa3k1Xtw3N_!!6000000003345-0-alipicbeacon.jpg_480x480Q30s150.jpg"},{cast: "江户川柯南,高山南,山崎和佳奈,小山力也,林原惠美,置鲇龙太郎,三石琴乃,土师孝也,乃村健次,飞田展男,绪方贤一,松井菜樱子,岩居由希子,大谷育江,茶风林",duration: 106,movieId: 147890,movieName: "名侦探柯南:黑铁的鱼影",movieType: "动画,悬疑,动作",posterUrl: "https://gw.alicdn.com/i1/O1CN01U9wWR81pfku0aqB6O_!!6000000005388-0-alipicbeacon.jpg_480x480Q30s150.jpg"}])
const MovieChange = (e) => {console.log(e);chooseMovice.value = movieList.value.filter((item) => item.movieId == e)[0]}
onMounted(() => {arrangementList.value = [{finishTime: "1704782520000",hallName: "7号激光杜比全景声厅",id: "1194219979173253121",pickUpPrice: 3380,price: 3500,showTime: "1704775500000"}]loading.value = false
})
</script>
<style lang="scss">
.movie-container-index {display: flex;flex-direction: column;.movie-arregment-container {}.swiper-main {height: 324px;position: relative;overflow: hidden;width: 100%;.background-img-vague {position: absolute;left: 0;right: 0;width: 100%;height: 100%;filter: blur(15px);-webkit-filter: blur(15px);}}.movie-detail {display: flex;flex-direction: column;align-items: center;justify-content: center;background-color: #fff;padding: 20px;.name {font-size: 30px;font-weight: 700;color: #15181d;}.center-detail {display: flex;align-items: center;color: #858a99;font-size: 24px;margin-top: 5px;}.cast {color: #858a99;font-size: 24px;margin-top: 5px;word-break: break-all;text-align: center;overflow: hidden;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}}.wrap {padding: 10px 0;}.box {width: 0;height: 0;border: 10rpx solid;border-color: transparent transparent #fff #fff;transform: rotate(135deg);position: absolute;bottom: -10rpx;left: 0;right: 0;margin: 0 auto;}
}
</style>
2.movie-list代码<template><div class="movie-list-component"><div class="list-container"><scroll-view id="contentScroll" class="scroll-view" :scroll-with-animation="true" :scroll-left="scrollLeft":scroll-x="true"><div class="movie-item seat"></div><div :data-id="item.movieId" @click="selectMovie" :id="`movieItem${item.movieId}`" class="movie-item" :class="{ active: modelValue == item.movieId }" v-for="( item, index ) in  list " :key="index"><div class="img-container"><image class="img" :src="item?.posterUrl" alt="" /></div></div><div class="movie-item seat1"></div></scroll-view></div></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"]);onMounted(() => {// selectMovie(list.value[0].movieId)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) => {let offsetLeft = e.currentTarget.offsetLeft;let { id } = e.currentTarget.dataset;if (!id) {id = list.value[0].movieId;}if (modelValue.value == id) {return;}emit("onchangeMovie", id);getRect(id, offsetLeft);
};
//计算电影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: 324px;.scroll-view {width: 100%;height: 324px;white-space: nowrap;position: relative;.movie-item:nth-child(n+2) {margin-left: 35px;}.movie-item {display: inline-block;position: relative;margin-top: 30px;border-radius: 18px;width: 156px;height: 218px;// line-height: 208px;transition: width 1s;transition: height 1s;.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 {transform: scale(1.15);/* 放大1.2倍 */transition: transform 1s ease;/* 过渡效果 */}.seat {display: inline-block;width: 50%;// height: 290px;margin-left: -110px;}.seat1 {display: inline-block;width: 35%;}}}
}
</style>
filter 组件<template><div class="cinema-detail-filter-container"><div class="date-tab"><nut-tabs :title-gutter="15" v-model="tabTimesIndex" title-scroll><nut-tab-pane v-for="(item, index) in tabTimesList" :pane-key="index" :title="`${item.t} ${item.a}`"></nut-tab-pane></nut-tabs></div></div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, toRefs, watch } from 'vue';
import moment from "moment";
const tabTimesIndex = ref(0)
const tabTimesList: any = ref([])
const props = defineProps({//子组件接收父组件传递过来的值data: Object,
});
//使用父组件传递过来的值
const { data: timesList } = toRefs(props);
onMounted(() => {getTimes()
});
const emit = defineEmits(['onChanged'])
watch(tabTimesIndex, (index) => {emit('onChanged', tabTimesList.value[index])
})
watch(tabTimesList, () => {emit('onChanged', tabTimesList.value[0])
})
const getTimes = () => {const times = timesList?.valueconst arr: any = []times?.forEach(item => {const time = itemlet t = getweek(moment(time).startOf('day').format('E'))if (time === moment().format('YYYY-MM-DD')) {t = '今天'} else if (time === moment().subtract(-1, 'days').format('YYYY-MM-DD')) {t = '明天'} else if (time === moment().subtract(-2, 'days').format('YYYY-MM-DD')) {t = '后天'}arr.push({time: time,t: t,a: time.substr(5, 9)})});tabTimesList.value = arr}
const getweek = (val) => {const week = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']return week[val - 1];
};
</script>
<style lang="scss">
.cinema-detail-filter-container {display: flex;flex-direction: column;.nut-tabs {.nut-tabs__titles {background: #ffffff !important;.nut-tabs__titles-item {.nut-tabs__titles-item__smile {display: none;}.nut-tabs__titles-item__text {color: #858a99;font-size: 22px !important;}}.nut-tabs__titles-item__line {background: linear-gradient(to right, #5232B7, #7237BC, #5232B7) !important;border-radius: 30px !important;}.nut-tabs__titles-item.active {.nut-tabs__titles-item__smile {display: block;margin-top: 10px;}.nut-tabs__titles-item__text {color: #15181d;}}}.nut-tabs__content {display: none !important;}}
}
</style>
header 组件<template><div class="movie-header-box"><div class="left"><div class="name">万达影城(北京昌平保利光魔店)</div><div class="address">昌平区鼓楼街贾琏时代广场四楼</div></div><div class="right"><IconFont name="locationg3" color="#5232B7"></IconFont></div></div>
</template>
<script setup>
import { IconFont } from '@nutui/icons-vue-taro';
</script>
<style lang="scss">
.movie-header-box {display: flex;align-items: center;justify-content: space-between;background-color: #fff;padding: 25px 30px;.left {.name {color: #15181d;font-weight: 700;font-size: 26px;}.address {color: #858a99;font-size: 22px;margin-top: 10px;}}
}
</style>

5.我这个项目是基于Taro +vue3 +ts 来写的 用的组件库也是京东的nut-ui  以上的代码和组件 也有的是我二次封装的组件 组件也挺方便的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/336077.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day7:消息队列与共享内存

思维导图&#xff1a; 消息队列原理&#xff1a; 进程在内核空间中维护出消息队列&#xff0c;每个进程借由消息队列的msgid对消息队列进行读写操作&#xff0c;消息队列中的信息是一个结构体&#xff0c;存储着消息的种类&#xff08;身份证&#xff09;和消息的内容&#xff…

《数据结构、算法与应用C++语言描述》-红黑树的C++实现-百万级数据量测试通过

红黑树 完整可编译运行代码见仓库&#xff1a;GitHub - Jasmine-up/Data-Structures-Algorithms-and-Applications/_3matrix。 如有问题请在评论区指出。另外&#xff0c;Github仓库会根据我的学习情况持续更新&#xff0c;欢迎大家点star&#xff0c;谢谢。 基本概念 红-黑…

智数融合|低代码入局,推动工业数字化转型走"深"向"实"

当下&#xff0c;“数字化、智能化”已经不再是新鲜词汇。事实上&#xff0c;早在几年前&#xff0c;就有企业开始大力推动数字化转型&#xff0c;并持续进行了一段时间。一些业内人士甚至认为&#xff0c;“如今的企业数字化已经走过了成熟期&#xff0c;进入了深水区。” 但事…

虚幻UE 材质-进阶边界混合之距离场限制PDO范围

基础边界混合那篇文章&#xff1a;虚幻UE 材质-边界混合之PDO像素深度偏移量 可以通过抖动来进行混合&#xff0c;但是有问题的点在与抖动发生的位置只需要在两物体的交界处 所以本篇文章会通过距离场限制来限制抖动的位置&#xff0c;防止其他地方发生抖动影响画面。 文章目录…

三、yolov8训练结果查看和模型预测

训练结果查看 1、在模型训练结束后&#xff0c;如下图所示&#xff0c;找到该文件夹。 2、然后找到weights文件夹中的best.pt文件&#xff0c;这就是该数据训练后的模型。 模型预测 1、在assets文件夹下创建FPC-2文件夹&#xff0c;放入一些同类FPC预测结果。 2、和训练…

HarmonyOS@Link装饰器:父子双向同步

Link装饰器&#xff1a;父子双向同步 子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 装饰器使用规则说明 Link变…

SpringMVC-异常处理及常用组件

异常处理器 1.基于配置的异常处理 springmvc提供了一个处理控制器方法执行过程中所出现的异常的接口: HandlerExceptionResolver HandlerExceptionResolver接口的实现类有: DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver springmvc提供了自定义的异常处…

【python】爬取豆瓣电影排行榜Top250存储到Excel文件中【附源码】

英杰社区https://bbs.csdn.net/topics/617804998 一、背景 近年来&#xff0c;Python在数据爬取和处理方面的应用越来越广泛。本文将介绍一个基于Python的爬虫程 序&#xff0c;用于抓取豆瓣电影Top250的相关信息&#xff0c;并将其保存为Excel文件。 程序包含以下几个部…

数据库的导入导出以及备份

1.数据库的导出和导入 一.navicat导入导出 导入&#xff1a;右键➡运行SQL文件 导出选&#xff1a;中要导出的表➡右键➡转储SQL文件➡数据和结构 mysqldump命 1. 进入navicat安装目录的bin目录&#xff0c;cmd打开命令窗口 2. mysql -u用户名 -p ➡ 输入密码 3. creat…

李沐之神经网络基础

目录 1.模型构造 1.1层和块 1.2自定义块 1.3顺序块 1.4在前向传播函数中执行代码 2.参数管理 2.1参数访问 2.2参数初始化 3.自定义层 3.1不带参数的层 3.2带参数的层 4.读写文件 4.1加载和保存张量 4.2加载和保存模型参数 1.模型构造 1.1层和块 import torch fr…

K2P路由器刷OpenWrt官方最新版本固件OpenWrt 23.05.2方法 其他型号的智能路由器OpenWrt固件刷入方法也基本上适用

最近路由器在开机时总出问题,于是就那他来开刀,直接刷一个OpenWrt官方最新版本的固件, 刷其他第三方的固件总是觉得不安全, 而且很多第三方固件都带了些小工具,始终会有安全隐患, 而且占用内存空间太多,本来这个东西就没有多少内存,于是就干脆刷一个官方的原始固件(才6.3M, 相…

网卡高级设置-提高网络环境

网卡高级设置&#xff0c;提高网络质量排除一些连接问题 一、有线网卡 1、关闭IPv6&#xff1b; 可以关闭协议版本6&#xff0c;因为它会引起一些网络连接问题&#xff0c;而且现在几乎用不到IP6。 2、关闭节约电源模式&#xff1b; 右击计算机->设备->设备管理器-&…