珠宝小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
5.0 KiB

2 months ago
  1. <template>
  2. <view class="swiper-item" ref="swiper_item" :style="itemStyle">
  3. <view class="item-cntent" bubble="true" @click.stop="onClick"><slot></slot></view>
  4. </view>
  5. </template>
  6. <script>
  7. import { getStyleStr } from '../../utils/style.js';
  8. // #ifdef APP-NVUE
  9. const animation = uni.requireNativePlugin('animation');
  10. // #endif
  11. /**
  12. * esc-swiper-item
  13. * @description esc-swiper-item (不支持使用class)
  14. * @property {Number} index 索引(必填)
  15. * @property {Boolean} clickAny 可以点击任意项
  16. * @event {Function} click 点击事件
  17. */
  18. export default {
  19. name: 'esc-swiper-item',
  20. inject: ['config'],
  21. props: {
  22. index: {
  23. type: Number,
  24. default: 0
  25. },
  26. clickAny: {
  27. type: Boolean,
  28. default: false
  29. }
  30. },
  31. data() {
  32. return {
  33. isAnimated: false,
  34. timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
  35. duration: 0,
  36. current: 0,
  37. position: 0,
  38. mScale: 0,
  39. canClick: true
  40. };
  41. },
  42. created() {},
  43. computed: {
  44. size() {
  45. return this.config.size;
  46. },
  47. width() {
  48. return this.config.width;
  49. },
  50. height() {
  51. return this.config.height;
  52. },
  53. itemWidth() {
  54. return this.config.itemWidth;
  55. },
  56. itemHeight() {
  57. return this.config.itemHeight;
  58. },
  59. space() {
  60. return this.config.space;
  61. },
  62. itemStyle() {
  63. if (this.index == this.size - 1) {
  64. return this.rightSpaceStyle();
  65. } else if (this.index == this.size - 2) {
  66. return this.centerSpaceStyle();
  67. } else {
  68. return this.leftSpaceStyle();
  69. }
  70. },
  71. scale() {
  72. if (!this.config.is3D) {
  73. return 1;
  74. }
  75. if (this.myCurrent == this.current) {
  76. return this.mScale || this.config.scale;
  77. } else {
  78. return this.mScale || 1;
  79. }
  80. },
  81. // 当前swiper-item所属current索引
  82. myCurrent() {
  83. if (!this.config.isCircular) {
  84. return this.index;
  85. }
  86. const p = this.index;
  87. const plus = this.config.plus;
  88. const actSize = this.size - plus * 2;
  89. let current = 0;
  90. if (p < plus) {
  91. current = p + (actSize - plus);
  92. } else if (p >= this.size - plus) {
  93. current = p - (actSize + plus);
  94. } else {
  95. current = p - plus;
  96. }
  97. return current;
  98. }
  99. },
  100. methods: {
  101. itemSize() {
  102. let style = {
  103. width: this.itemWidth + 'rpx',
  104. height: (this.itemHeight || this.height) + 'rpx'
  105. };
  106. if (this.config.is3D) {
  107. // #ifndef APP-NVUE
  108. if (this.isAnimated) {
  109. style.transition = 'transform ' + this.duration + 'ms ' + this.timingFunction;
  110. } else {
  111. style.transition = '';
  112. }
  113. style.transform = 'scale(' + this.scale + ')';
  114. // #endif
  115. // #ifdef APP-NVUE
  116. const isIOS = uni.getSystemInfoSync().platform == 'ios';
  117. if (isIOS) {
  118. style.transform = 'scale(' + this.scale + ')';
  119. } else {
  120. if (!this.isAnimated) style.transform = 'scale(' + this.scale + ')';
  121. }
  122. // #endif
  123. }
  124. return style;
  125. },
  126. leftSpaceStyle() {
  127. return getStyleStr({
  128. ...this.itemSize(),
  129. marginLeft: this.space + 'rpx'
  130. });
  131. },
  132. centerSpaceStyle() {
  133. return getStyleStr({
  134. ...this.itemSize(),
  135. marginLeft: this.space + 'rpx',
  136. marginRight: this.space + 'rpx'
  137. });
  138. },
  139. rightSpaceStyle() {
  140. return getStyleStr({
  141. ...this.itemSize(),
  142. marginRight: this.space + 'rpx'
  143. });
  144. },
  145. onClick(e) {
  146. if (!this.canClick) {
  147. return;
  148. }
  149. // #ifdef APP-NVUE
  150. e.stopPropagation();
  151. // #endif
  152. // 点击任意项
  153. if (this.clickAny) {
  154. this.$emit('click', e);
  155. return;
  156. }
  157. // 只能点击当前项
  158. if (this.myCurrent == this.current) {
  159. this.$emit('click', e);
  160. }
  161. },
  162. restoreScale(duration) {
  163. if (!this.config.is3D) {
  164. return;
  165. }
  166. // #ifndef APP-NVUE
  167. this.duration = duration;
  168. this.isAnimated = true;
  169. this.mScale = 0;
  170. setTimeout(() => {
  171. this.duration = 0;
  172. this.isAnimated = false;
  173. }, duration);
  174. // #endif
  175. // #ifdef APP-NVUE
  176. this.isAnimated = true;
  177. this.mScale = 0;
  178. animation.transition(
  179. this.$refs['swiper_item'].ref,
  180. {
  181. styles: {
  182. transform: 'scale(' + this.scale + ')'
  183. },
  184. duration, //ms
  185. timingFunction: this.timingFunction,
  186. needLayout: false,
  187. delay: 0 //ms
  188. },
  189. () => {
  190. this.isAnimated = false;
  191. }
  192. );
  193. // #endif
  194. },
  195. restoreToScale(scale, duration) {
  196. if (!this.config.is3D) {
  197. return;
  198. }
  199. // #ifndef APP-NVUE
  200. this.duration = duration;
  201. this.isAnimated = true;
  202. this.mScale = scale;
  203. setTimeout(() => {
  204. this.duration = 0;
  205. this.isAnimated = false;
  206. this.mScale = 0;
  207. }, duration);
  208. // #endif
  209. // #ifdef APP-NVUE
  210. this.isAnimated = true;
  211. animation.transition(
  212. this.$refs['swiper_item'].ref,
  213. {
  214. styles: {
  215. transform: 'scale(' + scale + ')'
  216. },
  217. duration, //ms
  218. timingFunction: this.timingFunction,
  219. needLayout: false,
  220. delay: 0 //ms
  221. },
  222. () => {
  223. this.isAnimated = false;
  224. this.mScale = 0;
  225. }
  226. );
  227. // #endif
  228. }
  229. }
  230. };
  231. </script>
  232. <style scoped>
  233. .swiper-item {
  234. position: relative;
  235. }
  236. .item-cntent {
  237. position: absolute;
  238. top: 0;
  239. right: 0;
  240. bottom: 0;
  241. left: 0;
  242. /* #ifndef APP-NVUE */
  243. display: flex;
  244. /* #endif */
  245. }
  246. </style>