自主产品,供应链食堂系统。将两个端拆开了。
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.

220 lines
5.9 KiB

  1. <template>
  2. <view>
  3. <swiper class="swiper" :animation="animationData"
  4. :style="{'background-color': perspective ? 'rgba(0,0,0,0.5)' : '#000000'}"
  5. :current="swiper_current" :circular="circular"
  6. v-if="show_assembly" @click="hideAssembly"
  7. @touchmove.stop.prevent="touchmove"
  8. @change="e => switchItem(e.detail.current)">
  9. <swiper-item v-for="(item, index) in images" :key="index"
  10. class="swiper-item">
  11. <!-- 可移动缩放操作的容器 -->
  12. <movable-area class="movable-area" :scale-area="true">
  13. <movable-view class="movable-view" direction="all" :scale="true" :inertia="true" @scale="scale" :scale-value="scale_values[swiper_current]">
  14. <image :src="item" class="swiper-image" mode="aspectFit" @mousewheel.stop="mousewheel"></image>
  15. </movable-view>
  16. </movable-area>
  17. <!-- 控制器 -->
  18. <view class="controls" v-if="controls">
  19. <view>
  20. <view @click.stop="switchItem(swiper_current - 1)" v-if="swiper_current != 0">
  21. <uni-icons type="arrowleft" size="36" color="#fff"></uni-icons>
  22. </view>
  23. <view v-else></view>
  24. </view>
  25. <view>
  26. <view @click.stop="switchItem(swiper_current + 1)" v-if="swiper_current != images.length - 1">
  27. <uni-icons type="arrowright" size="36" color="#fff"></uni-icons>
  28. </view>
  29. <view v-else></view>
  30. </view>
  31. </view>
  32. <!-- 指示器 -->
  33. <view class="indicators" v-if="indicators && images.length > 1">
  34. <view class="number" v-if="indicatorType == 'number'">{{ swiper_current + 1 }} / {{ images.length }}</view>
  35. <view class="square" v-else-if="indicatorType == 'square'">
  36. <view v-for="(item, index) in images" :key="index" class="indicators-icon" :style="swiper_current == index ? 'background-color:'+ themeColor : ''"></view>
  37. </view>
  38. <view class="dot" v-else-if="indicatorType == 'dot'">
  39. <view v-for="(item, index) in images" :key="index" class="indicators-icon" :style="swiper_current == index ? 'background-color:'+ themeColor : ''"></view>
  40. </view>
  41. </view>
  42. </swiper-item>
  43. </swiper>
  44. </view>
  45. </template>
  46. <script>
  47. export default {
  48. props: {
  49. controls: {
  50. type: Boolean, // 是否显示左右箭头控制
  51. default: true
  52. },
  53. indicators: {
  54. type: Boolean,
  55. default: true // 是否显示指示器
  56. },
  57. indicatorType: {
  58. type: String, // 指示器类型,dot圆点,square方形,number数字
  59. default: 'number'
  60. },
  61. perspective: {
  62. type: Boolean, // 是否开启背景透视,遮罩透明可以看见底下其他元素
  63. default: true
  64. },
  65. circular: {
  66. type: Boolean, // 是否可以衔接滑动
  67. default: false
  68. },
  69. themeColor: {
  70. type: String, // 主题色
  71. default: '#1833F2'
  72. }
  73. },
  74. data(){
  75. return {
  76. swiper_current: 0, // 当前显示的图片下标
  77. images: [],
  78. show_assembly: false, // 显示预览图片
  79. duration: 500, // 动画持续时间
  80. animation: {}, // 动画配置对象
  81. animationData: {}, // 动画导出执行对象
  82. scale_values: [], // 每张图的缩放比例
  83. clientY: 0
  84. }
  85. },
  86. created(){
  87. // TODO PC端屏蔽遮罩滚动穿透
  88. // TODO PC端滚轮放大缩小
  89. // TODO 放大缩小百分比显示
  90. // TODO 双击时会被关掉
  91. },
  92. methods: {
  93. // 初始化加载动画
  94. initAnimation(){
  95. let animation = uni.createAnimation({
  96. duration: this.duration
  97. });
  98. this.animation = animation;
  99. animation.opacity(0).step();
  100. animation.opacity(1).step();
  101. this.animationData = animation.export();
  102. },
  103. // swiper touchmove事件
  104. touchmove(){
  105. return false;
  106. },
  107. // swiper被改变
  108. switchItem(current){
  109. this.swiper_current = current;
  110. // this.clientY = 0; // 切换时需要复位
  111. },
  112. // movable 缩放事件
  113. scale(event){
  114. let scale = event.detail.scale;
  115. this.$msg(scale); // TODO 轻提示层级不够,没有被显示出来
  116. },
  117. // 鼠标滚动缩放事件,目前会触发浏览器页面滚动事件,暂时先不要这个功能
  118. mousewheel(event){
  119. return;
  120. let scale = this.scale_values[this.swiper_current];
  121. if(this.clientY > event.clientY){
  122. if(scale < 10){
  123. scale += 0.5;
  124. }
  125. }else{
  126. if(scale > 0.5){
  127. scale -= 0.5;
  128. }
  129. }
  130. this.clientY = event.clientY;
  131. this.scale_values.splice(this.swiper_current, 1, scale);
  132. },
  133. // 显示图片
  134. show(options){
  135. this.images = options.images || [];
  136. this.swiper_current = options.current || 0;
  137. this.scale_values = this.images.map(item => 1);
  138. this.show_assembly = true;
  139. this.initAnimation();
  140. },
  141. // 关闭隐藏图片
  142. hideAssembly(){
  143. this.animation.opacity(0).step();
  144. this.animationData = this.animation.export();
  145. setTimeout(() => {
  146. this.show_assembly = false;
  147. }, this.duration);
  148. }
  149. }
  150. }
  151. </script>
  152. <style lang="scss" scoped="scoped">
  153. .swiper{
  154. width: 100vw;
  155. height: 100vh;
  156. position: fixed;
  157. top: 0;
  158. left: 0;
  159. z-index: 1000;
  160. opacity: 0;
  161. .swiper-item{
  162. position: relative;
  163. .movable-area, .movable-view, .swiper-image{
  164. width: 100%;
  165. height: 100%;
  166. }
  167. .controls{
  168. position: absolute;
  169. padding: 0 16rpx;
  170. box-sizing: border-box;
  171. display: flex;
  172. justify-content: space-between;
  173. top: 42vh;
  174. left: 0;
  175. font-size: 40rpx;
  176. width: 100%;
  177. z-index: 1002;
  178. }
  179. .indicators{
  180. width: 100%;
  181. position: absolute;
  182. left: 0;
  183. bottom: 10vh;
  184. z-index: 1002;
  185. display: flex;
  186. justify-content: center;
  187. .number, .square, .dot{
  188. width: max-content;
  189. height: max-content;
  190. background-color: #dfe4ea;
  191. }
  192. .number{
  193. padding: 4rpx 26rpx;
  194. border-radius: 40rpx;
  195. color: #555555;
  196. }
  197. .square{
  198. border-radius: 40rpx;
  199. display: flex;
  200. padding: 2rpx 4rpx;
  201. view{
  202. border-radius: 50%;
  203. }
  204. }
  205. .dot{
  206. display: flex;
  207. padding: 4rpx 4rpx;
  208. }
  209. .indicators-icon{
  210. width: 20rpx;
  211. height: 20rpx;
  212. background-color: #bdc5bd;
  213. margin: 2rpx;
  214. }
  215. }
  216. }
  217. }
  218. </style>