leftRightSwiperScroll.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <!-- 文本超出,左右按钮滚动 -->
  3. <div ref="swiperScroll" class="left-right-swiper-scroll-box">
  4. <!-- 左边按钮 -->
  5. <div v-show="showLeftIcon" @click="handleLeftClick" class="scroll-icon left-icon">
  6. <i ></i>
  7. </div>
  8. <!-- 中间滚动区域 -->
  9. <div ref="swiperScrollContent" class="swiper-scroll-content">
  10. <slot></slot>
  11. </div>
  12. <!-- 右边按钮 -->
  13. <div v-show="showRightIcon" @click="handleRightClick" class="scroll-icon right-icon">
  14. <i ></i>
  15. </div>
  16. </div>
  17. </template>
  18. <script>
  19. export default {
  20. name: 'leftRightSwiperScroll',
  21. props: {
  22. swiperList: {
  23. type: Object,
  24. default: () => {
  25. return {};
  26. }
  27. }
  28. },
  29. data() {
  30. return {
  31. showRightIcon: false, // 是否显示右箭头
  32. swiperScrollWidth: 0, // 盒子的宽度
  33. swiperScrollContentWidth: 0, // 内容的宽度
  34. maxClickNum: 0, // 最大点击次数
  35. lastLeft: 0, // 上次滑动距离
  36. clickNum: 0, // 点击次数
  37. childrenList: [] // 传进来的子元素
  38. }
  39. },
  40. computed: {
  41. showLeftIcon() {
  42. return this.clickNum > 0
  43. }
  44. },
  45. mounted() {
  46. // 获取 HTMLCollection 转为 数组
  47. this.childrenList = [...this.$refs.swiperScrollContent.children];
  48. console.log('childrenList--->', this.childrenList);
  49. console.log('swiperScroll--->', this.$refs.swiperScroll);
  50. console.log('swiperScrollContent--->', this.$refs.swiperScrollContent);
  51. // 盒子的宽度
  52. this.swiperScrollWidth = this.$refs.swiperScroll.getBoundingClientRect().width;
  53. // 内容的宽度
  54. this.swiperScrollContentWidth = this.$refs.swiperScrollContent.getBoundingClientRect().width;
  55. // 比较盒子的宽度,跟内容的宽度:判断是否需要展示右边的按钮
  56. if(this.swiperScrollWidth < this.swiperScrollContentWidth) {
  57. this.showRightIcon = true;
  58. }
  59. console.log('盒子的宽度--->', this.swiperScrollWidth );
  60. console.log('内容的宽度--->', this.swiperScrollContentWidth);
  61. console.log('this.showRightIcon',this.showRightIcon)
  62. },
  63. methods: {
  64. // 点击右箭头(左侧滚动)
  65. handleRightClick() {
  66. // 如果点击次数小于数组长度-1时,执行左滑动效果。
  67. if (this.clickNum < this.childrenList.length - 1) {
  68. // 获取当前元素宽度
  69. let width = this.childrenList[this.clickNum].getBoundingClientRect().width;
  70. console.log(this.childrenList[this.clickNum], this.childrenList[this.clickNum].getBoundingClientRect());
  71. // 获取最后一个元素距离左侧的距离
  72. let lastItemOffsetLeft = this.childrenList[this.childrenList.length - 1].offsetLeft;
  73. // 获取最后一个元素宽度
  74. let lastWidth = this.childrenList[this.childrenList.length - 1].getBoundingClientRect().width;
  75. console.log('lastItemOffsetLeft-->', lastItemOffsetLeft, this.childrenList[this.childrenList.length - 1].getBoundingClientRect());
  76. // 获取可视区域宽度
  77. const lookWidth = this.$refs.swiperScroll.clientWidth;
  78. console.log('获取可视区域宽度-->lookWidth', lookWidth);
  79. // 如果最后一个元素距离左侧的距离+自身的宽度大于可视距离,表示最后一个元素没有出现,执行滚动效果
  80. if (lastItemOffsetLeft + lastWidth > lookWidth) {
  81. // 滚动距离(元素的magin-left值) = 负的它自己的长度 + 上一次滑动的距离
  82. this.$refs.swiperScrollContent.style.marginLeft = `${-width + this.lastLeft}px`;
  83. this.lastLeft = -width + this.lastLeft;
  84. // 点击次数+1
  85. this.clickNum++;
  86. // 记录到最后一个元素出现在可视区域时,点击次数的最大值。用于后面点击左侧箭头时判断右侧箭头的显示
  87. this.maxClickNum = this.clickNum;
  88. }
  89. // 如果最后一个元素距离左侧的距离小于于可视距离,需要隐藏右侧箭头
  90. let timer = setTimeout(() => {
  91. // 重新:获取最后一个元素距离左侧的距离
  92. let lastItemOffsetLeft2 = this.childrenList[this.childrenList.length - 1].offsetLeft;
  93. console.log('lastItemOffsetLeft2-新的->', lastItemOffsetLeft2);
  94. if(lastItemOffsetLeft2 + lastWidth <= lookWidth) {
  95. this.showRightIcon = false;
  96. }
  97. clearTimeout(timer);
  98. }, 200);
  99. }
  100. },
  101. // 点击左箭头(右侧滚动)
  102. handleLeftClick() {
  103. // 当点击次数大于0时才触发,这样当点击次数clickNum等于1的到时候,clickNum--等于0.根据计算属性的判断会隐藏掉左箭头
  104. if (this.clickNum > 0) {
  105. // 获取当前元素宽度
  106. let width = this.childrenList[this.clickNum - 1].getBoundingClientRect().width;
  107. // 公示:滚动距离(元素的magin-left值) = 它自己的长度 + 上一次滑动的距离
  108. this.$refs.swiperScrollContent.style.marginLeft = `${this.lastLeft + width}px`
  109. this.lastLeft = width + this.lastLeft;
  110. // 点击次数-1
  111. this.clickNum--;
  112. // 如果点击次数小于最大点击次数,说明最后一个元素已经不在可是区域内了,显示右箭头
  113. if (this.clickNum < this.maxClickNum) {
  114. this.showRightIcon = true;
  115. }
  116. }
  117. }
  118. }
  119. }
  120. </script>
  121. <style lang='scss' scoped>
  122. .left-right-swiper-scroll-box {
  123. position: relative;
  124. display: flex;
  125. width: 1145px;
  126. overflow: hidden;
  127. transition: all 0.3s;
  128. padding: 0 30px;
  129. margin-right: 5px;
  130. .scroll-icon {
  131. position: absolute;
  132. top: 0;
  133. width: 30px;
  134. height: 70px;
  135. z-index: 9;
  136. cursor: pointer;
  137. background-image: linear-gradient(270deg, invalid gradient);
  138. z-index: 1000;
  139. i {
  140. position: absolute;
  141. top: 5px;
  142. width: 20px;
  143. height: 20px;
  144. }
  145. &.left-icon {
  146. left: 0;
  147. background: url("~@/assets/images/img-mask-left.png") 0 0 no-repeat;
  148. // i {
  149. // left: 0;
  150. // background: url("~@/assets/images/icon-arrow-left.png") 0 0 no-repeat;
  151. // }
  152. }
  153. &.left-icon:hover{
  154. left: 0;
  155. background: url("~@/assets/images/icon-arrow-left.png") 0 0 no-repeat;
  156. }
  157. &.right-icon {
  158. right: 0;
  159. background: url("~@/assets/images/img-mask-right.png") 0 0 no-repeat;
  160. // i {
  161. // right: 0;
  162. // background: url("~@/assets/images/icon-arrow-right.png") 0 0 no-repeat;
  163. // }
  164. }
  165. &.right-icon:hover {
  166. right: 0;
  167. background: url("~@/assets/images/icon-arrow-right.png") 0 0 no-repeat;
  168. }
  169. }
  170. .swiper-scroll-content {
  171. width: fit-content;
  172. display: flex;
  173. flex-wrap: nowrap;
  174. white-space: nowrap;
  175. transition: all 0.3s;
  176. }
  177. }
  178. </style>