浏览代码

feat(imagepreview): 增加自动轮播功能;增加放大缩小功能 (#908)

* fix: 样式冲突问题修复

* fix: 文档修改ImagePreview

* fix: 文档修复ImagePreview,体现taro

* upd: imagepreview组件优化

* feat: searchbar 组件启动开发

* feat: searchbar 开发初步完成;迁移至taro

* feat: searchbar 适配 taro

* upd: imageprevie import 优化

* upd: searchbar 外套form,对外暴露 input-type

* fix: imagepreview 引入 swiper 报错问题修复

* fix: 修复 searchbar 的一些问题;扩充文档内容,使描述更详细

* fix: searchbar 样式微调

* upd: imagepreview 点击轮播区域会关闭弹层

* upd: searchbar 1.props暴露背景样式2.slot使用优化3.sass变量命名优化

* docs: 背景样式增加默认值

* upd: imagepreview 引入video展示功能开发

* upd: 图片预览完善

* docs: imapgepreview 文档修改

* docs: imagepreview taro 文档完成

* docs: event close 调整

* feat: 图片预览新增自动轮播功能;新增放大缩小功能

Co-authored-by: richard1015 <51844712@qq.com>
JackieScorpio 4 年之前
父节点
当前提交
f8d66f2a1b

+ 1 - 1
src/packages/__VUE/card/demo.vue

@@ -63,7 +63,7 @@
       <template #origin>
       <template #origin>
         <img
         <img
           class="tag"
           class="tag"
-          src="//img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
+          src="https://img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
           alt=""
           alt=""
         />
         />
       </template>
       </template>

+ 1 - 1
src/packages/__VUE/card/doc.md

@@ -58,7 +58,7 @@ app.use(Card);
   <template #tag>
   <template #tag>
     <img
     <img
         class="tag" 
         class="tag" 
-        src="//img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
+        src="https://img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
         alt=""
         alt=""
     />
     />
   </template>
   </template>

+ 2 - 0
src/packages/__VUE/imagepreview/doc.md

@@ -286,11 +286,13 @@ export default {
 | show | 是否展示预览图片 | Boolean | false
 | show | 是否展示预览图片 | Boolean | false
 | videos | 预览的视频数组(视频自动放到图片之前) | Array<`Object`> | []
 | videos | 预览的视频数组(视频自动放到图片之前) | Array<`Object`> | []
 | images | 预览图片数组 | Array<`String`> | []
 | images | 预览图片数组 | Array<`String`> | []
+| autoplay | 自动轮播时长,0表示不会自动轮播 | Number、String  | 3000  |
 | init-no | 初始页码 | Number | 1
 | init-no | 初始页码 | Number | 1
 | pagination-visible | 分页指示器是否展示    | Boolean | false |
 | pagination-visible | 分页指示器是否展示    | Boolean | false |
 | pagination-color   | 分页指示器选中的颜色    | String  | '#fff'  |
 | pagination-color   | 分页指示器选中的颜色    | String  | '#fff'  |
 | content-close   | 点击图片可以退出预览    | Boolean  | false  |
 | content-close   | 点击图片可以退出预览    | Boolean  | false  |
 
 
+
     
     
 ### Events
 ### Events
 
 

+ 1 - 0
src/packages/__VUE/imagepreview/index.scss

@@ -13,6 +13,7 @@
 
 
   &-index {
   &-index {
     position: fixed;
     position: fixed;
+    z-index: 2002;
     top: 50px;
     top: 50px;
     text-align: center;
     text-align: center;
     left: 0;
     left: 0;

+ 131 - 6
src/packages/__VUE/imagepreview/index.vue

@@ -1,9 +1,9 @@
 <template>
 <template>
-  <nut-popup pop-class="custom-pop" v-model:visible="showPop" @click="onClose">
-    <view class="nut-imagepreview" @click.stop="closeOnImg">
+  <nut-popup pop-class="custom-pop" v-model:visible="showPop" @click="onClose" style="width: 100%">
+    <view class="nut-imagepreview" @click.stop="closeOnImg" @touchstart.capture="onTouchStart">
       <nut-swiper
       <nut-swiper
         v-if="showPop"
         v-if="showPop"
-        :auto-play="3000"
+        :auto-play="autoplay"
         class="nut-imagepreview-swiper"
         class="nut-imagepreview-swiper"
         :loop="true"
         :loop="true"
         :is-preventDefault="false"
         :is-preventDefault="false"
@@ -20,8 +20,8 @@
           <img :src="item.src" class="nut-imagepreview-img" />
           <img :src="item.src" class="nut-imagepreview-img" />
         </nut-swiper-item>
         </nut-swiper-item>
       </nut-swiper>
       </nut-swiper>
-      <view class="nut-imagepreview-index"> {{ active }} / {{ images.length + videos.length }} </view>
     </view>
     </view>
+    <view class="nut-imagepreview-index"> {{ active }} / {{ images.length + videos.length }} </view>
   </nut-popup>
   </nut-popup>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
@@ -62,6 +62,10 @@ export default create({
     paginationColor: {
     paginationColor: {
       type: String,
       type: String,
       default: '#fff'
       default: '#fff'
+    },
+    autoplay: {
+      type: [Number, String],
+      default: 3000
     }
     }
   },
   },
   emits: ['close'],
   emits: ['close'],
@@ -86,7 +90,13 @@ export default create({
       options: {
       options: {
         muted: true,
         muted: true,
         controls: true
         controls: true
-      }
+      },
+      eleImg: null,
+      store: {
+        scale: 1,
+        moveable: false
+      },
+      lastTouchEndTime: 0 // 用来辅助监听双击
     });
     });
 
 
     const slideChangeEnd = function (page: number) {
     const slideChangeEnd = function (page: number) {
@@ -102,14 +112,124 @@ export default create({
 
 
     const onClose = () => {
     const onClose = () => {
       state.showPop = false;
       state.showPop = false;
+      state.store.scale = 1;
+      scaleNow();
       state.active = 1;
       state.active = 1;
       emit('close');
       emit('close');
     };
     };
 
 
+    // 计算两个点的距离
+    const getDistance = (first: any, second: any) => {
+      // 计算两个点起始时刻的距离和终止时刻的距离,终止时刻距离变大了则放大,变小了则缩小
+      // 放大 k 倍则 scale 也 扩大 k 倍
+      return Math.hypot(Math.abs(second.x - first.x), Math.abs(second.y - first.y));
+    };
+
+    const scaleNow = () => {
+      (state.eleImg as any).style.transform = 'scale(' + state.store.scale + ')';
+    };
+
+    const onTouchStart = (event: any) => {
+      console.log('start');
+      // 如果已经放大,双击应变回原尺寸;如果是原尺寸,双击应放大
+      const curTouchTime = new Date().getTime();
+      if (curTouchTime - state.lastTouchEndTime < 300) {
+        const store = state.store;
+        if (store.scale > 1) {
+          store.scale = 1;
+        } else if (store.scale == 1) {
+          store.scale = 2;
+        }
+        scaleNow();
+      }
+
+      var touches = event.touches;
+      var events = touches[0];
+      var events2 = touches[1];
+
+      // event.preventDefault();
+
+      const store = state.store as any;
+      store.moveable = true;
+
+      if (events2) {
+        // 如果开始两指操作,记录初始时刻两指间的距离
+        store.oriDistance = getDistance(
+          {
+            x: events.pageX,
+            y: events.pageY
+          },
+          {
+            x: events2.pageX,
+            y: events2.pageY
+          }
+        );
+      }
+      // 取到开始两指操作时的放大(缩小比例),store.scale 存储的是当前的放缩比(相对于标准大小 scale 为 1 的情况的放大缩小比)
+      store.originScale = store.scale || 1;
+    };
+
+    const onTouchMove = (event: any) => {
+      if (!state.store.moveable) {
+        return;
+      }
+      const store = state.store as any;
+      // event.preventDefault();
+      var touches = event.touches;
+      var events = touches[0];
+      var events2 = touches[1];
+      // 双指移动
+      if (events2) {
+        // 获得当前两点间的距离
+        const curDistance = getDistance(
+          {
+            x: events.pageX,
+            y: events.pageY
+          },
+          {
+            x: events2.pageX,
+            y: events2.pageY
+          }
+        );
+
+        /** 此处计算倍数,距离放大(缩小) k 倍则 scale 也 扩大(缩小) k 倍。距离放大(缩小)倍数 = 结束时两点距离 除以 开始时两点距离
+         * 注意此处的 scale 变化是基于 store.scale 的。
+         * store.scale 是一个暂存值,比如第一次放大 2 倍,则 store.scale 为 2。
+         * 再次两指触碰的时候,store.originScale 就为 store.scale 的值,基于此时的 store.scale 继续放大缩小。 **/
+        const curScale = curDistance / store.oriDistance;
+        store.scale = store.originScale * curScale;
+
+        // 最大放大 3 倍,缩小后松手要弹回原比例
+        if (store.scale > 3) {
+          store.scale = 3;
+        }
+        scaleNow();
+      }
+    };
+
+    const onTouchEnd = () => {
+      console.log('end');
+      state.lastTouchEndTime = new Date().getTime();
+      const store = state.store as any;
+      store.moveable = false;
+      if ((store.scale < 1.1 && store.scale > 1) || store.scale < 1) {
+        store.scale = 1;
+        scaleNow();
+      }
+    };
+
+    const init = () => {
+      state.eleImg = document.querySelector('.nut-imagepreview') as any;
+      document.addEventListener('touchmove', onTouchMove);
+      document.addEventListener('touchend', onTouchEnd);
+      document.addEventListener('touchcancel', onTouchEnd);
+    };
+
     watch(
     watch(
       () => props.show,
       () => props.show,
       (val) => {
       (val) => {
         state.showPop = val;
         state.showPop = val;
+        init();
       }
       }
     );
     );
 
 
@@ -124,7 +244,12 @@ export default create({
       ...toRefs(state),
       ...toRefs(state),
       slideChangeEnd,
       slideChangeEnd,
       onClose,
       onClose,
-      closeOnImg
+      closeOnImg,
+      onTouchStart,
+      onTouchMove,
+      onTouchEnd,
+      getDistance,
+      scaleNow
     };
     };
   }
   }
 });
 });

+ 1 - 1
src/sites/mobile-taro/vue/src/business/pages/card/index.vue

@@ -49,7 +49,7 @@
       <template #tag>
       <template #tag>
         <img
         <img
           class="tag"
           class="tag"
-          src="//img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
+          src="https://img11.360buyimg.com/jdphoto/s58x28_jfs/t9451/359/415622649/15318/b0943e5d/59a78495N3bd2a9f8.png"
           alt=""
           alt=""
         />
         />
       </template>
       </template>