Showing
3 changed files
with
201 additions
and
4 deletions
| ... | @@ -18,12 +18,14 @@ declare module 'vue' { | ... | @@ -18,12 +18,14 @@ declare module 'vue' { |
| 18 | ElInput: typeof import('element-ui/lib/input')['default'] | 18 | ElInput: typeof import('element-ui/lib/input')['default'] |
| 19 | ElRow: typeof import('element-ui/lib/row')['default'] | 19 | ElRow: typeof import('element-ui/lib/row')['default'] |
| 20 | HagerBox: typeof import('./src/components/common/hagerBox.vue')['default'] | 20 | HagerBox: typeof import('./src/components/common/hagerBox.vue')['default'] |
| 21 | + HagerCarousel: typeof import('./src/components/hagerCarousel.vue')['default'] | ||
| 21 | HagerFooter: typeof import('./src/components/common/hagerFooter.vue')['default'] | 22 | HagerFooter: typeof import('./src/components/common/hagerFooter.vue')['default'] |
| 22 | HagerHeader: typeof import('./src/components/common/hagerHeader.vue')['default'] | 23 | HagerHeader: typeof import('./src/components/common/hagerHeader.vue')['default'] |
| 23 | Navbar: typeof import('./src/components/navbar.vue')['default'] | 24 | Navbar: typeof import('./src/components/navbar.vue')['default'] |
| 24 | RouterLink: typeof import('vue-router')['RouterLink'] | 25 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 25 | RouterView: typeof import('vue-router')['RouterView'] | 26 | RouterView: typeof import('vue-router')['RouterView'] |
| 26 | SlideComp: typeof import('./src/components/slideComp.vue')['default'] | 27 | SlideComp: typeof import('./src/components/slideComp.vue')['default'] |
| 28 | + TagerCarousel: typeof import('./src/components/tagerCarousel.vue')['default'] | ||
| 27 | VideoPlayer: typeof import('./src/components/videoPlayer.vue')['default'] | 29 | VideoPlayer: typeof import('./src/components/videoPlayer.vue')['default'] |
| 28 | } | 30 | } |
| 29 | } | 31 | } | ... | ... |
src/components/hagerCarousel.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-09-27 19:49:03 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-09-27 20:09:22 | ||
| 5 | + * @FilePath: /hager/src/components/hagerCarousel.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="hager-carousel"> | ||
| 10 | + <div class="image-switcher"> | ||
| 11 | + <!-- 缩略图区域 --> | ||
| 12 | + <div class="thumbnail-container"> | ||
| 13 | + <!-- 上箭头 --> | ||
| 14 | + <div class="arrow-up" @click="prevImage">▲</div> | ||
| 15 | + | ||
| 16 | + <!-- 缩略图列表 --> | ||
| 17 | + <div class="thumbnails"> | ||
| 18 | + <div | ||
| 19 | + v-for="(image, index) in visibleThumbnails" | ||
| 20 | + :key="index" | ||
| 21 | + :class="['thumbnail', { active: selectedImage === (startIndex + index) }]" | ||
| 22 | + @click="selectImage(startIndex + index)" | ||
| 23 | + > | ||
| 24 | + <img :src="image" alt="thumbnail"> | ||
| 25 | + </div> | ||
| 26 | + </div> | ||
| 27 | + | ||
| 28 | + <!-- 下箭头 --> | ||
| 29 | + <div class="arrow-down" @click="nextImage">▼</div> | ||
| 30 | + </div> | ||
| 31 | + | ||
| 32 | + <!-- 右边大图区域 --> | ||
| 33 | + <div class="main-image" :class="{ 'fade-out': isTransitioning, 'fade-in': !isTransitioning }"> | ||
| 34 | + <img :src="images[selectedImage]" alt="main image"> | ||
| 35 | + </div> | ||
| 36 | + </div> | ||
| 37 | + </div> | ||
| 38 | +</template> | ||
| 39 | + | ||
| 40 | +<script> | ||
| 41 | +import mixin from "common/mixin"; | ||
| 42 | + | ||
| 43 | +export default { | ||
| 44 | + mixins: [mixin.init], | ||
| 45 | + data() { | ||
| 46 | + return { | ||
| 47 | + selectedImage: 0, // 当前选中的图片索引 | ||
| 48 | + startIndex: 0, // 当前显示的缩略图起始索引 | ||
| 49 | + thumbnailsToShow: 4, // 每次显示4个缩略图 | ||
| 50 | + isTransitioning: false, // 控制大图的切换动画 | ||
| 51 | + images: [ | ||
| 52 | + "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", | ||
| 53 | + "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg", | ||
| 54 | + "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", | ||
| 55 | + "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg", | ||
| 56 | + "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", | ||
| 57 | + "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg", | ||
| 58 | + "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg", | ||
| 59 | + ], | ||
| 60 | + }; | ||
| 61 | + }, | ||
| 62 | + mounted() {}, | ||
| 63 | + computed: { | ||
| 64 | + // 计算当前显示的缩略图 | ||
| 65 | + visibleThumbnails() { | ||
| 66 | + return this.images.slice(this.startIndex, this.startIndex + this.thumbnailsToShow); | ||
| 67 | + }, | ||
| 68 | + endIndex() { | ||
| 69 | + return this.startIndex + this.thumbnailsToShow - 1; | ||
| 70 | + } | ||
| 71 | + }, | ||
| 72 | + methods: { | ||
| 73 | + // 选择某个图片并更新大图和选中状态 | ||
| 74 | + selectImage(index) { | ||
| 75 | + this.isTransitioning = true; // 开始大图的淡出动画 | ||
| 76 | + setTimeout(() => { | ||
| 77 | + this.selectedImage = index; // 切换大图 | ||
| 78 | + this.isTransitioning = false; // 动画结束 | ||
| 79 | + this.ensureVisibleThumbnail(); // 保证选中的缩略图在可视区域 | ||
| 80 | + }, 500); // 动画时间为500ms | ||
| 81 | + }, | ||
| 82 | + // 控制缩略图上下滚动 | ||
| 83 | + scrollThumbnails(direction) { | ||
| 84 | + if (direction === 'up' && this.startIndex > 0) { | ||
| 85 | + this.startIndex--; | ||
| 86 | + } else if (direction === 'down' && this.endIndex < this.images.length - 1) { | ||
| 87 | + this.startIndex++; | ||
| 88 | + } | ||
| 89 | + }, | ||
| 90 | + // 确保选中的缩略图在可见范围内 | ||
| 91 | + ensureVisibleThumbnail() { | ||
| 92 | + if (this.selectedImage < this.startIndex) { | ||
| 93 | + // 如果选中的缩略图在当前显示范围的上方,则向上滚动 | ||
| 94 | + this.startIndex = this.selectedImage; | ||
| 95 | + } else if (this.selectedImage > this.endIndex) { | ||
| 96 | + // 如果选中的缩略图在当前显示范围的下方,则向下滚动 | ||
| 97 | + this.startIndex = this.selectedImage - this.thumbnailsToShow + 1; | ||
| 98 | + } | ||
| 99 | + }, | ||
| 100 | + // 切换到下一张图片 | ||
| 101 | + nextImage() { | ||
| 102 | + if (this.selectedImage < this.images.length - 1) { | ||
| 103 | + this.selectImage(this.selectedImage + 1); | ||
| 104 | + } | ||
| 105 | + }, | ||
| 106 | + // 切换到上一张图片 | ||
| 107 | + prevImage() { | ||
| 108 | + if (this.selectedImage > 0) { | ||
| 109 | + this.selectImage(this.selectedImage - 1); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + }, | ||
| 113 | +}; | ||
| 114 | +</script> | ||
| 115 | + | ||
| 116 | +<style lang="less" scoped> | ||
| 117 | +.hager-carousel { | ||
| 118 | + .image-switcher { | ||
| 119 | + display: flex; | ||
| 120 | + align-items: center; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + .thumbnail-container { | ||
| 124 | + display: flex; | ||
| 125 | + flex-direction: column; | ||
| 126 | + align-items: center; | ||
| 127 | + margin-right: 20px; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + .arrow-up, | ||
| 131 | + .arrow-down { | ||
| 132 | + cursor: pointer; | ||
| 133 | + padding: 5px; | ||
| 134 | + font-size: 18px; | ||
| 135 | + user-select: none; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + .thumbnails { | ||
| 139 | + display: flex; | ||
| 140 | + flex-direction: column; | ||
| 141 | + align-items: center; | ||
| 142 | + max-height: 220px; /* 限制缩略图容器的高度 */ | ||
| 143 | + overflow: hidden; | ||
| 144 | + position: relative; /* 为缩略图滚动效果提供基础 */ | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + .thumbnail { | ||
| 148 | + width: 50px; | ||
| 149 | + height: 50px; | ||
| 150 | + margin-bottom: 10px; | ||
| 151 | + cursor: pointer; | ||
| 152 | + border: 2px solid transparent; | ||
| 153 | + transition: border 0.3s; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + .thumbnail img { | ||
| 157 | + width: 100%; | ||
| 158 | + height: 100%; | ||
| 159 | + object-fit: cover; | ||
| 160 | + transition: transform 0.5s ease-in-out; /* 缩略图切换时的动画效果 */ | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + .thumbnail.active { | ||
| 164 | + border: 2px solid #00f; /* 选中的缩略图边框样式 */ | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + .main-image { | ||
| 168 | + width: 300px; | ||
| 169 | + height: 300px; | ||
| 170 | + position: relative; | ||
| 171 | + transition: opacity 0.5s ease-in-out; /* 大图切换时的淡入淡出效果 */ | ||
| 172 | + opacity: 1; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + .main-image img { | ||
| 176 | + width: 100%; | ||
| 177 | + height: 100%; | ||
| 178 | + object-fit: cover; | ||
| 179 | + position: absolute; | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + .main-image.fade-out { | ||
| 183 | + opacity: 0; /* 当切换时,将大图的透明度渐变为0 */ | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + .main-image.fade-in { | ||
| 187 | + opacity: 1; /* 切换后,图片渐渐显现 */ | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + .thumbnails-wrapper { | ||
| 191 | + transition: transform 0.5s ease-in-out; /* 缩略图滑动时的动画效果 */ | ||
| 192 | + display: flex; | ||
| 193 | + flex-direction: column; | ||
| 194 | + } | ||
| 195 | +} | ||
| 196 | +</style> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-08-27 10:06:30 | 2 | * @Date: 2024-08-27 10:06:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-09-26 17:18:46 | 4 | + * @LastEditTime: 2024-09-27 19:51:44 |
| 5 | * @FilePath: /hager/src/views/index.vue | 5 | * @FilePath: /hager/src/views/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div> | 9 | <div> |
| 10 | <hager-box style="background-color: #fff;"> | 10 | <hager-box style="background-color: #fff;"> |
| 11 | - <div v-for="(item, index) in 10" :key="index"> | 11 | + <hager-carousel></hager-carousel> |
| 12 | - <div style="height: 5rem;">{{ index + 1 }}</div> | ||
| 13 | - </div> | ||
| 14 | </hager-box> | 12 | </hager-box> |
| 15 | <hager-box style="background-color: #f1f1f1;"> | 13 | <hager-box style="background-color: #f1f1f1;"> |
| 16 | <div v-for="(item, index) in 10" :key="index"> | 14 | <div v-for="(item, index) in 10" :key="index"> |
| ... | @@ -23,6 +21,7 @@ | ... | @@ -23,6 +21,7 @@ |
| 23 | <script> | 21 | <script> |
| 24 | import mixin from '@/common/mixin'; | 22 | import mixin from '@/common/mixin'; |
| 25 | import hagerBox from '@/components/common/hagerBox'; | 23 | import hagerBox from '@/components/common/hagerBox'; |
| 24 | +import hagerCarousel from '@/components/hagerCarousel'; | ||
| 26 | 25 | ||
| 27 | export default { | 26 | export default { |
| 28 | mixins: [mixin.init], | 27 | mixins: [mixin.init], | ... | ... |
-
Please register or login to post a comment