MinJieLiu 7 år sedan
förälder
incheckning
71e646905a
2 ändrade filer med 64 tillägg och 58 borttagningar
  1. 31 29
      src/PhotoView.tsx
  2. 33 29
      src/utils.ts

+ 31 - 29
src/PhotoView.tsx

@@ -3,7 +3,7 @@ import { Motion, spring } from 'react-motion';
 import throttle from 'lodash.throttle';
 import Photo from './Photo';
 import { PhotoContainer, Backdrop } from './StyledElements';
-import { getPositionOnScale, jumpToSuitableOffset } from './utils';
+import { isMobile, getPositionOnScale, jumpToSuitableOffset } from './utils';
 import { defaultAnimationConfig } from './variables';
 import { animationType } from './types';
 
@@ -29,11 +29,6 @@ type PhotoViewState = {
   // 触摸开始时图片 y 偏移量
   lastY: number;
 
-  originX: number;
-  originY: number;
-  originTranslateX: number;
-  originTranslateY: number;
-
   // 触摸开始时时间
   touchedTime: number;
 } & animationType;
@@ -73,17 +68,23 @@ export default class PhotoView extends React.Component<
   }
 
   componentDidMount() {
-    window.addEventListener('touchmove', this.handleTouchMove);
-    window.addEventListener('touchend', this.handleMouseUp);
-    window.addEventListener('mousemove', this.handleMouseMove);
-    window.addEventListener('mouseup', this.handleMouseUp);
+    if (isMobile) {
+      window.addEventListener('touchmove', this.handleTouchMove);
+      window.addEventListener('touchend', this.handleTouchEnd);
+    } else {
+      window.addEventListener('mousemove', this.handleMouseMove);
+      window.addEventListener('mouseup', this.handleMouseUp);
+    }
   }
 
   componentWillUnmount() {
-    window.removeEventListener('touchmove', this.handleTouchMove);
-    window.removeEventListener('touchend', this.handleMouseUp);
-    window.removeEventListener('mousemove', this.handleMouseMove);
-    window.removeEventListener('mouseup', this.handleMouseUp);
+    if (isMobile) {
+      window.removeEventListener('touchmove', this.handleTouchMove);
+      window.removeEventListener('touchend', this.handleTouchEnd);
+    } else {
+      window.removeEventListener('mousemove', this.handleMouseMove);
+      window.removeEventListener('mouseup', this.handleMouseUp);
+    }
   }
 
   handleStart = e => {
@@ -111,7 +112,7 @@ export default class PhotoView extends React.Component<
 
   handleDoubleClick = (e) => {
     const { pageX, pageY } = e;
-    this.setState(({ x, y, scale, originX, originY, originTranslateX, originTranslateY }) => {
+    this.setState(({ x, y, scale }) => {
       return {
         pageX,
         pageY,
@@ -120,12 +121,8 @@ export default class PhotoView extends React.Component<
           y,
           pageX,
           pageY,
-          originX,
-          originY,
-          originTranslateX,
-          originTranslateY,
           fromScale: scale,
-          toScale: scale > 1 ? 1 : 2,
+          toScale: scale !== 1 ? 1 : 2,
         }),
       };
     });
@@ -133,7 +130,7 @@ export default class PhotoView extends React.Component<
 
   handleWheel = (e) => {
     const { pageX, pageY, deltaY } = e;
-    this.setState(({ x, y, scale, originX, originY, originTranslateX, originTranslateY }) => {
+    this.setState(({ x, y, scale }) => {
       return {
         pageX,
         pageY,
@@ -142,10 +139,6 @@ export default class PhotoView extends React.Component<
           y,
           pageX,
           pageY,
-          originX,
-          originY,
-          originTranslateX,
-          originTranslateY,
           fromScale: scale,
           toScale: scale - deltaY / 100 / 2,
         }),
@@ -172,8 +165,7 @@ export default class PhotoView extends React.Component<
     this.handleMove(e.pageX, e.pageY);
   }
 
-  handleMouseUp = (e) => {
-    const { pageX, pageY } = e;
+  handleUp = (pageX, pageY) => {
     const { width, height } = this.photoRef.state;
     this.setState(({
       x,
@@ -202,6 +194,16 @@ export default class PhotoView extends React.Component<
     });
   }
 
+  handleTouchEnd = (e) => {
+    const { pageX, pageY } = e.changedTouches[0];
+    this.handleUp(pageX, pageY);
+  }
+
+  handleMouseUp = (e) => {
+    const { pageX, pageY } = e;
+    this.handleUp(pageX, pageY);
+  }
+
   handlePhotoRef = (ref) => {
     this.photoRef = ref;
   }
@@ -226,8 +228,8 @@ export default class PhotoView extends React.Component<
                 src={src}
                 ref={this.handlePhotoRef}
                 onDoubleClick={this.handleDoubleClick}
-                onMouseDown={this.handleMouseDown}
-                onTouchStart={this.handleTouchStart}
+                onMouseDown={isMobile ? undefined : this.handleMouseDown}
+                onTouchStart={isMobile ? this.handleTouchStart : undefined}
                 onWheel={this.handleWheel}
                 style={{
                   WebkitTransform: transform,

+ 33 - 29
src/utils.ts

@@ -2,6 +2,11 @@ import { animationType } from './types';
 import { maxTouchTime, defaultAnimationConfig } from './variables';
 
 /**
+ * 是否为移动端设备
+ */
+export const isMobile: boolean = window.navigator.userAgent.includes('Mobile');
+
+/**
  * 获取图片合适的大小
  * @param naturalWidth 图片真实宽度
  * @param naturalHeight 图片真实高度
@@ -48,10 +53,6 @@ export const getPositionOnScale = ({
   y,
   pageX,
   pageY,
-  originX,
-  originY,
-  originTranslateX,
-  originTranslateY,
   fromScale,
   toScale,
 }: {
@@ -59,43 +60,46 @@ export const getPositionOnScale = ({
   y: number;
   pageX: number;
   pageY: number;
-  originX: number;
-  originY: number;
-  originTranslateX: number;
-  originTranslateY: number;
   fromScale: number;
   toScale: number;
 }): {
   x: number;
   y: number;
-  originX: number;
-  originY: number;
-  originTranslateX: number;
-  originTranslateY: number;
   scale: number;
 } => {
   const { innerWidth, innerHeight } = window;
-  // 缩放距离计算
-  const imageCenterX = innerWidth / 2 + x;
-  const imageCenterY = innerHeight / 2 + y;
-
-  const offsetX = pageX - imageCenterX;
-  const offsetY = pageY - imageCenterY;
+  let endScale = toScale;
+  let currentX = x;
+  let currentY = y;
+  // 缩放限制
+  if (toScale < 0.5) {
+    endScale = 0.5;
+  } else if (toScale > 5) {
+    endScale = 5;
+  } else {
+    const centerPageX = pageX - innerWidth / 2;
+    const centerPageY = pageY - innerHeight / 2;
 
-  const currentTranslateX = x + (offsetX - originX * fromScale);
-  const currentTranslateY = y + (offsetY - originY * fromScale);
+    const scale = endScale - fromScale;
 
-  const currentOriginX = offsetX / fromScale;
-  const currentOriginY = offsetY / fromScale;
+    currentX = x - centerPageX * scale;
+    currentY = y - centerPageY * scale;
 
+    // const imageCenterX = innerWidth / 2 + x;
+    // const imageCenterY = innerHeight / 2 + y;
+    //
+    // const offsetX = pageX - imageCenterX;
+    // const offsetY = pageY - imageCenterY;
+    //
+    // const scale = endScale - fromScale;
+    //
+    // currentX = x - offsetX * scale;
+    // currentY = y - offsetY * scale;
+  }
   return {
-    x: 0,
-    y: 0,
-    originTranslateX: currentTranslateX,
-    originTranslateY: currentTranslateY,
-    scale: Math.max(Math.min(toScale, 5), 1),
-    originX: currentOriginX,
-    originY: currentOriginY,
+    x: currentX,
+    y: currentY,
+    scale: endScale,
   };
 };