index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <div class="tabSwiperWarpAll">
  3. <div class="tabwarp" ref="tabwarp">
  4. <slot name="tab"></slot>
  5. </div>
  6. <div
  7. class="tabSwiperWarp"
  8. ref="swiper"
  9. @touchstart="touchstart"
  10. @touchmove="touchmove"
  11. @touchend="touchend"
  12. >
  13. <div class="transwarp" :style="{left:loop?-pageWidth+'px':0}" ref="transwarp">
  14. <slot name="content"></slot>
  15. </div>
  16. </div>
  17. </div>
  18. </template>
  19. <script>
  20. export default {
  21. name: "tabSwiperWarp",
  22. props: {
  23. loop: {
  24. type: Boolean,
  25. default() {
  26. return false;
  27. }
  28. }
  29. },
  30. data() {
  31. return {
  32. originalPos: 0,
  33. pageWidth: 100,
  34. currentIndex :0,
  35. };
  36. },
  37. created() {},
  38. mounted() {
  39. this.pageWidth = this.$refs.swiper.offsetWidth;
  40. this.transwarpDom = this.$refs.transwarp;
  41. if (this.loop) {
  42. let firstNode = this.transwarpDom.firstChild.cloneNode(true);
  43. let lastNode = this.transwarpDom.lastChild.cloneNode(true);
  44. this.transwarpDom.appendChild(firstNode);
  45. this.transwarpDom.insertBefore(lastNode, this.transwarpDom.childNodes[0]);
  46. }
  47. this.domlen = this.transwarpDom.querySelectorAll(".swiperItem").length;
  48. this.activeTab();
  49. this.addActiveTab(0)
  50. },
  51. methods: {
  52. activeTab() {
  53. this.$refs.tabwarp
  54. .querySelectorAll(".swiperTab")
  55. .forEach((item, index) => {
  56. item.indexs = index;
  57. });
  58. this.$refs.tabwarp.querySelectorAll(".swiperTab").forEach((target,index)=>{
  59. target.addEventListener(
  60. "click",
  61. e => {
  62. let distance = 0;
  63. this.addActiveTab(target.indexs)
  64. if (this.loop) {
  65. distance = target.indexs * this.pageWidth;
  66. } else {
  67. distance = (target.indexs - 1) * this.pageWidth;
  68. }
  69. this.transwarpDom.style.transform = `translate3d(${-distance}px,0px,0px)`;
  70. this.transwarpDom.style.transition = "transform .3s";
  71. },
  72. false
  73. );
  74. })
  75. },
  76. touchstart(e) {
  77. this.originalPos = e.touches[0].pageX;
  78. const transform = this.transwarpDom.style.transform;
  79. this.originalLeft = Number(
  80. transform ? transform.split("(")[1].split("px")[0] : 0
  81. );
  82. },
  83. touchmove(e) {
  84. let moveDistance = e.touches[0].pageX - this.originalPos; // >0 右滑,<0 左滑
  85. this.slideTo(moveDistance, false);
  86. },
  87. touchend(e) {
  88. let moveDistance = e.changedTouches[0].pageX - this.originalPos; // >0 右滑,<0 左滑
  89. const transform = this.transwarpDom.style.transform;
  90. let currentLeft = Number(
  91. transform ? transform.split("(")[1].split("px")[0] : 0
  92. );
  93. if (
  94. Math.abs(moveDistance) > this.pageWidth / 3 &&
  95. (this.loop ||
  96. (moveDistance > 0 && currentLeft < 0) ||
  97. (moveDistance < 0 &&
  98. Math.abs(currentLeft) <
  99. (this.transwarpDom.querySelectorAll(".tabItem").length - 1) *
  100. this.pageWidth))
  101. ) {
  102. // 滑动距离大于阙值,且内容在边界内时,滑动一整页
  103. let distance = moveDistance > 0 ? this.pageWidth : -this.pageWidth;
  104. this.slideTo(distance, true);
  105. } else {
  106. this.slideTo(0, true); //回到远处
  107. }
  108. },
  109. /**
  110. * 滑动方法
  111. * @param {Number} distance 滑动距离
  112. * @param {Boolean} delay 轮播切换
  113. */
  114. slideTo(distance, delay = false) {
  115. let alldistance = this.originalLeft + distance;
  116. this.transwarpDom.style.transform = `translate3d(${alldistance}px,0px,0px)`;
  117. this.transwarpDom.style.transition = delay ? "transform .3s" : "initial";
  118. if (this.loop && delay) {
  119. if (Math.abs(alldistance) > (this.domlen - 3) * this.pageWidth) {
  120. setTimeout(() => {
  121. this.slideTo((this.domlen - 3) * this.pageWidth);
  122. this.currentIndex = 0
  123. this.addActiveTab(this.currentIndex)
  124. }, 300);
  125. } else if (alldistance > 0) {
  126. setTimeout(() => {
  127. this.slideTo(-(this.domlen - 3) * this.pageWidth);
  128. this.currentIndex = this.domlen - 3
  129. this.addActiveTab(this.currentIndex)
  130. }, 300);
  131. }else{
  132. this.currentIndex = alldistance > 0 ? (this.domlen - 3):-alldistance/this.pageWidth
  133. this.addActiveTab(this.currentIndex)
  134. }
  135. }else if(delay){
  136. this.currentIndex = -alldistance/this.pageWidth
  137. this.addActiveTab(this.currentIndex)
  138. }
  139. },
  140. addActiveTab(tabindex){
  141. if(this.$refs.tabwarp.querySelectorAll(".swiperTab").length>0){
  142. this.$refs.tabwarp.querySelectorAll(".swiperTab").forEach((item,index)=>{
  143. item.classList.remove('active')
  144. })
  145. this.$refs.tabwarp.querySelectorAll(".swiperTab")[tabindex].classList.add('active')
  146. }
  147. }
  148. }
  149. };
  150. </script>
  151. <style scoped>
  152. .tabSwiperWarp {
  153. width: 100%;
  154. overflow: hidden;
  155. }
  156. .transwarp {
  157. font-size: 0;
  158. transform: translate3d(0px, 0, 0);
  159. white-space: nowrap;
  160. display: inline-block;
  161. /* padding: 40px 0px; */
  162. box-sizing: border-box;
  163. width: 100%;
  164. position: relative;
  165. }
  166. .swiperTab {
  167. /* position: relative; */
  168. display: inline-block;
  169. text-align: center;
  170. font-size: 14px;
  171. padding: 0 10px;
  172. }
  173. .tabwarp {
  174. display: inline-block;
  175. text-align: left;
  176. }
  177. </style>