MinJieLiu 5 роки тому
батько
коміт
a975a48bd4

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "react-photo-view",
-  "version": "0.3.11",
+  "version": "0.4.0",
   "description": "一款精致的 React 的图片预览组件",
   "author": "MinJieLiu",
   "license": "MIT",

+ 52 - 0
src/PhotoSlider.less

@@ -8,6 +8,15 @@
 }
 
 .PhotoView {
+  &-PhotoSlider__clean {
+    .PhotoView-PhotoSlider__BannerWrap,
+    .PhotoView-PhotoSlider__ArrowLeft,
+    .PhotoView-PhotoSlider__ArrowRight,
+    .PhotoView-PhotoSlider__FooterWrap {
+      opacity: 0;
+    }
+  }
+
   &-PhotoSlider__Backdrop {
     position: absolute;
     top: 0;
@@ -41,6 +50,10 @@
     background-color: rgba(0, 0, 0, 0.5);
     transition: opacity 0.2s ease-out;
     z-index: 20;
+
+    &:hover {
+      opacity: 1;
+    }
   }
 
   &-PhotoSlider__Counter {
@@ -65,6 +78,45 @@
     }
   }
 
+  &-PhotoSlider__ArrowLeft,
+  &-PhotoSlider__ArrowRight {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 70px;
+    height: 100px;
+    margin: auto;
+    opacity: 0.75;
+    z-index: 20;
+    cursor: pointer;
+    user-select: none;
+    transition: opacity 0.2s linear;
+
+    &:hover {
+      opacity: 1;
+    }
+
+    svg {
+      box-sizing: content-box;
+      padding: 10px;
+      width: 24px;
+      height: 24px;
+      fill: white;
+      background: rgba(0, 0, 0, 0.3);
+    }
+  }
+
+  &-PhotoSlider__ArrowLeft {
+    left: 0;
+  }
+
+  &-PhotoSlider__ArrowRight {
+    right: 0;
+  }
+
   &-PhotoSlider__FooterWrap {
     box-sizing: border-box;
     position: absolute;

+ 21 - 8
src/PhotoSlider.tsx

@@ -5,6 +5,8 @@ import PhotoView from './PhotoView';
 import SlideWrap from './components/SlideWrap';
 import VisibleAnimationHandle from './components/VisibleAnimationHandle';
 import CloseSVG from './components/CloseSVG';
+import ArrowLeft from './components/ArrowLeft';
+import ArrowRight from './components/ArrowRight';
 import isTouchDevice from './utils/isTouchDevice';
 import { dataType, IPhotoProviderBase, ReachTypeEnum, ShowAnimateEnum } from './types';
 import { defaultOpacity, horizontalOffset, maxMoveOffset } from './variables';
@@ -321,14 +323,13 @@ export default class PhotoSlider extends React.Component<IPhotoSliderProps, Phot
           if (photoVisible) {
             const { innerWidth } = window;
             const currentOverlayVisible = overlayVisible && showAnimateType === ShowAnimateEnum.None;
-            const overlayStyle = {
-              opacity: +currentOverlayVisible,
-            };
             // 关闭过程中使用下拉保存的透明度
             const currentOpacity = visible ? backdropOpacity : lastBackdropOpacity;
 
             return (
-              <SlideWrap className={className}>
+              <SlideWrap
+                className={classNames({ 'PhotoView-PhotoSlider__clean': !currentOverlayVisible }, className)}
+              >
                 <div
                   className={classNames('PhotoView-PhotoSlider__Backdrop', maskClassName, {
                     'PhotoView-PhotoSlider__fadeIn': showAnimateType === ShowAnimateEnum.In,
@@ -340,7 +341,7 @@ export default class PhotoSlider extends React.Component<IPhotoSliderProps, Phot
                   onAnimationEnd={onShowAnimateEnd}
                 />
                 {bannerVisible && (
-                  <div className="PhotoView-PhotoSlider__BannerWrap" style={overlayStyle}>
+                  <div className="PhotoView-PhotoSlider__BannerWrap">
                     <div className="PhotoView-PhotoSlider__Counter">
                       {photoIndex + 1} / {imageLength}
                     </div>
@@ -390,10 +391,22 @@ export default class PhotoSlider extends React.Component<IPhotoSliderProps, Phot
                       />
                     );
                   })}
+                {!isTouchDevice && bannerVisible && (
+                  <>
+                    {photoIndex !== 0 && (
+                      <div className="PhotoView-PhotoSlider__ArrowLeft" onClick={() => this.handlePrevious(false)}>
+                        <ArrowLeft />
+                      </div>
+                    )}
+                    {photoIndex + 1 < imageLength && (
+                      <div className="PhotoView-PhotoSlider__ArrowRight" onClick={() => this.handleNext(false)}>
+                        <ArrowRight />
+                      </div>
+                    )}
+                  </>
+                )}
                 {Boolean(introVisible && overlayIntro) && (
-                  <div className="PhotoView-PhotoSlider__FooterWrap" style={overlayStyle}>
-                    {overlayIntro}
-                  </div>
+                  <div className="PhotoView-PhotoSlider__FooterWrap">{overlayIntro}</div>
                 )}
                 {overlayRender &&
                   overlayRender({

+ 5 - 10
src/PhotoView.tsx

@@ -133,11 +133,9 @@ export default class PhotoView extends React.Component<IPhotoViewProps, typeof i
 
   componentWillUnmount() {
     if (isTouchDevice) {
-      window.removeEventListener('touchstart', this.handleTouchStart);
       window.removeEventListener('touchmove', this.handleTouchMove);
       window.removeEventListener('touchend', this.handleTouchEnd);
     } else {
-      window.removeEventListener('mousedown', this.handleMouseDown);
       window.removeEventListener('mousemove', this.handleMouseMove);
       window.removeEventListener('mouseup', this.handleMouseUp);
     }
@@ -200,12 +198,11 @@ export default class PhotoView extends React.Component<IPhotoViewProps, typeof i
         const isStillY = Math.abs(newClientY - clientY) <= minStartTouchOffset;
         // 初始移动距离不足
         if (isStillX && isStillY) {
-          // Y 方向记录上次移动距离,以便平滑过渡
-          if (isStillY) {
-            this.setState({
-              lastMoveClientY: newClientY,
-            });
-          }
+          // 方向记录上次移动距离,以便平滑过渡
+          this.setState({
+            lastMoveClientX: newClientX,
+            lastMoveClientY: newClientY,
+          });
           return;
         }
         // 设置响应状态
@@ -327,13 +324,11 @@ export default class PhotoView extends React.Component<IPhotoViewProps, typeof i
   };
 
   handleMaskTouchStart = e => {
-    e.preventDefault();
     const { clientX, clientY } = e.touches[0];
     this.handleMaskStart(clientX, clientY);
   };
 
   handleTouchStart = e => {
-    e.preventDefault();
     const { clientX, clientY, touchLength } = getMultipleTouchPosition(e);
     this.handleStart(clientX, clientY, touchLength);
   };

+ 11 - 0
src/components/ArrowLeft.tsx

@@ -0,0 +1,11 @@
+import React from 'react';
+
+function ArrowLeft(props) {
+  return (
+    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 768 768" {...props}>
+      <path d="M640.5 352.5v63h-390l178.5 180-45 45-256.5-256.5 256.5-256.5 45 45-178.5 180h390z" />
+    </svg>
+  );
+}
+
+export default ArrowLeft;

+ 11 - 0
src/components/ArrowRight.tsx

@@ -0,0 +1,11 @@
+import React from 'react';
+
+function ArrowRight(props) {
+  return (
+    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 768 768" {...props}>
+      <path d="M384 127.5l256.5 256.5-256.5 256.5-45-45 178.5-180h-390v-63h390l-178.5-180z" />
+    </svg>
+  );
+}
+
+export default ArrowRight;

+ 1 - 9
src/components/CloseSVG.tsx

@@ -2,15 +2,7 @@ import React from 'react';
 
 function CloseSVG(props) {
   return (
-    <svg
-      className=""
-      version="1.1"
-      xmlns="http://www.w3.org/2000/svg"
-      width="44"
-      height="44"
-      viewBox="0 0 768 768"
-      {...props}
-    >
+    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 768 768" {...props}>
       <path
         fill="#FFF"
         d="M607.5 205.5l-178.5 178.5 178.5 178.5-45 45-178.5-178.5-178.5 178.5-45-45 178.5-178.5-178.5-178.5 45-45 178.5 178.5 178.5-178.5z"