Skip to content

feat(image): add new features #5479

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

Merged
merged 13 commits into from
Apr 14, 2022
Merged
5 changes: 5 additions & 0 deletions components/image/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ Previewable image.
| placeholder | Load placeholder, use default placeholder when set `true` | boolean \| slot | - | 2.0.0 |
| preview | preview config, disabled when `false` | boolean \| [previewType](#previewType) | true | 2.0.0 |
| src | Image path | string | - | 2.0.0 |
| previewMask | custom mask | slot | - | 3.2.0 |
| width | Image width | string \| number | - | 2.0.0 |
| onError | Load failed callback | (event: Event) => void | - | 3.2.0 |

### previewType

Expand All @@ -31,6 +33,9 @@ Previewable image.
visible?: boolean;
onVisibleChange?: (visible, prevVisible) => void;
getContainer?: string | HTMLElement | (() => HTMLElement);
src?: string;
maskClassName?: string;
current?: number;
}
```

Expand Down
23 changes: 13 additions & 10 deletions components/image/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,13 @@ const Image = defineComponent<ImageProps>({

const mergedPreview = computed(() => {
const { preview } = props;
const imageLocale = configProvider.locale?.Image || defaultLocale.Image;

if (preview === false) {
return preview;
}
const _preview = typeof preview === 'object' ? preview : {};

return {
mask: slots.previewMask ? (
slots.previewMask()
) : (
<div class={`${prefixCls.value}-mask-info`}>
<EyeOutlined />
{imageLocale?.preview}
</div>
),
icons,
..._preview,
transitionName: getTransitionName(rootPrefixCls.value, 'zoom', _preview.transitionName),
Expand All @@ -49,11 +40,23 @@ const Image = defineComponent<ImageProps>({
});

return () => {
const imageLocale = configProvider.locale?.Image || defaultLocale.Image;

return (
<ImageInternal
{...{ ...attrs, ...props, prefixCls: prefixCls.value }}
preview={mergedPreview.value}
v-slots={slots}
v-slots={{
...slots,
previewMask:
slots.previewMask ??
(() => (
<div class={`${prefixCls.value}-mask-info`}>
<EyeOutlined />
{imageLocale?.preview}
</div>
)),
}}
></ImageInternal>
);
};
Expand Down
4 changes: 2 additions & 2 deletions components/image/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
| placeholder | 加载占位, 为 `true` 时使用默认占位 | boolean \| slot | - | 2.0.0 |
| preview | 预览参数,为 `false` 时禁用 | boolean \| [previewType](#previewType) | true | 2.0.0 |
| src | 图片地址 | string | - | 2.0.0 |
| previewMask | 自定义 mask | slot | - | 3.2.0 |
| width | 图像宽度 | string \| number | - | 2.0.0 |
| onError | 加载错误回调 | (event: Event) => void | - | |
| onError | 加载错误回调 | (event: Event) => void | - | 3.2.0 |

### previewType

Expand All @@ -34,7 +35,6 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
onVisibleChange?: (visible, prevVisible) => void;
getContainer: string | HTMLElement | (() => HTMLElement);
src?: string;
mask?: VNode;
maskClassName?: string;
current?: number;
}
Expand Down
15 changes: 7 additions & 8 deletions components/vc-image/src/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ImgHTMLAttributes, CSSProperties, PropType, VNode } from 'vue';
import { ref, watch, defineComponent, computed, onMounted, onBeforeUnmount } from 'vue';
import type { ImgHTMLAttributes, CSSProperties, PropType } from 'vue';
import { ref, watch, defineComponent, computed, onMounted, onUnmounted } from 'vue';
import isNumber from 'lodash-es/isNumber';
import cn from '../../_util/classNames';
import PropTypes from '../../_util/vue-types';
Expand All @@ -20,7 +20,6 @@ export type ImagePreviewType = Omit<
visible?: boolean;
onVisibleChange?: (value: boolean, prevValue: boolean) => void;
getContainer?: GetContainer | false;
mask?: VNode | VNode[];
maskClassName?: string;
icons?: PreviewProps['icons'];
};
Expand Down Expand Up @@ -191,7 +190,7 @@ const ImageInternal = defineComponent({
{ flush: 'post', immediate: true },
);
});
onBeforeUnmount(unRegister);
onUnmounted(unRegister);
const toSizePx = (l: number | string) => {
if (isNumber(l)) return l + 'px';
return l;
Expand All @@ -217,7 +216,7 @@ const ImageInternal = defineComponent({
class: cls,
style,
} = attrs as ImgHTMLAttributes;
const { icons, mask: previewMask, src: previewSrc, ...dialogProps } = preview.value;
const { icons, src: previewSrc, ...dialogProps } = preview.value;

const wrappperClass = cn(prefixCls, wrapperClassName, {
[`${prefixCls}-error`]: isError.value,
Expand Down Expand Up @@ -248,7 +247,7 @@ const ImageInternal = defineComponent({
<div
class={wrappperClass}
onClick={
props.preview && !Object.is(previewVisible.value, false) && !isError.value
canPreview.value && !Object.is(previewVisible.value, false)
? onPreview
: e => {
emit('click', e);
Expand Down Expand Up @@ -276,8 +275,8 @@ const ImageInternal = defineComponent({
</div>
)}
{/* Preview Click Mask */}
{previewMask && canPreview.value && (
<div class={`${prefixCls}-mask`}>{previewMask}</div>
{slots.previewMask && canPreview.value && (
<div class={`${prefixCls}-mask`}>{slots.previewMask()}</div>
)}
</div>
{!isPreviewGroup.value && canPreview.value && (
Expand Down
5 changes: 1 addition & 4 deletions components/vc-image/src/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export interface PreviewProps extends Omit<IDialogChildProps, 'onClose' | 'mask'
onClose?: (e: Element) => void;
src?: string;
alt?: string;
mask?: VNode;
rootClassName?: string;
icons?: {
rotateLeft?: VNode;
Expand All @@ -51,9 +50,6 @@ export const previewProps = {
type: Object as PropType<PreviewProps['icons']>,
default: () => ({} as PreviewProps['icons']),
},
mask: {
type: Object as PropType<PreviewProps['mask']>,
},
};
const Preview = defineComponent({
name: 'Preview',
Expand Down Expand Up @@ -101,6 +97,7 @@ const Preview = defineComponent({
scale.value = 1;
rotate.value = 0;
setPosition(initialPosition);
emit('afterClose');
};

const onZoomIn = () => {
Expand Down
16 changes: 10 additions & 6 deletions components/vc-image/src/PreviewGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { PropType, Ref, ComputedRef } from 'vue';
import { ref, provide, defineComponent, inject, watch, reactive, computed, watchEffect } from 'vue';
import { ref, provide, defineComponent, inject, watch, reactive, computed } from 'vue';
import { type ImagePreviewType, mergeDefaultValue } from './Image';
import Preview from './Preview';
import type { PreviewProps } from './Preview';
Expand Down Expand Up @@ -135,17 +135,20 @@ const Group = defineComponent({
mousePosition.value = null;
};

const onPreviewAfterClose = () => {
if (!isShowPreview.value && isControlled.value) {
setCurrent(currentControlledKey.value);
}
};

watch(previewVisible, () => {
isShowPreview.value = !!previewVisible.value;
});
watch(isShowPreview, (val, preVal) => {
onPreviewVisibleChange.value(val, preVal);
});

watchEffect(() => {
if (!isShowPreview.value && isControlled.value) {
setCurrent(currentControlledKey.value);
}
watch(currentControlledKey, val => {
setCurrent(val);
});

context.provide({
Expand All @@ -170,6 +173,7 @@ const Group = defineComponent({
visible={isShowPreview.value}
prefixCls={props.previewPrefixCls}
onClose={onPreviewClose}
onAfterClose={onPreviewAfterClose}
mousePosition={mousePosition.value}
src={canPreviewUrls.value.get(current.value)}
icons={props.icons}
Expand Down