Ver Fonte

事件处理

MinJieLiu há 7 anos atrás
pai
commit
b3c40d859c
5 ficheiros alterados com 39 adições e 65 exclusões
  1. 1 1
      package.json
  2. 10 6
      src/PhotoSlider.tsx
  3. 27 45
      src/PhotoView.tsx
  4. 1 1
      src/types.ts
  5. 0 12
      src/utils/getCurrentFromEvent.ts

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "react-photo-view",
-  "version": "0.2.1",
+  "version": "0.2.2",
   "description": "React photo preview.",
   "main": "./lib/index",
   "module": "./es/index",

+ 10 - 6
src/PhotoSlider.tsx

@@ -4,6 +4,7 @@ import SlideWrap from './components/SlideWrap';
 import Backdrop from './components/Backdrop';
 import { Close, Counter, BannerWrap, BannerRight } from './components/BannerWrap';
 import FooterWrap from './components/FooterWrap';
+import isMobile from './utils/isMobile';
 import { dataType, IPhotoProviderBase } from './types';
 import { defaultOpacity, horizontalOffset, maxMoveOffset } from './variables';
 
@@ -15,7 +16,7 @@ interface IPhotoSliderProps extends IPhotoProviderBase {
   // 可见
   visible: boolean;
   // 关闭事件
-  onClose: (evt?: React.MouseEvent) => void;
+  onClose: (evt?: React.MouseEvent | React.TouchEvent) => void;
   // 索引改变回调
   onIndexChange?: Function;
 }
@@ -94,13 +95,13 @@ export default class PhotoSlider extends React.Component<
     window.removeEventListener('resize', this.handleResize);
   }
 
-  handlePhotoClick = () => {
+  handlePhotoTap = () => {
     this.setState(prevState => ({
       overlayVisible: !prevState.overlayVisible,
     }));
   }
 
-  handlePhotoMaskClick = () => {
+  handlePhotoMaskTap = () => {
     const { maskClosable, onClose } = this.props;
     if (maskClosable) {
       onClose();
@@ -254,7 +255,10 @@ export default class PhotoSlider extends React.Component<
             <BannerWrap style={overlayStyle}>
               <Counter>{photoIndex + 1} / {imageLength}</Counter>
               <BannerRight>
-                <Close onClick={onClose} />
+                <Close
+                  onTouchEnd={isMobile ? onClose : undefined}
+                  onClick={isMobile ? undefined : onClose}
+                />
               </BannerRight>
             </BannerWrap>
           ) : undefined}
@@ -283,8 +287,8 @@ export default class PhotoSlider extends React.Component<
                     realIndex > 0 ? this.handleReachHorizontalMove : undefined
                   }
                   onReachUp={this.handleReachUp}
-                  onPhotoClick={this.handlePhotoClick}
-                  onMaskClick={this.handlePhotoMaskClick}
+                  onPhotoTap={this.handlePhotoTap}
+                  onMaskTap={this.handlePhotoMaskTap}
                   photoScale={photoIndex === realIndex ? photoScale : 1}
                   wrapClassName={viewClassName}
                   className={imageClassName}

+ 27 - 45
src/PhotoView.tsx

@@ -5,7 +5,6 @@ import PhotoWrap from './components/PhotoWrap';
 import PhotoMask from './components/PhotoMask';
 import throttle from './utils/throttle';
 import isMobile from './utils/isMobile';
-import getCurrentFromEvent from './utils/getCurrentFromEvent';
 import getMultipleTouchPosition from './utils/getMultipleTouchPosition';
 import getPositionOnMoveOrScale from './utils/getPositionOnMoveOrScale';
 import slideToSuitableOffset from './utils/slideToSuitableOffset';
@@ -13,7 +12,7 @@ import { getClosedHorizontal, getClosedVertical } from './utils/getCloseEdge';
 import { maxScale, minReachOffset, minScale, scaleBuffer } from './variables';
 import {
   ReachFunction,
-  PhotoClickFunction,
+  PhotoTapFunction,
   ReachTypeEnum,
 } from './types';
 
@@ -34,9 +33,9 @@ interface IPhotoViewProps {
   brokenElement?: JSX.Element;
 
   // Photo 点击事件
-  onPhotoClick?: PhotoClickFunction;
+  onPhotoTap?: PhotoTapFunction;
   // Mask 点击事件
-  onMaskClick?: PhotoClickFunction;
+  onMaskTap?: PhotoTapFunction;
   // 到达顶部滑动事件
   onReachTopMove?: ReachFunction;
   // 到达右部滑动事件
@@ -46,7 +45,7 @@ interface IPhotoViewProps {
   // 到达左部滑动事件
   onReachLeftMove?: ReachFunction;
   // 触摸解除事件
-  onReachUp?: (clientX: number, clientY: number) => void;
+  onReachUp?: ReachFunction;
 
   onPhotoResize?: () => void;
 }
@@ -94,9 +93,9 @@ export default class PhotoView extends React.Component<
 
   constructor(props) {
     super(props);
-    // 加入延迟触发,避免与双击混淆
-    this.photoClick = debounce(this.photoClick, 300);
     this.handleMove = throttle(this.handleMove, 8);
+    // 延迟触发,与双击事件区分
+    this.handlePhotoTap = debounce(this.handlePhotoTap, 300);
   }
 
   componentDidMount() {
@@ -195,26 +194,17 @@ export default class PhotoView extends React.Component<
     }
   }
 
-  photoClick = (newClientX: number, newClientY: number) => {
-    const { onPhotoClick } = this.props;
-    const { clientX, clientY } = this.state;
-    if (onPhotoClick
-      && Math.abs(clientX - newClientX) < 5
-      && Math.abs(clientY - newClientY) < 5
-    ) {
-      onPhotoClick(newClientX, newClientY);
+  handlePhotoTap = (clientX: number, clientY: number) => {
+    const { onPhotoTap } = this.props;
+    if (onPhotoTap) {
+      onPhotoTap(clientX, clientY);
     }
   }
 
-  handlePhotoClick = (e) => {
-    const { clientX, clientY } = getCurrentFromEvent(e);
-    this.photoClick(clientX, clientY);
-  }
-
   handleDoubleClick = (e) => {
     e.preventDefault();
-    // @ts-ignore 取消 click 事件
-    this.photoClick.cancel();
+    // @ts-ignore 取消 Tap 事件
+    this.handlePhotoTap.cancel();
     const { clientX, clientY } = e;
     const { width, naturalWidth } = this.photoRef.state;
     this.setState(({ x, y, scale }) => {
@@ -282,19 +272,6 @@ export default class PhotoView extends React.Component<
     this.handleMaskStart(clientX, clientY);
   }
 
-  handleMaskClick = (e) => {
-    const evt = getCurrentFromEvent(e);
-    const { onMaskClick } = this.props;
-    const { clientX, clientY } = this.state;
-    if (
-      onMaskClick
-      && Math.abs(clientX - evt.clientX) < 5
-      && Math.abs(clientY - evt.clientY) < 5
-    ) {
-      onMaskClick(clientX, clientY);
-    }
-  }
-
   handleTouchStart = e => {
     if (e.touches.length >= 2) {
       const { clientX, clientY, touchLength } = getMultipleTouchPosition(e);
@@ -329,7 +306,7 @@ export default class PhotoView extends React.Component<
   handleUp = (newClientX: number, newClientY: number) => {
     const { touched, maskTouched } = this.state;
     if (touched || maskTouched) {
-      const { onReachUp } = this.props;
+      const { onReachUp, onPhotoTap, onMaskTap } = this.props;
       const { width, naturalWidth, height } = this.photoRef.state;
       this.setState(({
         x,
@@ -341,19 +318,26 @@ export default class PhotoView extends React.Component<
         clientX,
         clientY,
       }) => {
+        const hasMove = clientX !== newClientX || clientY !== newClientY;
         if (onReachUp) {
           onReachUp(newClientX, newClientY);
         }
-        const hasMove = clientX !== newClientX || clientY !== newClientY;
-        // 缩放弹性效果
-        const toScale = Math.max(
-          Math.min(scale, Math.max(maxScale, naturalWidth / width)),
-          minScale,
-        );
+        // 没有移动触发 Tap 事件
+        if (!hasMove) {
+          if (touched && onPhotoTap) {
+            this.handlePhotoTap(newClientX, newClientY);
+          } else if (maskTouched && onMaskTap) {
+            onMaskTap(newClientX, newClientY);
+          }
+        }
         return {
           touched: false,
           maskTouched: false,
-          scale: toScale,
+          // 限制缩放
+          scale: Math.max(
+            Math.min(scale, Math.max(maxScale, naturalWidth / width)),
+            minScale,
+          ),
           reachState: ReachTypeEnum.Normal, // 重置触发状态
           ...hasMove
             ? slideToSuitableOffset({
@@ -474,13 +458,11 @@ export default class PhotoView extends React.Component<
         <PhotoMask
           onMouseDown={isMobile ? undefined : this.handleMaskMouseDown}
           onTouchStart={isMobile ? this.handleMaskTouchStart : undefined}
-          onClick={this.handleMaskClick}
         />
         <Photo
           className={className}
           src={src}
           ref={this.handlePhotoRef}
-          onClick={this.handlePhotoClick}
           onDoubleClick={this.handleDoubleClick}
           onMouseDown={isMobile ? undefined : this.handleMouseDown}
           onTouchStart={isMobile ? this.handleTouchStart : undefined}

+ 1 - 1
src/types.ts

@@ -37,7 +37,7 @@ export interface IPhotoProviderBase {
 
 export type ReachFunction = (clientX: number, clientY: number) => void;
 
-export type PhotoClickFunction = (clientX: number, clientY: number) => void;
+export type PhotoTapFunction = (clientX: number, clientY: number) => void;
 
 /**
  * 边缘超出状态

+ 0 - 12
src/utils/getCurrentFromEvent.ts

@@ -1,12 +0,0 @@
-/**
- * 获取 mouse 或 touch 事件的当前节点
- * @param evt
- */
-const getCurrentFromEvent = (evt) => {
-  if (evt.touches && evt.touches.length) {
-    return evt.touches[0];
-  }
-  return evt;
-};
-
-export default getCurrentFromEvent;