Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(image): add mouse wheel zoom switch for image preview #2625

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions components/Image/README.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Show and preview pictures.
|maskClosable|Whether click mask to close|boolean |`true`|-|
|resetTranslate|Enable position correction|boolean |`true`|2.61.0|
|visible|Whether is visible|boolean |`-`|-|
|wheelZoomable|Whether to allow mouse wheel zoom|boolean |`true`|-|
|breakPoint|The width that triggers the toolbar to switch to simple mode|number |`316`|-|
|src|Image path, The default in Image is the src of Image|string **(Required)**|`-`|-|
|imgAttributes|Image props, passthrough to the `img` tag in the preview modal|Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'> |`-`|2.39.0|
Expand Down Expand Up @@ -71,6 +72,7 @@ Start from `v2.14.0`
|maskClosable|Whether click mask to close|boolean |`true`|-|
|resetTranslate|Enable position correction|boolean |`true`|2.61.0|
|visible|Whether is visible|boolean |`-`|-|
|wheelZoomable|Whether to allow mouse wheel zoom|boolean |`true`|-|
|breakPoint|The width that triggers the toolbar to switch to simple mode|number |`316`|-|
|current|The index of current image (controlled prop)|number |`-`|-|
|defaultCurrent|The default index of first image|number |`-`|-|
Expand Down
2 changes: 2 additions & 0 deletions components/Image/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
|maskClosable|点击 mask 是否触发关闭|boolean |`true`|-|
|resetTranslate|开启位置修正|boolean |`true`|2.61.0|
|visible|是否可见,受控属性|boolean |`-`|-|
|wheelZoomable|是否允许鼠标滚轮缩放|boolean |`true`|-|
|breakPoint|触发 toolbar 切换为 simple 模式的宽度|number |`316`|-|
|src|图片获取地址, 在 Image 中默认是 Image 的 src|string **(必填)**|`-`|-|
|imgAttributes|图片属性,透传至预览弹窗中的 `img` 标签上|Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'> |`-`|2.39.0|
Expand Down Expand Up @@ -71,6 +72,7 @@
|maskClosable|点击 mask 是否触发关闭|boolean |`true`|-|
|resetTranslate|开启位置修正|boolean |`true`|2.61.0|
|visible|是否可见,受控属性|boolean |`-`|-|
|wheelZoomable|是否允许鼠标滚轮缩放|boolean |`true`|-|
|breakPoint|触发 toolbar 切换为 simple 模式的宽度|number |`316`|-|
|current|当前展示的图片的下标 (受控属性)|number |`-`|-|
|defaultCurrent|第一张展示的图片的下标|number |`-`|-|
Expand Down
10 changes: 10 additions & 0 deletions components/Image/__test__/preview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,16 @@ describe('Image', () => {
expect(wrapper.find('.arco-image-preview-img-moving')[0]).toBeUndefined();
});

it('turn off mousewheel zoom', () => {
const wrapper = render(<Image.Preview src={imgSrc} wheelZoomable={false} visible />);
jest.runAllTimers();
const ele = wrapper.find('.arco-image-preview-img-container')[0];
expect(ele.style.transform).toEqual(`scale(1, 1)`);
act(() => {
fireEvent.wheel(ele, { deltaY: 10 });
});
expect(ele.style.transform).toBe(`scale(1, 1)`);
});
it('handle zoom event correctly when set custom scales', () => {
const customsScale = [-90, 20, 120];

Expand Down
4 changes: 3 additions & 1 deletion components/Image/image-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type ImagePreviewHandle = {
const defaultProps: Partial<ImagePreviewProps> = {
maskClosable: true,
closable: true,
wheelZoomable: true,
breakPoint: 316,
actionsLayout: [
'fullScreen',
Expand Down Expand Up @@ -75,6 +76,7 @@ function Preview(baseProps: ImagePreviewProps, ref) {
defaultVisible,
maskClosable,
closable,
wheelZoomable,
breakPoint,
actions,
actionsLayout,
Expand Down Expand Up @@ -454,7 +456,7 @@ function Preview(baseProps: ImagePreviewProps, ref) {
const renderImage = () => {
const image = (
<img
onWheel={onWheelZoom}
onWheel={wheelZoomable ? onWheelZoom : undefined}
ref={refImage}
className={cs(imgClassName, `${previewPrefixCls}-img`, {
[`${previewPrefixCls}-img-moving`]: moving,
Expand Down
10 changes: 9 additions & 1 deletion components/Image/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function Image(baseProps: ImagePropsType, ref: LegacyRef<HTMLDivElement>) {
}, []);

const previewSrc = previewProps.src || src;
const previewWheelZoomable = previewProps.wheelZoomable;
const [showFooter] = useShowFooter({ title, description, actions });
const { isLoading, isError, isLoaded, isBeforeLoad, setStatus } = useImageStatus('beforeLoad');
const loaded = useRef(false);
Expand All @@ -92,7 +93,13 @@ function Image(baseProps: ImagePropsType, ref: LegacyRef<HTMLDivElement>) {

// Props passed directly into Preview component
const availablePreviewProps = useMemo(() => {
return omit(previewProps, ['visible', 'defaultVisible', 'src', 'onVisibleChange']);
return omit(previewProps, [
'visible',
'defaultVisible',
'src',
'onVisibleChange',
'wheelZoomable',
]);
}, [previewProps]);

const prefixCls = getPrefixCls('image');
Expand Down Expand Up @@ -243,6 +250,7 @@ function Image(baseProps: ImagePropsType, ref: LegacyRef<HTMLDivElement>) {
)}
{isLoaded && preview && (
<ImagePreview
wheelZoomable={previewWheelZoomable}
visible={previewVisible}
src={previewSrc}
{...availablePreviewProps}
Expand Down
6 changes: 6 additions & 0 deletions components/Image/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ export interface ImagePreviewProps {
* @version 2.16.0
*/
closable?: boolean;
/**
* @zh 是否允许鼠标滚轮缩放
* @en Whether to allow mouse wheel zoom
* @defaultValue true
*/
wheelZoomable?: boolean;
/**
* @zh 额外操作,[ImagePreviewActionProps](#imagepreviewactionprops)
* @en Extra operations, [ImagePreviewActionProps](#imagepreviewactionprops)
Expand Down
123 changes: 84 additions & 39 deletions stories/Image.story.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { useState } from 'react';
import { Image, Button, Space } from '@self';
import { Image } from '@self';

function ImageWrapper({ actions }) {
console.log(actions);
function ImageWrapper({ previewProps = {} }) {
const { wheelZoomable, actions = [] } = previewProps || {};
return (
<Image
width={200}
src="//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp"
previewProps={{
actions: actions || [],
wheelZoomable,
}}
/>
);
Expand All @@ -17,47 +19,90 @@ ImageWrapper.displayName = 'Image';
function Demo1() {
const [actions, setActions] = useState([]);
return (
<a>
<span
onClick={() => {
setActions([
{
key: 'download',
content: (
<span
onClick={() => {
setActions([
{
key: 'info',
content: 'info',
name: 'Info',
},
]);
}}
>
download
</span>
),
name: 'Download',
},
{
key: 'info',
content: 'info',
name: 'Info',
},
]);
}}
>
asdd
</span>
<div>
<h2>Loop rendering in Image component</h2>
<a>
<span
onClick={() => {
setActions([
{
key: 'download',
content: (
<span
onClick={() => {
setActions([
{
key: 'info',
content: 'info',
name: 'Info',
},
]);
}}
>
download
</span>
),
name: 'Download',
},
{
key: 'info',
content: 'info',
name: 'Info',
},
]);
}}
>
<u>click here to add actions</u>
</span>{' '}
</a>
<br />
<Image.PreviewGroup>
<ImageWrapper actions={actions} />
<ImageWrapper previewProps={{ actions }} />
</Image.PreviewGroup>
</a>
</div>
);
}

export const Demo = () => <Demo1 />;
function DemoWheelSwitch() {
return (
<div>
<h2>WheelZoom Switch</h2>
<div>
<p>(default) enable wheelZoom @Image</p>
<ImageWrapper />
</div>
<div>
<p>(defaul) enable wheelZoom @ImagePreview</p>
<Image.PreviewGroup>
<ImageWrapper />
<ImageWrapper />
</Image.PreviewGroup>
</div>
<div>
<p>turn off wheelZoom @Image</p>
<ImageWrapper
previewProps={{
wheelZoomable: false,
}}
/>
</div>
<div>
<p>turn off wheelZoom @ImagePreview</p>
<Image.PreviewGroup wheelZoomable={false}>
<ImageWrapper />
<ImageWrapper />
</Image.PreviewGroup>
</div>
</div>
);
}

export const Demo = () => (
<>
<Demo1 />
<DemoWheelSwitch />
</>
);

export default {
title: 'Image',
Expand Down