index.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. Component({
  2. properties: {
  3. list: {
  4. type: Array,
  5. value: []
  6. },
  7. // 是否展示指示器
  8. showIndicators: {
  9. type: Boolean,
  10. value: true
  11. },
  12. // 左右边距(px)
  13. paddingLR: {
  14. type: Number,
  15. value: 30
  16. },
  17. // 中间卡片高度(px)
  18. centerHeight: {
  19. type: Number,
  20. value: 200
  21. },
  22. // 左右两侧卡片高度(px)
  23. sideHeight: {
  24. type: Number,
  25. value: 130
  26. },
  27. duration: {
  28. type: Number,
  29. value: 300
  30. },
  31. // 当前项索引
  32. current: {
  33. type: Number,
  34. value: 0
  35. },
  36. // 是否使用 navigator 进行跳转(仅当前项且有 url)
  37. useNavigator: {
  38. type: Boolean,
  39. value: true
  40. },
  41. onlineIcon: {
  42. type: String,
  43. value: 'https://klmybwg.4dage.com/mini/wxImg/exhibition/online-kz.png'
  44. },
  45. // 是否自动轮播
  46. autoplay: {
  47. type: Boolean,
  48. value: false
  49. },
  50. // 轮播间隔时间(毫秒)
  51. interval: {
  52. type: Number,
  53. value: 3000
  54. }
  55. },
  56. data: {
  57. preloadedImages: {},
  58. autoplayTimer: null, // 自动轮播定时器
  59. isUserInteracting: false // 用户是否正在交互
  60. },
  61. observers: {
  62. 'list': function(newList) {
  63. if (newList && newList.length > 0) {
  64. this.preloadImages(newList);
  65. // 当列表数据更新时,重新启动自动轮播
  66. this.restartAutoplay();
  67. }
  68. },
  69. 'autoplay, interval': function(autoplay, interval) {
  70. // 当自动轮播设置改变时,重新启动
  71. if (autoplay) {
  72. this.startAutoplay();
  73. } else {
  74. this.stopAutoplay();
  75. }
  76. }
  77. },
  78. lifetimes: {
  79. attached() {
  80. if (this.data.list && this.data.list.length > 0) {
  81. this.preloadImages(this.data.list);
  82. }
  83. // 组件初始化时启动自动轮播
  84. if (this.data.autoplay) {
  85. this.startAutoplay();
  86. }
  87. },
  88. detached() {
  89. // 组件销毁时清理定时器
  90. this.stopAutoplay();
  91. }
  92. },
  93. pageLifetimes: {
  94. show() {
  95. // 页面显示时重启自动轮播
  96. if (this.data.autoplay && !this.data.isUserInteracting) {
  97. this.startAutoplay();
  98. }
  99. },
  100. hide() {
  101. // 页面隐藏时停止自动轮播
  102. this.stopAutoplay();
  103. }
  104. },
  105. methods: {
  106. // 预加载图片
  107. preloadImages(list) {
  108. const preloadedImages = {};
  109. list.forEach((item, index) => {
  110. if (item.image && !this.data.preloadedImages[item.image]) {
  111. // 创建图片对象进行预加载
  112. // const img = wx.createOffscreenCanvas().getContext('2d');
  113. preloadedImages[item.image] = true;
  114. }
  115. });
  116. // 同时预加载在线观展图标
  117. if (this.data.onlineIcon && !this.data.preloadedImages[this.data.onlineIcon]) {
  118. // const img = wx.createOffscreenCanvas().getContext('2d');
  119. preloadedImages[this.data.onlineIcon] = true;
  120. }
  121. this.setData({
  122. preloadedImages: { ...this.data.preloadedImages, ...preloadedImages }
  123. });
  124. },
  125. onSwiperChange(e) {
  126. const index = e.detail.current;
  127. this.setData({ current: index });
  128. this.triggerEvent('change', { current: index });
  129. // swiper滑动时暂停自动轮播一段时间
  130. this.pauseAutoplayTemporarily();
  131. },
  132. // 左右图片可点击切换,不可跳转
  133. onSlideTap(e) {
  134. const index = e.currentTarget.dataset.index;
  135. if (index === this.data.current) return; // 当前项点击保持
  136. this.setData({ current: index });
  137. this.triggerEvent('change', { current: index });
  138. // 用户点击切换时暂停自动轮播一段时间
  139. this.pauseAutoplayTemporarily();
  140. },
  141. // 当前项且无 url 的点击,向外抛事件处理
  142. onCurrentTap(e) {
  143. const index = e.currentTarget.dataset.index;
  144. const item = this.data.list[index];
  145. this.triggerEvent('exhibitiontap', { item, index });
  146. },
  147. // 线上观展点击事件(有URL的情况)
  148. onOnlineExhibitionTap(e) {
  149. const index = e.currentTarget.dataset.index;
  150. const item = this.data.list[index];
  151. this.triggerEvent('onlineexhibitiontap', { item, index, url: item.url });
  152. },
  153. onDotTap(e) {
  154. const index = e.currentTarget.dataset.index;
  155. this.setData({ current: index });
  156. this.triggerEvent('change', { current: index });
  157. // 用户点击指示器时暂停自动轮播一段时间
  158. this.pauseAutoplayTemporarily();
  159. },
  160. // 启动自动轮播
  161. startAutoplay() {
  162. if (!this.data.autoplay || this.data.list.length <= 1) {
  163. return;
  164. }
  165. this.stopAutoplay(); // 先清除可能存在的定时器
  166. const timer = setInterval(() => {
  167. if (!this.data.isUserInteracting) {
  168. const nextIndex = (this.data.current + 1) % this.data.list.length;
  169. this.setData({ current: nextIndex });
  170. this.triggerEvent('change', { current: nextIndex });
  171. }
  172. }, this.data.interval);
  173. this.setData({ autoplayTimer: timer });
  174. },
  175. // 停止自动轮播
  176. stopAutoplay() {
  177. if (this.data.autoplayTimer) {
  178. clearInterval(this.data.autoplayTimer);
  179. this.setData({ autoplayTimer: null });
  180. }
  181. },
  182. // 重启自动轮播
  183. restartAutoplay() {
  184. if (this.data.autoplay) {
  185. this.stopAutoplay();
  186. this.startAutoplay();
  187. }
  188. },
  189. // 暂时暂停自动轮播(用户交互时)
  190. pauseAutoplayTemporarily(duration = 3000) {
  191. if (!this.data.autoplay) return;
  192. this.setData({ isUserInteracting: true });
  193. this.stopAutoplay();
  194. setTimeout(() => {
  195. this.setData({ isUserInteracting: false });
  196. if (this.data.autoplay) {
  197. this.startAutoplay();
  198. }
  199. }, duration);
  200. }
  201. }
  202. });