Преглед на файлове

photo 添加 click 事件

MinJieLiu преди 7 години
родител
ревизия
668f088fa4
променени са 7 файла, в които са добавени 64 реда и са изтрити 8 реда
  1. 2 2
      package.json
  2. 1 1
      src/Photo.tsx
  3. 22 2
      src/PhotoSlider.tsx
  4. 21 1
      src/PhotoView.tsx
  5. 2 1
      src/components/TopWrap.tsx
  6. 14 0
      src/utils/throttle.ts
  7. 2 1
      tsconfig.json

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "react-photo-view",
-  "version": "0.1.7",
+  "version": "0.1.8",
   "description": "React photo preview.",
   "main": "./lib/index",
   "module": "./es/index",
@@ -52,7 +52,7 @@
     "react-dom": "^16.4.1"
   },
   "dependencies": {
-    "lodash.throttle": "^4.1.1",
+    "lodash.debounce": "^4.0.8",
     "lodash.uniqueid": "^4.0.1",
     "styled-components": "^3.0.1"
   }

+ 1 - 1
src/Photo.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import styled from 'styled-components';
-import throttle from 'lodash.throttle';
+import throttle from './utils/throttle';
 import Spinner from './components/Spinner';
 import getSuitableImageSize from './utils/getSuitableImageSize';
 

+ 22 - 2
src/PhotoSlider.tsx

@@ -51,6 +51,8 @@ type PhotoSliderState = {
   backdropOpacity: number;
   // 缩放度
   photoScale: number;
+  // 覆盖物可见度
+  overlayVisible: boolean;
 };
 
 export default class PhotoSlider extends React.Component<
@@ -84,6 +86,7 @@ export default class PhotoSlider extends React.Component<
       lastClientY: undefined,
       backdropOpacity: defaultOpacity,
       photoScale: 1,
+      overlayVisible: true,
     };
   }
 
@@ -100,6 +103,12 @@ export default class PhotoSlider extends React.Component<
     window.removeEventListener('resize', this.handleResize);
   }
 
+  handlePhotoClick = () => {
+    this.setState(prevState => ({
+      overlayVisible: !prevState.overlayVisible,
+    }));
+  }
+
   handleResize = () => {
     const { innerWidth } = window;
     this.setState(({ photoIndex }) => {
@@ -156,7 +165,12 @@ export default class PhotoSlider extends React.Component<
   handleReachUp = (clientX: number, clientY: number, touchType: TouchTypeEnum) => {
     const { innerWidth, innerHeight } = window;
     const { images, onIndexChange, onClose, maskClosable = true } = this.props;
-    const { lastClientX = clientX, lastClientY = clientY, photoIndex } = this.state;
+    const {
+      lastClientX = clientX,
+      lastClientY = clientY,
+      photoIndex,
+      overlayVisible,
+    } = this.state;
 
     const offsetClientX = clientX - lastClientX;
     const offsetClientY = clientY - lastClientY;
@@ -165,6 +179,7 @@ export default class PhotoSlider extends React.Component<
     // 当前偏移
     let currentTranslateX = -singlePageWidth * photoIndex;
     let currentPhotoIndex = photoIndex;
+    let isChangeVisible = false;
 
     // mask 点击事件
     if (lastClientX === clientX
@@ -172,8 +187,10 @@ export default class PhotoSlider extends React.Component<
       && maskClosable
       && touchType === TouchTypeEnum.Mask
     ) {
+      isChangeVisible = true;
       onClose();
     } else if (Math.abs(offsetClientY) > innerHeight * 0.14) {
+      isChangeVisible = true;
       onClose();
       // 下一张
     } else if (offsetClientX < -maxMoveOffset && photoIndex < images.length - 1) {
@@ -198,6 +215,7 @@ export default class PhotoSlider extends React.Component<
       lastClientY: undefined,
       backdropOpacity: defaultOpacity,
       photoScale: 1,
+      overlayVisible: isChangeVisible ? true : overlayVisible,
     });
   }
 
@@ -220,6 +238,7 @@ export default class PhotoSlider extends React.Component<
       photoIndex,
       backdropOpacity,
       photoScale,
+      overlayVisible,
     } = this.state;
     const imageLength = images.length;
     const transform = `translate3d(${translateX}px, 0px, 0)`;
@@ -233,7 +252,7 @@ export default class PhotoSlider extends React.Component<
             className={maskClassName}
             style={{ background: `rgba(0, 0, 0, ${backdropOpacity})` }}
           />
-          <TopBar>
+          <TopBar style={{ opacity: +overlayVisible }}>
             <Counter>{photoIndex + 1} / {imageLength}</Counter>
             <Close onClick={onClose} />
           </TopBar>
@@ -267,6 +286,7 @@ export default class PhotoSlider extends React.Component<
                     realIndex > 0 ? this.handleReachHorizontalMove : undefined
                   }
                   onReachUp={this.handleReachUp}
+                  onPhotoClick={this.handlePhotoClick}
                   photoScale={photoIndex === realIndex ? photoScale : 1}
                   wrapClassName={viewClassName}
                   className={imageClassName}

+ 21 - 1
src/PhotoView.tsx

@@ -1,8 +1,9 @@
 import React from 'react';
-import throttle from 'lodash.throttle';
+import debounce from 'lodash.debounce';
 import Photo from './Photo';
 import PhotoWrap from './components/PhotoWrap';
 import PhotoMask from './components/PhotoMask';
+import throttle from './utils/throttle';
 import isMobile from './utils/isMobile';
 import getMultipleTouchPosition from './utils/getMultipleTouchPosition';
 import getPositionOnMoveOrScale from './utils/getPositionOnMoveOrScale';
@@ -27,6 +28,8 @@ interface IPhotoViewProps {
   // 加载失败 Element
   brokenElement?: JSX.Element;
 
+  // Photo 点击事件
+  onPhotoClick?: (clientX: number, clientY: number) => void;
   // 到达顶部滑动事件
   onReachTopMove?: ReachFunction;
   // 到达右部滑动事件
@@ -81,9 +84,11 @@ export default class PhotoView extends React.Component<
   readonly state = initialState;
 
   private photoRef;
+  private readonly onPhotoClick;
 
   constructor(props) {
     super(props);
+    this.onPhotoClick = debounce(this.debouncePhotoClick, 400);
     this.handleMove = throttle(this.handleMove, 8);
   }
 
@@ -183,8 +188,22 @@ export default class PhotoView extends React.Component<
     }
   }
 
+  debouncePhotoClick = (newClientX: number, newClientY: number) => {
+    const { onPhotoClick } = this.props;
+    const { clientX, clientY } = this.state;
+    if (onPhotoClick && clientX === newClientX && clientY === newClientY) {
+      onPhotoClick(newClientX, newClientY);
+    }
+  }
+
+  handlePhotoClick = (e) => {
+    this.onPhotoClick(e.clientX, e.clientY);
+  }
+
   handleDoubleClick = (e) => {
     e.preventDefault();
+    // 取消 click 事件
+    this.onPhotoClick.cancel();
     const { clientX, clientY } = e;
     const { width, naturalWidth } = this.photoRef.state;
     this.setState(({ x, y, scale }) => {
@@ -446,6 +465,7 @@ export default class PhotoView extends React.Component<
           className={className}
           src={src}
           ref={this.handlePhotoRef}
+          onClick={this.handlePhotoClick}
           onDoubleClick={this.handleDoubleClick}
           onMouseDown={isMobile ? undefined : this.handleMouseDown}
           onTouchStart={isMobile ? this.handleTouchStart : undefined}

+ 2 - 1
src/components/TopWrap.tsx

@@ -12,7 +12,7 @@ export const TopBar = styled.div`
   height: 44px;
   color: white;
   background-color: rgba(0, 0, 0, 0.5);
-  transition: opacity 0.4s linear;
+  transition: opacity 0.2s ease-out;
   will-change: opacity;
   z-index: 20;
 `;
@@ -42,6 +42,7 @@ function CloseSVG(props) {
 }
 
 export const Close = styled(CloseSVG)<React.HTMLAttributes<any>>`
+  box-sizing: border-box;
   padding: 10px;
   opacity: 0.75;
   cursor: pointer;

+ 14 - 0
src/utils/throttle.ts

@@ -0,0 +1,14 @@
+import debounce from 'lodash.debounce';
+
+/**
+ * throttle
+ * @param func
+ * @param wait
+ */
+export default function throttle(func: Function, wait: number) {
+  return debounce(func, wait, {
+    leading: true,
+    maxWait: wait,
+    trailing: true
+  });
+}

+ 2 - 1
tsconfig.json

@@ -4,6 +4,7 @@
     "moduleResolution": "node",
     "jsx": "preserve",
     "allowSyntheticDefaultImports": true,
-    "target": "es6"
+    "target": "es6",
+    "experimentalDecorators": true
   }
 }