Skip to content

Commit

Permalink
fix: loadingElement 位置问题
Browse files Browse the repository at this point in the history
fix: 图片放大限制优化
fix: 个别机型中图片无法预览问题
  • Loading branch information
MinJieLiu committed Mar 17, 2022
1 parent 3a43679 commit 0675d2a
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 106 deletions.
13 changes: 6 additions & 7 deletions packages/example/components/doc-broken.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React from 'react';
import { PhotoProvider, PhotoView } from 'react-photo-view';
import { Button, ImageList } from './doc-components';
import { EosIconsBubbleLoading } from '../icons/EosIconsBubbleLoading';
import defaultPhoto from '../images/default-photo.svg';

export default function DocDemo() {
return (
<ImageList>
<PhotoProvider>
<PhotoProvider
loadingElement={<EosIconsBubbleLoading className="text-white w-8 h-8" />}
brokenElement={<img className="w-32 h-32" src={defaultPhoto.src} alt="" />}
>
<PhotoView src="/error.png">
<Button>无默认图</Button>
</PhotoView>
</PhotoProvider>
<PhotoProvider brokenElement={<img className="w-32 h-32" src={defaultPhoto.src} alt="" />}>
<PhotoView src="/error.png">
<Button>自定义默认图</Button>
<Button>Click</Button>
</PhotoView>
</PhotoProvider>
</ImageList>
Expand Down
97 changes: 97 additions & 0 deletions packages/example/icons/EosIconsBubbleLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { SVGProps } from 'react';

export function EosIconsBubbleLoading(props: SVGProps<SVGSVGElement>) {
return (
<svg width="1em" height="1em" viewBox="0 0 24 24" {...props}>
<circle cx="12" cy="2" r="0" fill="currentColor">
<animate
attributeName="r"
begin="0"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(45 12 12)">
<animate
attributeName="r"
begin="0.125s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(90 12 12)">
<animate
attributeName="r"
begin="0.25s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(135 12 12)">
<animate
attributeName="r"
begin="0.375s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(180 12 12)">
<animate
attributeName="r"
begin="0.5s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(225 12 12)">
<animate
attributeName="r"
begin="0.625s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(270 12 12)">
<animate
attributeName="r"
begin="0.75s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
<circle cx="12" cy="2" r="0" fill="currentColor" transform="rotate(315 12 12)">
<animate
attributeName="r"
begin="0.875s"
calcMode="spline"
dur="1s"
keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8"
repeatCount="indefinite"
values="0;2;0;0"
/>
</circle>
</svg>
);
}
export default EosIconsBubbleLoading;
6 changes: 6 additions & 0 deletions packages/example/pages/docs/change-log.en-US.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
title: Change Log
---

## 1.0.0

1. fix: `loadingElement` position problem
2. fix: Image enlargement limit optimization
3. fix: In a few models, the picture cannot be previewed

## 1.0.0-beta.8

1. fix: Inaccurate zoom position after `onScale` API call
Expand Down
6 changes: 6 additions & 0 deletions packages/example/pages/docs/change-log.zh-CN.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
title: Change Log
---

## 1.0.0

1. fix: `loadingElement` 位置问题
2. fix: 图片放大限制优化
3. fix: 个别机型中图片无法预览问题

## 1.0.0-beta.8

1. fix: `onScale` API 调用后缩放位置不准确的问题
Expand Down
4 changes: 2 additions & 2 deletions packages/example/pages/docs/getting-started.en-US.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ When loading images whose aspect ratio exceeds `3` times, the mobile device will

`<PhotoView>` child components can be of the regular `React.HTMLAttributes` type, such as `<img>`, `<div>`, etc.

If it is a custom component, you need to ensure that `onClick` (desktop), `onTouchStart` and `onTouchEnd` (mobile) events can be triggered normally, and forward `ref` to `HTMLElement` to ensure the correctness of opening and closing the animation source.
If it is a custom component, you need to ensure that `onClick` event can be triggered normally, and forward `ref` to `HTMLElement` to ensure the correctness of opening and closing the animation source.

```jsx
<PhotoView src={imageURL}>
Expand Down Expand Up @@ -299,7 +299,7 @@ Add the `overlayRender` function to `<PhotoProvider>` to implement custom nodes.

### Loop preview

Add parameter `loop` on `<PhotoProvider>` to change the number of loop previews. Set to `boolean` to enable and disable, set to `number` type to reach a specific number to enable loop preview, the default value is `3` sheets:
Add parameter `loop` on `<PhotoProvider>` to change the number of loop previews. Set to `boolean` to enable and disable, set to `number` type to exceed the specific number to enable loop preview, the default value is `3` sheets:

```jsx
<PhotoProvider loop={4} />
Expand Down
4 changes: 2 additions & 2 deletions packages/example/pages/docs/getting-started.zh-CN.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export default function MyComponent() {

`<PhotoView>` 子组件可以是常规 `React.HTMLAttributes` 类型,如 `<img />``<div />` 等。

如果是自定义组件则需要保证 `onClick` (桌面端),`onTouchStart``onTouchEnd` (移动端)事件能正常触发,转发 `ref``HTMLElement` 上保证打开/关闭动画源的正确性。
如果是自定义组件则需要保证 `onClick` 事件能正常触发,转发 `ref``HTMLElement` 上保证打开/关闭动画源的正确性。

```jsx
<PhotoView src={imageURL}>
Expand Down Expand Up @@ -297,7 +297,7 @@ function MyComponent() {

### 循环预览

`<PhotoProvider />` 上添加参数 `loop` 可以更改循环预览数量。设为 `boolean` 启用/关闭,设为 `number` 类型则达到具体数量以开启循环预览,默认值为 `3` 张:
`<PhotoProvider />` 上添加参数 `loop` 可以更改循环预览数量。设为 `boolean` 启用/关闭,设为 `number` 类型则超过具体数量以开启循环预览,默认值为 `3` 张:

```jsx
<PhotoProvider loop={4} />
Expand Down
2 changes: 1 addition & 1 deletion packages/react-photo-view/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-photo-view",
"version": "1.0.0-beta.8",
"version": "1.0.0",
"description": "An exquisite React photo preview component",
"author": "MinJieLiu",
"license": "Apache-2.0",
Expand Down
9 changes: 3 additions & 6 deletions packages/react-photo-view/src/Photo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,16 @@ export default function Photo({
alt=""
{...restProps}
/>
{!loaded && (loadingElement || <Spinner className="PhotoView__icon" />)}
{!loaded &&
(<span className="PhotoView__icon">{loadingElement}</span> || <Spinner className="PhotoView__icon" />)}
</>
);
}

if (brokenElement) {
return (
<span className="PhotoView__icon">
{typeof brokenElement === 'function'
? brokenElement({
src,
})
: brokenElement}
{typeof brokenElement === 'function' ? brokenElement({ src }) : brokenElement}
</span>
);
}
Expand Down
62 changes: 23 additions & 39 deletions packages/react-photo-view/src/PhotoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,7 @@ export default function PhotoBox({
// 初始移动距离不足
if (isStillX && isStillY) {
// 方向记录上次移动距离,以便平滑过渡
updateState({
lastCX: nextClientX,
lastCY: nextClientY,
});
updateState({ lastCX: nextClientX, lastCY: nextClientY });
return;
}
// 设置响应状态
Expand All @@ -233,33 +230,22 @@ export default function PhotoBox({
// 横向边缘触发、背景触发禁用当前滑动
if (currentReach === 'x' || maskTouched) {
updateState({ reach: 'x' });
} else {
// 目标倍数
const toScale = limitScale(
scale + ((currentTouchLength - touchLength) / 100 / 2) * scale,
naturalWidth / width,
scaleBuffer,
);
// 导出变量
expose({ scale: toScale });
updateState({
touchLength: currentTouchLength,
reach: currentReach,
scale: toScale,
...getPositionOnMoveOrScale(
x,
y,
width,
height,
scale,
toScale,
nextClientX,
nextClientY,
offsetX,
offsetY,
),
});
return;
}
// 目标倍数
const toScale = limitScale(
scale + ((currentTouchLength - touchLength) / 100 / 2) * scale,
naturalWidth / width,
scaleBuffer,
);
// 导出变量
expose({ scale: toScale });
updateState({
touchLength: currentTouchLength,
reach: currentReach,
scale: toScale,
...getPositionOnMoveOrScale(x, y, width, height, scale, toScale, nextClientX, nextClientY, offsetX, offsetY),
});
}
},
{
Expand Down Expand Up @@ -302,23 +288,25 @@ export default function PhotoBox({
// 重置响应状态
initialTouchRef.current = 0;
if ((touched || maskTouched) && isActive) {
const hasMove = CX !== nextClientX || CY !== nextClientY;
updateState({
touched: false,
maskTouched: false,
pause: false,
stopRaf: false,
reach: undefined,
});
const safeScale = limitScale(scale, naturalWidth / width);
// Go
slideToPosition(x, y, lastX, lastY, width, height, scale, lastScale, rotate, touchTime);
slideToPosition(x, y, lastX, lastY, width, height, scale, safeScale, lastScale, rotate, touchTime);

onReachUp(nextClientX, nextClientY);
// 触发 Tap 事件
if (!hasMove) {
if (CX === nextClientX && CY === nextClientY) {
if (touched) {
handlePhotoTap(nextClientX, nextClientY);
} else if (maskTouched) {
return;
}
if (maskTouched) {
onMaskTap(nextClientX, nextClientY);
}
}
Expand Down Expand Up @@ -394,11 +382,7 @@ export default function PhotoBox({
if (!reach) {
// 限制最大倍数和最小倍数
const toScale = limitScale(scale - e.deltaY / 100 / 2, naturalWidth / width);
updateState({
CX: e.clientX,
CY: e.clientY,
stopRaf: true,
});
updateState({ stopRaf: true });
onScale(toScale, e.clientX, e.clientY);
}
}
Expand Down
6 changes: 1 addition & 5 deletions packages/react-photo-view/src/PhotoSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,7 @@ export default function PhotoSlider(props: IPhotoSliderProps) {
});

function handlePhotoTap(closeable: boolean | undefined) {
return closeable
? close()
: updateState({
overlay: !overlay,
});
return closeable ? close() : updateState({ overlay: !overlay });
}

function handleResize() {
Expand Down
35 changes: 2 additions & 33 deletions packages/react-photo-view/src/PhotoView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type React from 'react';
import { Children, cloneElement, useContext, useEffect, useRef, useState } from 'react';
import { Children, cloneElement, useContext, useEffect, useRef } from 'react';
import useInitial from './hooks/useInitial';
import useMethods from './hooks/useMethods';
import type { PhotoContextType } from './photo-context';
import PhotoContext from './photo-context';
import type { PhotoRenderParams } from './types';
import isTouchDevice from './utils/isTouchDevice';

export interface PhotoViewProps {
/**
Expand Down Expand Up @@ -33,10 +32,6 @@ export interface PhotoViewProps {
const PhotoView: React.FC<PhotoViewProps> = ({ src, render, width, height, children }) => {
const photoContext = useContext<PhotoContextType>(PhotoContext);
const key = useInitial(() => photoContext.nextId());
const [position, updatePosition] = useState({
clientX: undefined as number | undefined,
clientY: undefined as number | undefined,
});
const originRef = useRef<HTMLElement>(null);

useEffect(() => {
Expand All @@ -58,21 +53,6 @@ const PhotoView: React.FC<PhotoViewProps> = ({ src, render, width, height, child
render(props: PhotoRenderParams) {
return render && render(props);
},
touchStart(e: React.TouchEvent) {
const { clientX, clientY } = e.touches[0];
updatePosition({
clientX,
clientY,
});
invokeChildrenFn('onTouchStart', e);
},
touchEnd(e: React.TouchEvent) {
const { clientX, clientY } = e.changedTouches[0];
if (position.clientX === clientX && position.clientY === clientY) {
photoContext.show(key);
}
invokeChildrenFn('onTouchEnd', e);
},
click(e: React.MouseEvent) {
photoContext.show(key);
invokeChildrenFn('onClick', e);
Expand All @@ -91,18 +71,7 @@ const PhotoView: React.FC<PhotoViewProps> = ({ src, render, width, height, child
}, [src]);

if (children) {
return Children.only(
cloneElement(
children,
isTouchDevice
? {
onTouchStart: fn.touchStart,
onTouchEnd: fn.touchEnd,
ref: originRef,
}
: { onClick: fn.click, ref: originRef },
),
);
return Children.only(cloneElement(children, { onClick: fn.click, ref: originRef }));
}
return null;
};
Expand Down
Loading

1 comment on commit 0675d2a

@vercel
Copy link

@vercel vercel bot commented on 0675d2a Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.