mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
feat: 支持图片点击/鼠标移入移出事件 & 支持图片预览放大缩小动作 (#8266)
* feat: 支持图片点击/鼠标移入移出事件 & 支持图片预览放大缩小动作 * docs & test: 补充image文档及单测
This commit is contained in:
parent
67afdb0b05
commit
6480245738
@ -433,31 +433,33 @@ List 的内容、Card 卡片的内容配置同上
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 | 版本 |
|
||||
| ------------------ | ------------------------------------ | --------- | --------------------------------------------------------------------------------------------- | ------- |
|
||||
| type | `string` | | 如果在 Table、Card 和 List 中,为`"image"`;在 Form 中用作静态展示,为`"static-image"` |
|
||||
| className | `string` | | 外层 CSS 类名 |
|
||||
| innerClassName | `string` | | 组件内层 CSS 类名 |
|
||||
| imageClassName | `string` | | 图片 CSS 类名 |
|
||||
| thumbClassName | `string` | | 图片缩率图 CSS 类名 |
|
||||
| height | `string` | | 图片缩率高度 |
|
||||
| width | `string` | | 图片缩率宽度 |
|
||||
| title | `string` | | 标题 |
|
||||
| imageCaption | `string` | | 描述 |
|
||||
| placeholder | `string` | | 占位文本 |
|
||||
| defaultImage | `string` | | 无数据时显示的图片 |
|
||||
| src | `string` | | 缩略图地址 |
|
||||
| href | [模板](../../docs/concepts/template) | | 外部链接地址 |
|
||||
| originalSrc | `string` | | 原图地址 |
|
||||
| enlargeAble | `boolean` | | 支持放大预览 |
|
||||
| enlargeTitle | `string` | | 放大预览的标题 |
|
||||
| enlargeCaption | `string` | | 放大预览的描述 |
|
||||
| enlargeWithGallary | `string` | `true` | 在表格中,图片的放大功能会默认展示所有图片信息,设置为`false`将关闭放大模式下图片集列表的展示 |
|
||||
| thumbMode | `string` | `contain` | 预览图模式,可选:`'w-full'`, `'h-full'`, `'contain'`, `'cover'` |
|
||||
| thumbRatio | `string` | `1:1` | 预览图比例,可选:`'1:1'`, `'4:3'`, `'16:9'` |
|
||||
| imageMode | `string` | `thumb` | 图片展示模式,可选:`'thumb'`, `'original'` 即:缩略图模式 或者 原图模式 |
|
||||
| showToolbar | `boolean` | `false` | 放大模式下是否展示图片的工具栏 | `2.2.0` |
|
||||
| toolbarActions | `ImageAction[]` | | 图片工具栏,支持旋转,缩放,默认操作全部开启 | `2.2.0` |
|
||||
| 属性名 | 类型 | 默认值 | 说明 | 版本 |
|
||||
| ------------------ | ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------- | ------- |
|
||||
| type | `string` | | 如果在 Table、Card 和 List 中,为`"image"`;在 Form 中用作静态展示,为`"static-image"` |
|
||||
| className | `string` | | 外层 CSS 类名 |
|
||||
| innerClassName | `string` | | 组件内层 CSS 类名 |
|
||||
| imageClassName | `string` | | 图片 CSS 类名 |
|
||||
| thumbClassName | `string` | | 图片缩率图 CSS 类名 |
|
||||
| height | `string` | | 图片缩率高度 |
|
||||
| width | `string` | | 图片缩率宽度 |
|
||||
| title | `string` | | 标题 |
|
||||
| imageCaption | `string` | | 描述 |
|
||||
| placeholder | `string` | | 占位文本 |
|
||||
| defaultImage | `string` | | 无数据时显示的图片 |
|
||||
| src | `string` | | 缩略图地址 |
|
||||
| href | [模板](../../docs/concepts/template) | | 外部链接地址 |
|
||||
| originalSrc | `string` | | 原图地址 |
|
||||
| enlargeAble | `boolean` | | 支持放大预览 |
|
||||
| enlargeTitle | `string` | | 放大预览的标题 |
|
||||
| enlargeCaption | `string` | | 放大预览的描述 |
|
||||
| enlargeWithGallary | `string` | `true` | 在表格中,图片的放大功能会默认展示所有图片信息,设置为`false`将关闭放大模式下图片集列表的展示 |
|
||||
| thumbMode | `string` | `contain` | 预览图模式,可选:`'w-full'`, `'h-full'`, `'contain'`, `'cover'` |
|
||||
| thumbRatio | `string` | `1:1` | 预览图比例,可选:`'1:1'`, `'4:3'`, `'16:9'` |
|
||||
| imageMode | `string` | `thumb` | 图片展示模式,可选:`'thumb'`, `'original'` 即:缩略图模式 或者 原图模式 |
|
||||
| showToolbar | `boolean` | `false` | 放大模式下是否展示图片的工具栏 | `2.2.0` |
|
||||
| toolbarActions | `ImageAction[]` | | 图片工具栏,支持旋转,缩放,默认操作全部开启 | `2.2.0` |
|
||||
| maxScale | `number` 或 [模板](../../docs/concepts/template) | | 执行调整图片比例动作时的最大百分比 | `3.4.4` |
|
||||
| minScale | `number` 或 [模板](../../docs/concepts/template) | | 执行调整图片比例动作时的最小百分比 | `3.4.4` |
|
||||
|
||||
#### ImageAction
|
||||
|
||||
@ -475,3 +477,170 @@ interface ImageAction {
|
||||
disabled?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## 事件表
|
||||
|
||||
当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`或`${event.data.[事件参数名]}`来获取事件产生的数据,详细查看[事件动作](../../docs/concepts/event-action)。
|
||||
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| ---------- | ---------- | -------------- |
|
||||
| click | 上下文数据 | 点击图片时触发 |
|
||||
| mouseenter | 上下文数据 | 鼠标移入时触发 |
|
||||
| mouseleave | 上下文数据 | 鼠标移入时触发 |
|
||||
|
||||
### click / mouseenter / mouseleave
|
||||
|
||||
点击图片 / 鼠标移入图片 / 鼠标移出图片,可以尝试通过${event.context.nativeEvent}获取鼠标事件对象。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "image",
|
||||
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80",
|
||||
"onEvent": {
|
||||
"click": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "toast",
|
||||
"args": {
|
||||
"msg": "图片被点击了"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"mouseenter": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "toast",
|
||||
"args": {
|
||||
"msg": "鼠标移入图片"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"mouseleave": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "toast",
|
||||
"args": {
|
||||
"msg": "鼠标移出图片"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 动作表
|
||||
|
||||
当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。
|
||||
|
||||
| 动作名称 | 动作配置 | 说明 |
|
||||
| -------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
|
||||
| preview | - | 预览图片 |
|
||||
| zoom | `scale: number` 或 `scale: `[模板](../../docs/concepts/template),定义每次放大或缩小图片的百分比大小,正值为放大,负值为缩小,默认 50 | 调整图片比例,将图片等比例放大或缩小 |
|
||||
|
||||
### preview
|
||||
|
||||
预览图片,可以通过配置`originalSrc`来指定预览的原图地址。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "page",
|
||||
"body": {
|
||||
"type": "container",
|
||||
"body": [
|
||||
{
|
||||
"type": "container",
|
||||
"body": [
|
||||
{
|
||||
"type": "image",
|
||||
"className": "mb-1",
|
||||
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80",
|
||||
"originalSrc": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
|
||||
"id": "previewImage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "action",
|
||||
"label": "预览图片",
|
||||
"onEvent": {
|
||||
"click": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "preview",
|
||||
"componentId": "previewImage"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### zoom
|
||||
|
||||
调整图片比例,将图片等比例放大或缩小。可以通过配置图片的`maxScale`和`minScale`来限制调整的比例。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "page",
|
||||
"body": {
|
||||
"type": "container",
|
||||
"body": [
|
||||
{
|
||||
"type": "flex",
|
||||
"items": [
|
||||
{
|
||||
"type": "image",
|
||||
"innerClassName": "no-border",
|
||||
"className": "mt-5 mb-5",
|
||||
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80",
|
||||
"maxScale": 200,
|
||||
"minScale": 20,
|
||||
"id": "zoomImage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "action",
|
||||
"label": "放大图片",
|
||||
"onEvent": {
|
||||
"click": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "zoom",
|
||||
"args": {
|
||||
"scale": 50,
|
||||
},
|
||||
"componentId": "zoomImage"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "action",
|
||||
"label": "缩小图片",
|
||||
"className": "mx-1",
|
||||
"onEvent": {
|
||||
"click": {
|
||||
"actions": [
|
||||
{
|
||||
"actionType": "zoom",
|
||||
"args": {
|
||||
"scale": -50,
|
||||
},
|
||||
"componentId": "zoomImage"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -1,4 +1,9 @@
|
||||
import {getI18nEnabled, registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
RendererPluginAction,
|
||||
RendererPluginEvent,
|
||||
getI18nEnabled,
|
||||
registerEditorPlugin
|
||||
} from 'amis-editor-core';
|
||||
import {
|
||||
ActiveEventContext,
|
||||
BaseEventContext,
|
||||
@ -8,6 +13,10 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import {mockValue} from 'amis-editor-core';
|
||||
import {
|
||||
getArgsWrapper,
|
||||
getEventControlConfig
|
||||
} from '../renderer/event-control/helper';
|
||||
|
||||
export class ImagePlugin extends BasePlugin {
|
||||
static id = 'ImagePlugin';
|
||||
@ -34,6 +43,112 @@ export class ImagePlugin extends BasePlugin {
|
||||
value: mockValue({type: 'image'})
|
||||
};
|
||||
|
||||
// 事件定义
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'click',
|
||||
eventLabel: '点击',
|
||||
description: '点击时触发',
|
||||
defaultShow: true,
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
context: {
|
||||
type: 'object',
|
||||
title: '上下文',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'mouseenter',
|
||||
eventLabel: '鼠标移入',
|
||||
description: '鼠标移入时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
context: {
|
||||
type: 'object',
|
||||
title: '上下文',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'mouseleave',
|
||||
eventLabel: '鼠标移出',
|
||||
description: '鼠标移出时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
context: {
|
||||
type: 'object',
|
||||
title: '上下文',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 动作定义
|
||||
actions: RendererPluginAction[] = [
|
||||
{
|
||||
actionType: 'preview',
|
||||
actionLabel: '预览',
|
||||
description: '预览图片'
|
||||
},
|
||||
{
|
||||
actionType: 'zoom',
|
||||
actionLabel: '调整图片比例',
|
||||
description: '将图片等比例放大或缩小',
|
||||
schema: {
|
||||
type: 'container',
|
||||
body: [
|
||||
getArgsWrapper([
|
||||
getSchemaTpl('formulaControl', {
|
||||
name: 'scale',
|
||||
mode: 'horizontal',
|
||||
variables: '${variables}',
|
||||
horizontal: {
|
||||
leftFixed: 4 // 需要设置下leftFixed,否则这个字段的控件没有与其他字段的控件左对齐
|
||||
},
|
||||
label: tipedLabel(
|
||||
'调整比例',
|
||||
'定义每次放大或缩小图片的百分比大小,正值为放大,负值为缩小,默认50'
|
||||
),
|
||||
value: 50,
|
||||
size: 'lg'
|
||||
})
|
||||
])
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
panelTitle = '图片';
|
||||
panelJustify = true;
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
@ -63,7 +178,7 @@ export class ImagePlugin extends BasePlugin {
|
||||
pipeIn: defaultValue('thumb'),
|
||||
options: [
|
||||
{
|
||||
label: '缩率图',
|
||||
label: '缩略图',
|
||||
value: 'thumb'
|
||||
},
|
||||
{
|
||||
@ -130,6 +245,24 @@ export class ImagePlugin extends BasePlugin {
|
||||
getSchemaTpl('imageUrl', {
|
||||
name: 'defaultImage',
|
||||
label: tipedLabel('占位图', '无数据时显示的图片')
|
||||
}),
|
||||
getSchemaTpl('formulaControl', {
|
||||
name: 'maxScale',
|
||||
mode: 'horizontal',
|
||||
label: tipedLabel(
|
||||
'放大极限',
|
||||
'定义动作调整图片大小的最大百分比,默认200'
|
||||
),
|
||||
value: 200
|
||||
}),
|
||||
getSchemaTpl('formulaControl', {
|
||||
name: 'minScale',
|
||||
mode: 'horizontal',
|
||||
label: tipedLabel(
|
||||
'缩小极限',
|
||||
'定义动作调整图片大小的最小百分比,默认50'
|
||||
),
|
||||
value: 50
|
||||
})
|
||||
]
|
||||
},
|
||||
@ -245,6 +378,16 @@ export class ImagePlugin extends BasePlugin {
|
||||
},
|
||||
getSchemaTpl('theme:cssCode')
|
||||
])
|
||||
},
|
||||
{
|
||||
title: '事件',
|
||||
className: 'p-none',
|
||||
body: [
|
||||
getSchemaTpl('eventControl', {
|
||||
name: 'onEvent',
|
||||
...getEventControlConfig(this.manager, context)
|
||||
})
|
||||
]
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
@ -2352,6 +2352,12 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
},
|
||||
confirm: {
|
||||
descDetail: (info: any) => <div>打开确认对话框</div>
|
||||
},
|
||||
preview: {
|
||||
descDetail: (info: any) => <div>预览图片</div>
|
||||
},
|
||||
zoom: {
|
||||
descDetail: (info: any) => <div>调整图片比例</div>
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,10 @@
|
||||
* 9. href
|
||||
* 10. 作为表单项
|
||||
* 11. clickAction
|
||||
* 12. click事件
|
||||
* 13. mouseenter / mouseleave 事件
|
||||
* 14. preview 预览动作
|
||||
* 15. zoom & maxScale & minScale 调整图片比例动作
|
||||
*
|
||||
* * 组件名称:Images 图片集
|
||||
* 内容说明:images 与 image 使用组件相同,相同属性不重复测试了
|
||||
@ -20,7 +24,7 @@
|
||||
* 2. enlargeAble & originalSrc & source & title & description
|
||||
*/
|
||||
|
||||
import {fireEvent, render} from '@testing-library/react';
|
||||
import {fireEvent, render, waitFor} from '@testing-library/react';
|
||||
import '../../src';
|
||||
import {render as amisRender} from '../../src';
|
||||
import {makeEnv, wait} from '../helper';
|
||||
@ -334,7 +338,228 @@ describe('Renderer:image', () => {
|
||||
})
|
||||
);
|
||||
fireEvent.click(container.querySelector('.cxd-Image-thumbWrap')!);
|
||||
expect(getByText('这是一个弹框')!).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(getByText('这是一个弹框')!).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test('image:click', async () => {
|
||||
const notify = jest.fn();
|
||||
const {container, getByText} = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'image',
|
||||
src: 'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80',
|
||||
class: 'cursor-pointer',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'toast',
|
||||
args: {
|
||||
msgType: 'info',
|
||||
msg: '派发点击事件'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
mouseenter: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'toast',
|
||||
args: {
|
||||
msgType: 'info',
|
||||
msg: '派发鼠标移入事件'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
mouseleave: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'toast',
|
||||
args: {
|
||||
msgType: 'info',
|
||||
msg: '派发鼠标移出事件'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({
|
||||
notify,
|
||||
session: 'image-test-action-1'
|
||||
})
|
||||
)
|
||||
);
|
||||
fireEvent.click(container.querySelector('.cxd-Image-thumbWrap')!);
|
||||
await waitFor(() => {
|
||||
expect(notify).toHaveBeenCalledWith('info', '派发点击事件', {
|
||||
msg: '派发点击事件',
|
||||
msgType: 'info'
|
||||
});
|
||||
});
|
||||
fireEvent.mouseEnter(container.querySelector('.cxd-Image-thumbWrap')!);
|
||||
await waitFor(() => {
|
||||
expect(notify).toHaveBeenCalledWith('info', '派发鼠标移入事件', {
|
||||
msg: '派发鼠标移入事件',
|
||||
msgType: 'info'
|
||||
});
|
||||
});
|
||||
fireEvent.mouseLeave(container.querySelector('.cxd-Image-thumbWrap')!);
|
||||
await waitFor(() => {
|
||||
expect(notify).toHaveBeenCalledWith('info', '派发鼠标移出事件', {
|
||||
msg: '派发鼠标移出事件',
|
||||
msgType: 'info'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('image:preview 预览动作', async () => {
|
||||
const {container, getByText, baseElement} = render(
|
||||
amisRender({
|
||||
type: 'page',
|
||||
body: [
|
||||
{
|
||||
type: 'image',
|
||||
id: 'previewImage',
|
||||
src: 'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80',
|
||||
originalSrc:
|
||||
'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg'
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
label: '预览图片',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'preview',
|
||||
componentId: 'previewImage'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
fireEvent.click(getByText('预览图片'));
|
||||
expect(baseElement.querySelector('.cxd-ImageGallery')!).toBeInTheDocument();
|
||||
expect(
|
||||
baseElement.querySelector('.cxd-ImageGallery .cxd-ImageGallery-main img')!
|
||||
).toHaveAttribute(
|
||||
'src',
|
||||
'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg'
|
||||
);
|
||||
});
|
||||
|
||||
test('image:zoom & maxScale & minScale 调整图片比例动作', async () => {
|
||||
const {container, getByText, baseElement} = render(
|
||||
amisRender({
|
||||
type: 'page',
|
||||
body: [
|
||||
{
|
||||
type: 'image',
|
||||
id: 'zoomImage',
|
||||
src: 'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80',
|
||||
originalSrc:
|
||||
'https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg',
|
||||
maxScale: 200,
|
||||
minScale: 20
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
label: '放大图片',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'zoom',
|
||||
args: {
|
||||
scale: 50
|
||||
},
|
||||
componentId: 'zoomImage'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
label: '缩小图片',
|
||||
onEvent: {
|
||||
click: {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'zoom',
|
||||
args: {
|
||||
scale: -50
|
||||
},
|
||||
componentId: 'zoomImage'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
|
||||
const imgIns = baseElement.querySelector('.cxd-ImageField--thumb')!;
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(1)'
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('放大图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(1.5)'
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(1)'
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('放大图片'));
|
||||
fireEvent.click(getByText('放大图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(2)'
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('放大图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(2)'
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(0.2)'
|
||||
});
|
||||
});
|
||||
|
||||
fireEvent.click(getByText('缩小图片'));
|
||||
await waitFor(() => {
|
||||
expect(imgIns).toHaveStyle({
|
||||
transform: 'scale(0.2)'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -56,6 +56,7 @@ exports[`Renderer:image image as form item 1`] = `
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb no-border"
|
||||
@ -103,6 +104,7 @@ exports[`Renderer:image image:basic 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb show"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -138,6 +140,7 @@ exports[`Renderer:image image:enlargeAble & originalSrc & enlargeTitle & showToo
|
||||
<div>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -178,6 +181,7 @@ exports[`Renderer:image image:enlargeAble & originalSrc & enlargeTitle & showToo
|
||||
<div>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -231,6 +235,7 @@ exports[`Renderer:image image:href 1`] = `
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<a
|
||||
class="cxd-Link"
|
||||
@ -263,10 +268,62 @@ exports[`Renderer:image image:href 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Renderer:image image:preview 预览动作 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-Page"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-main"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
role="page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image-thumbWrap"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image-thumb cxd-Image-thumb--contain cxd-Image-thumb--1-1"
|
||||
>
|
||||
<img
|
||||
class="cxd-Image-image"
|
||||
src="https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--size-default"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
预览图片
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Renderer:image image:title & imageCaption 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -308,6 +365,7 @@ exports[`Renderer:image image:width & height 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -330,6 +388,65 @@ exports[`Renderer:image image:width & height 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Renderer:image image:zoom & maxScale & minScale 调整图片比例动作 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-Page"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-main"
|
||||
>
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
role="page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image-thumbWrap"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image-thumb cxd-Image-thumb--contain cxd-Image-thumb--1-1"
|
||||
>
|
||||
<img
|
||||
class="cxd-Image-image"
|
||||
src="https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--size-default"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
放大图片
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--size-default"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
缩小图片
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Renderer:images images:basic 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
@ -7090,6 +7090,7 @@ exports[`Renderer:table list 1`] = `
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -7331,6 +7332,7 @@ exports[`Renderer:table list 1`] = `
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
@ -7692,6 +7694,7 @@ exports[`Renderer:table list 1`] = `
|
||||
>
|
||||
<div
|
||||
class="cxd-ImageField cxd-ImageField--thumb"
|
||||
style="transform: scale(1);"
|
||||
>
|
||||
<div
|
||||
class="cxd-Image cxd-Image--thumb"
|
||||
|
@ -3,7 +3,13 @@ import {
|
||||
Renderer,
|
||||
RendererProps,
|
||||
CustomStyle,
|
||||
setThemeClassName
|
||||
setThemeClassName,
|
||||
ActionObject,
|
||||
IScopedContext,
|
||||
ScopedContext,
|
||||
createObject,
|
||||
resolveVariableAndFilter,
|
||||
isPureVariable
|
||||
} from 'amis-core';
|
||||
import {filter} from 'amis-core';
|
||||
import {themeable, ThemeProps} from 'amis-core';
|
||||
@ -398,6 +404,8 @@ export interface ImageFieldProps extends RendererProps {
|
||||
enlargeWithGallary?: boolean;
|
||||
showToolbar?: boolean;
|
||||
toolbarActions?: ImageAction[];
|
||||
maxScale?: number;
|
||||
minScale?: number;
|
||||
onImageEnlarge?: (
|
||||
info: {
|
||||
src: string;
|
||||
@ -414,9 +422,21 @@ export interface ImageFieldProps extends RendererProps {
|
||||
target: any
|
||||
) => void;
|
||||
imageGallaryClassName?: string;
|
||||
onClick?:
|
||||
| ((e: React.MouseEvent<any>, props: any) => void)
|
||||
| string
|
||||
| Function
|
||||
| null;
|
||||
}
|
||||
|
||||
export class ImageField extends React.Component<ImageFieldProps, object> {
|
||||
interface ImageFieldState {
|
||||
scale: number; // 放大倍率
|
||||
}
|
||||
|
||||
export class ImageField extends React.Component<
|
||||
ImageFieldProps,
|
||||
ImageFieldState
|
||||
> {
|
||||
static defaultProps: Pick<
|
||||
ImageFieldProps,
|
||||
'defaultImage' | 'thumbMode' | 'thumbRatio'
|
||||
@ -426,6 +446,10 @@ export class ImageField extends React.Component<ImageFieldProps, object> {
|
||||
thumbRatio: '1:1'
|
||||
};
|
||||
|
||||
state: ImageFieldState = {
|
||||
scale: 1
|
||||
};
|
||||
|
||||
@autobind
|
||||
handleEnlarge({
|
||||
src,
|
||||
@ -468,13 +492,73 @@ export class ImageField extends React.Component<ImageFieldProps, object> {
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleClick(e: React.MouseEvent<HTMLElement>) {
|
||||
async handleClick(e: React.MouseEvent<HTMLElement>) {
|
||||
const {dispatchEvent, data} = this.props;
|
||||
const clickAction = this.props.clickAction;
|
||||
const rendererEvent = await dispatchEvent(
|
||||
e,
|
||||
createObject(data, {
|
||||
nativeEvent: e
|
||||
})
|
||||
);
|
||||
|
||||
if (rendererEvent?.prevented) {
|
||||
return;
|
||||
}
|
||||
if (clickAction) {
|
||||
handleAction(e, clickAction, this.props);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleMouseEnter(e: React.MouseEvent<any>) {
|
||||
const {dispatchEvent, data} = this.props;
|
||||
dispatchEvent(e, data);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleMouseLeave(e: React.MouseEvent<any>) {
|
||||
const {dispatchEvent, data} = this.props;
|
||||
dispatchEvent(e, data);
|
||||
}
|
||||
|
||||
handleSelfAction(actionType: string, action: ActionObject) {
|
||||
let {data, maxScale = 200, minScale = 50} = this.props;
|
||||
let {scale = 50} = action.args;
|
||||
if (actionType === 'zoom') {
|
||||
if (isPureVariable(maxScale)) {
|
||||
maxScale = isNaN(
|
||||
resolveVariableAndFilter(maxScale, createObject(action.data, data))
|
||||
)
|
||||
? 200
|
||||
: resolveVariableAndFilter(maxScale, createObject(action.data, data));
|
||||
}
|
||||
if (isPureVariable(minScale)) {
|
||||
minScale = isNaN(
|
||||
resolveVariableAndFilter(minScale, createObject(action.data, data))
|
||||
)
|
||||
? 50
|
||||
: resolveVariableAndFilter(minScale, createObject(action.data, data));
|
||||
}
|
||||
|
||||
if (scale >= 0) {
|
||||
this.setState({
|
||||
scale:
|
||||
this.state.scale + scale / 100 < maxScale / 100
|
||||
? this.state.scale + scale / 100
|
||||
: maxScale / 100
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
scale:
|
||||
this.state.scale + scale / 100 > minScale / 100
|
||||
? this.state.scale + scale / 100
|
||||
: minScale / 100
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
@ -520,8 +604,10 @@ export class ImageField extends React.Component<ImageFieldProps, object> {
|
||||
className,
|
||||
setThemeClassName('wrapperCustomStyle', id, wrapperCustomStyle)
|
||||
)}
|
||||
style={style}
|
||||
style={{...style, transform: `scale(${this.state.scale})`}}
|
||||
onClick={this.handleClick}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
>
|
||||
{value || (!value && !placeholder) ? (
|
||||
<ThemedImageThumb
|
||||
@ -597,4 +683,26 @@ export class ImageField extends React.Component<ImageFieldProps, object> {
|
||||
@Renderer({
|
||||
type: 'image'
|
||||
})
|
||||
export class ImageFieldRenderer extends ImageField {}
|
||||
export class ImageFieldRenderer extends ImageField {
|
||||
static contextType = ScopedContext;
|
||||
constructor(props: ImageFieldProps, context: IScopedContext) {
|
||||
super(props);
|
||||
|
||||
const scoped = context;
|
||||
scoped.registerComponent(this);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const scoped = this.context as IScopedContext;
|
||||
scoped.unRegisterComponent(this);
|
||||
}
|
||||
|
||||
doAction(action: ActionObject) {
|
||||
const actionType = action?.actionType as string;
|
||||
if (actionType === 'preview') {
|
||||
this.handleEnlarge(this.props as ImageThumbProps);
|
||||
} else {
|
||||
this.handleSelfAction(actionType, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,9 @@ export interface Action extends Button {
|
||||
| 'selectAll'
|
||||
| 'changeTabKey'
|
||||
| 'click'
|
||||
| 'stopAutoRefresh';
|
||||
| 'stopAutoRefresh'
|
||||
| 'preview'
|
||||
| 'zoom';
|
||||
api?: SchemaApi;
|
||||
asyncApi?: SchemaApi;
|
||||
payload?: any;
|
||||
|
Loading…
Reference in New Issue
Block a user