hookehuyr

✨ feat: 新增详情页产品显示切换组件测试

......@@ -18,12 +18,14 @@ declare module 'vue' {
ElInput: typeof import('element-ui/lib/input')['default']
ElRow: typeof import('element-ui/lib/row')['default']
HagerBox: typeof import('./src/components/common/hagerBox.vue')['default']
HagerCarousel: typeof import('./src/components/hagerCarousel.vue')['default']
HagerFooter: typeof import('./src/components/common/hagerFooter.vue')['default']
HagerHeader: typeof import('./src/components/common/hagerHeader.vue')['default']
Navbar: typeof import('./src/components/navbar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SlideComp: typeof import('./src/components/slideComp.vue')['default']
TagerCarousel: typeof import('./src/components/tagerCarousel.vue')['default']
VideoPlayer: typeof import('./src/components/videoPlayer.vue')['default']
}
}
......
<!--
* @Date: 2024-09-27 19:49:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-09-27 20:09:22
* @FilePath: /hager/src/components/hagerCarousel.vue
* @Description: 文件描述
-->
<template>
<div class="hager-carousel">
<div class="image-switcher">
<!-- 缩略图区域 -->
<div class="thumbnail-container">
<!-- 上箭头 -->
<div class="arrow-up" @click="prevImage">▲</div>
<!-- 缩略图列表 -->
<div class="thumbnails">
<div
v-for="(image, index) in visibleThumbnails"
:key="index"
:class="['thumbnail', { active: selectedImage === (startIndex + index) }]"
@click="selectImage(startIndex + index)"
>
<img :src="image" alt="thumbnail">
</div>
</div>
<!-- 下箭头 -->
<div class="arrow-down" @click="nextImage">▼</div>
</div>
<!-- 右边大图区域 -->
<div class="main-image" :class="{ 'fade-out': isTransitioning, 'fade-in': !isTransitioning }">
<img :src="images[selectedImage]" alt="main image">
</div>
</div>
</div>
</template>
<script>
import mixin from "common/mixin";
export default {
mixins: [mixin.init],
data() {
return {
selectedImage: 0, // 当前选中的图片索引
startIndex: 0, // 当前显示的缩略图起始索引
thumbnailsToShow: 4, // 每次显示4个缩略图
isTransitioning: false, // 控制大图的切换动画
images: [
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
"https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg",
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
"https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg",
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
"https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg",
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
],
};
},
mounted() {},
computed: {
// 计算当前显示的缩略图
visibleThumbnails() {
return this.images.slice(this.startIndex, this.startIndex + this.thumbnailsToShow);
},
endIndex() {
return this.startIndex + this.thumbnailsToShow - 1;
}
},
methods: {
// 选择某个图片并更新大图和选中状态
selectImage(index) {
this.isTransitioning = true; // 开始大图的淡出动画
setTimeout(() => {
this.selectedImage = index; // 切换大图
this.isTransitioning = false; // 动画结束
this.ensureVisibleThumbnail(); // 保证选中的缩略图在可视区域
}, 500); // 动画时间为500ms
},
// 控制缩略图上下滚动
scrollThumbnails(direction) {
if (direction === 'up' && this.startIndex > 0) {
this.startIndex--;
} else if (direction === 'down' && this.endIndex < this.images.length - 1) {
this.startIndex++;
}
},
// 确保选中的缩略图在可见范围内
ensureVisibleThumbnail() {
if (this.selectedImage < this.startIndex) {
// 如果选中的缩略图在当前显示范围的上方,则向上滚动
this.startIndex = this.selectedImage;
} else if (this.selectedImage > this.endIndex) {
// 如果选中的缩略图在当前显示范围的下方,则向下滚动
this.startIndex = this.selectedImage - this.thumbnailsToShow + 1;
}
},
// 切换到下一张图片
nextImage() {
if (this.selectedImage < this.images.length - 1) {
this.selectImage(this.selectedImage + 1);
}
},
// 切换到上一张图片
prevImage() {
if (this.selectedImage > 0) {
this.selectImage(this.selectedImage - 1);
}
}
},
};
</script>
<style lang="less" scoped>
.hager-carousel {
.image-switcher {
display: flex;
align-items: center;
}
.thumbnail-container {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 20px;
}
.arrow-up,
.arrow-down {
cursor: pointer;
padding: 5px;
font-size: 18px;
user-select: none;
}
.thumbnails {
display: flex;
flex-direction: column;
align-items: center;
max-height: 220px; /* 限制缩略图容器的高度 */
overflow: hidden;
position: relative; /* 为缩略图滚动效果提供基础 */
}
.thumbnail {
width: 50px;
height: 50px;
margin-bottom: 10px;
cursor: pointer;
border: 2px solid transparent;
transition: border 0.3s;
}
.thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease-in-out; /* 缩略图切换时的动画效果 */
}
.thumbnail.active {
border: 2px solid #00f; /* 选中的缩略图边框样式 */
}
.main-image {
width: 300px;
height: 300px;
position: relative;
transition: opacity 0.5s ease-in-out; /* 大图切换时的淡入淡出效果 */
opacity: 1;
}
.main-image img {
width: 100%;
height: 100%;
object-fit: cover;
position: absolute;
}
.main-image.fade-out {
opacity: 0; /* 当切换时,将大图的透明度渐变为0 */
}
.main-image.fade-in {
opacity: 1; /* 切换后,图片渐渐显现 */
}
.thumbnails-wrapper {
transition: transform 0.5s ease-in-out; /* 缩略图滑动时的动画效果 */
display: flex;
flex-direction: column;
}
}
</style>
<!--
* @Date: 2024-08-27 10:06:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-09-26 17:18:46
* @LastEditTime: 2024-09-27 19:51:44
* @FilePath: /hager/src/views/index.vue
* @Description: 文件描述
-->
<template>
<div>
<hager-box style="background-color: #fff;">
<div v-for="(item, index) in 10" :key="index">
<div style="height: 5rem;">{{ index + 1 }}</div>
</div>
<hager-carousel></hager-carousel>
</hager-box>
<hager-box style="background-color: #f1f1f1;">
<div v-for="(item, index) in 10" :key="index">
......@@ -23,6 +21,7 @@
<script>
import mixin from '@/common/mixin';
import hagerBox from '@/components/common/hagerBox';
import hagerCarousel from '@/components/hagerCarousel';
export default {
mixins: [mixin.init],
......