MinJieLiu 5 жил өмнө
parent
commit
2fc1619c82

+ 30 - 0
src/PhotoSlider.tsx

@@ -87,12 +87,39 @@ export default class PhotoSlider extends React.Component<
     this.handlePhotoMaskTap = debounce(this.handlePhotoMaskTap, 200);
   }
 
+  private computeMousePosition: { x: number; y: number } | null; // 保存触发位置
+  private mousePositionEventBind: boolean = false; // 点击事件状态
+
   componentDidMount() {
     const { index = 0 } = this.props;
     this.setState({
       translateX: index * -(window.innerWidth + horizontalOffset),
       photoIndex: index,
     });
+
+    if (this.mousePositionEventBind) {
+      return;
+    }
+    // 只有点击事件支持从鼠标位置动画展开
+    let thisTimeOut;
+    document.addEventListener(
+      'click',
+      e => {
+        this.computeMousePosition = {
+          x: e.pageX,
+          y: e.pageY,
+        };
+        // 20ms 内发生过点击事件,则从点击位置动画展示
+        // 否则直接动画展示
+        // 这样可以兼容非点击方式展开
+        clearTimeout(thisTimeOut);
+        thisTimeOut = setTimeout(() => {
+          this.computeMousePosition = null;
+        }, 20);
+      },
+      true,
+    );
+    this.mousePositionEventBind = true;
   }
 
   handleClose = () => {
@@ -349,6 +376,9 @@ export default class PhotoSlider extends React.Component<
                   loadingElement={loadingElement}
                   brokenElement={brokenElement}
                   onPhotoResize={this.handleResize}
+                  transformOrigin={this.computeMousePosition
+                    ? `${this.computeMousePosition.x}px ${this.computeMousePosition.y}px`
+                    : undefined}
                 />
               );
             })}

+ 17 - 0
src/PhotoView.less

@@ -1,4 +1,21 @@
+@keyframes PhotoView__animateIn {
+  from {
+    opacity: 0;
+    transform: scale(0.9);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
 .PhotoView {
+
+  &__animateIn {
+    opacity: 0;
+    animation: PhotoView__animateIn 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) both;
+  }
+
   &__PhotoWrap {
     position: absolute;
     top: 0;

+ 23 - 18
src/PhotoView.tsx

@@ -37,6 +37,8 @@ export interface IPhotoViewProps {
   // 加载失败 Element
   brokenElement?: JSX.Element;
 
+  transformOrigin: string | undefined;
+
   // Photo 点击事件
   onPhotoTap: PhotoTapFunction;
   // Mask 点击事件
@@ -417,6 +419,7 @@ export default class PhotoView extends React.Component<
       style,
       loadingElement,
       brokenElement,
+      transformOrigin,
     } = this.props;
     const { x, y, scale, touched } = this.state;
 
@@ -429,24 +432,26 @@ export default class PhotoView extends React.Component<
           onMouseDown={isMobile ? undefined : this.handleMaskMouseDown}
           onTouchStart={isMobile ? this.handleMaskTouchStart : undefined}
         />
-        <Photo
-          className={className}
-          src={src}
-          ref={this.photoRef}
-          onMouseDown={isMobile ? undefined : this.handleMouseDown}
-          onTouchStart={isMobile ? this.handleTouchStart : undefined}
-          onWheel={this.handleWheel}
-          onPhotoResize={this.handleResize}
-          style={{
-            WebkitTransform: transform,
-            transform,
-            transition: touched
-              ? undefined
-              : 'transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1)',
-          }}
-          loadingElement={loadingElement}
-          brokenElement={brokenElement}
-        />
+        <div className="PhotoView__animateIn" style={{ transformOrigin }}>
+          <Photo
+            className={className}
+            src={src}
+            ref={this.photoRef}
+            onMouseDown={isMobile ? undefined : this.handleMouseDown}
+            onTouchStart={isMobile ? this.handleTouchStart : undefined}
+            onWheel={this.handleWheel}
+            onPhotoResize={this.handleResize}
+            style={{
+              WebkitTransform: transform,
+              transform,
+              transition: touched
+                ? undefined
+                : 'transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1)',
+            }}
+            loadingElement={loadingElement}
+            brokenElement={brokenElement}
+          />
+        </div>
       </div>
     );
   }

+ 1 - 1
src/components/SlideWrap.less

@@ -1,5 +1,5 @@
 .PhotoView {
-  &__SlideWrap {
+  &-SlideWrap {
     position: fixed;
     top: 0;
     left: 0;

+ 1 - 1
src/components/SlideWrap.tsx

@@ -35,7 +35,7 @@ const SlideWrap: React.FC<{ className?: string }> = ({
   );
 
   return createPortal(
-    <div className={classNames('PhotoView__SlideWrap', className)}>
+    <div className={classNames('PhotoView-SlideWrap', className)}>
       {children}
     </div>,
     dialogNode,