Skip to content

Commit ee350bd

Browse files
committed
feat: 图片集优化
1 parent 8dc06a0 commit ee350bd

File tree

7 files changed

+201
-37
lines changed

7 files changed

+201
-37
lines changed

docs/zh-CN/components/image.md

+17
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,22 @@ List 的内容、Card 卡片的内容配置同上
431431
}
432432
```
433433

434+
## 内嵌模式
435+
436+
配置`"embed": true`,显示图片内嵌模式
437+
438+
```schema
439+
{
440+
"type": "page",
441+
"body": {
442+
"type": "image",
443+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80",
444+
"embed": true,
445+
"showToolbar": true
446+
}
447+
}
448+
```
449+
434450
## 属性表
435451

436452
| 属性名 | 类型 | 默认值 | 说明 | 版本 |
@@ -458,6 +474,7 @@ List 的内容、Card 卡片的内容配置同上
458474
| imageMode | `string` | `thumb` | 图片展示模式,可选:`'thumb'`, `'original'` 即:缩略图模式 或者 原图模式 |
459475
| showToolbar | `boolean` | `false` | 放大模式下是否展示图片的工具栏 | `2.2.0` |
460476
| toolbarActions | `ImageAction[]` | | 图片工具栏,支持旋转,缩放,默认操作全部开启 | `2.2.0` |
477+
| embed | `boolean` | | 内嵌模式,当是 `true` 开启内嵌显示 | `3.5.3` |
461478
| maxScale | `number`[模板](../../docs/concepts/template) | | 执行调整图片比例动作时的最大百分比 | `3.4.4` |
462479
| minScale | `number`[模板](../../docs/concepts/template) | | 执行调整图片比例动作时的最小百分比 | `3.4.4` |
463480

docs/zh-CN/components/images.md

+54
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,56 @@ Array<{
418418
}
419419
```
420420

421+
## 内嵌模式
422+
423+
**images 组件** 上,配置`embed``true`,支持放大预览
424+
425+
```schema
426+
{
427+
"type": "page",
428+
"data": {
429+
"images": [
430+
{
431+
"image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80",
432+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
433+
"title": "图片1",
434+
"description": "图片1的描述"
435+
},
436+
{
437+
"image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692942/d8e4992057f9.jpeg@s_0,w_216,l_1,f_jpg,q_80",
438+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
439+
"title": "图片2",
440+
"description": "图片2的描述"
441+
},
442+
{
443+
"image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693148/1314a2a3d3f6.jpeg@s_0,w_216,l_1,f_jpg,q_80",
444+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
445+
"title": "图片3",
446+
"description": "图片3的描述"
447+
},
448+
{
449+
"image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693379/8f2e79f82be0.jpeg@s_0,w_216,l_1,f_jpg,q_80",
450+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
451+
"title": "图片4",
452+
"description": "图片4的描述"
453+
},
454+
{
455+
"image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693566/552b175ef11d.jpeg@s_0,w_216,l_1,f_jpg,q_80",
456+
"src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg",
457+
"title": "图片5",
458+
"description": "图片5的描述"
459+
}
460+
]
461+
},
462+
"body": {
463+
"type": "images",
464+
"source": "${images}",
465+
"embed": true
466+
}
467+
}
468+
```
469+
470+
421471
## 用作 Field 时
422472

423473
当用在 Table 的列配置 Column、List 的内容、Card 卡片的内容和表单的 Static-XXX 中时,可以设置`name`属性,映射同名变量
@@ -680,3 +730,7 @@ List 的内容、Card 卡片的内容配置同上。
680730
| thumbRatio | `string` | `1:1` | 预览图比例,可选:`'1:1'`, `'4:3'`, `'16:9'` |
681731
| showToolbar | `boolean` | `false` | 放大模式下是否展示图片的工具栏 | `2.2.0` |
682732
| toolbarActions | `ImageAction[]` | | 图片工具栏,支持旋转,缩放,默认操作全部开启 | `2.2.0` |
733+
| embed | `boolean` | `false` | 内嵌模式,当是 `true` 开启内嵌显示 | `3.5.3` |
734+
| imageStyle | `object` | | 设置图片列表每一项的style | `3.5.3` |
735+
| position.toolbar | `top' \| 'bottom'` | `'bottom'` | 设置图片放大时,工具栏位置 | `3.5.3` |
736+
| position.description | `'left' \| 'right'` | `'right'` | 设置图片放大时,描述对应显示框位置 | `3.5.3` |

packages/amis-ui/scss/components/_image-gallery.scss

-2
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@
248248
position: absolute;
249249
cursor: move;
250250
cursor: -webkit-grab;
251-
max-width: 100%;
252-
max-height: 100%;
253251
vertical-align: middle;
254252
transform-origin: center;
255253
transition: transform 0.3s cubic-bezier(0, 0, 0.25, 1) 0s;

packages/amis-ui/src/components/DragProgress.tsx

+21-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface DragProgrocessProp extends ThemeProps, LocaleProps {
1111
value: number;
1212
onChange?: (value?: number) => void;
1313
skin: 'light' | 'dark';
14+
max: number;
1415
}
1516

1617
interface DragProgrocessState {
@@ -39,14 +40,16 @@ class DragProgress extends React.PureComponent<
3940
isDragging: boolean = false;
4041
previousX: number;
4142

42-
static defaultProps: Pick<DragProgrocessProp, 'skin'> = {
43-
skin: 'light'
43+
static defaultProps: Pick<DragProgrocessProp, 'skin' | 'max'> = {
44+
skin: 'light',
45+
max: 1
4446
};
4547

4648
constructor(props: DragProgrocessProp) {
4749
super(props);
4850

49-
const left = props?.value ? getLeftByValue(props.value) : leftStartPoint;
51+
const act = props.value / props.max;
52+
const left = act ? getLeftByValue(act) : leftStartPoint;
5053
this.state = {
5154
left,
5255
precent: getPrecentByLeft(left)
@@ -56,6 +59,17 @@ class DragProgress extends React.PureComponent<
5659
document.addEventListener('mouseup', this.handleMouseUp);
5760
}
5861

62+
componentDidUpdate(prevProps: Readonly<DragProgrocessProp>): void {
63+
if (prevProps.value !== this.props.value) {
64+
const act = this.props.value / this.props.max;
65+
const left = act ? getLeftByValue(act) : leftStartPoint;
66+
this.setState({
67+
left,
68+
precent: getPrecentByLeft(left)
69+
});
70+
}
71+
}
72+
5973
componentWillUnmount() {
6074
document.removeEventListener('mousemove', this.handleMouseMove);
6175
document.removeEventListener('mouseup', this.handleMouseUp);
@@ -101,12 +115,13 @@ class DragProgress extends React.PureComponent<
101115
@autobind
102116
handleDrag(clientX: number) {
103117
this.previousX = clientX;
118+
const max = this.props.max;
104119
const {precent} = this.state;
105-
this.props?.onChange?.(precent);
120+
this.props?.onChange?.(precent * max);
106121
}
107122

108123
render() {
109-
const {classnames: cx, skin} = this.props;
124+
const {classnames: cx, skin, max} = this.props;
110125
const {left, precent} = this.state;
111126

112127
return (
@@ -132,7 +147,7 @@ class DragProgress extends React.PureComponent<
132147
}}
133148
></div>
134149
</div>
135-
<div className={cx('DrapProgress-precent')}>{precent}%</div>
150+
<div className={cx('DrapProgress-precent')}>{precent * max}%</div>
136151
</div>
137152
);
138153
}

packages/amis-ui/src/components/ImageGallery.tsx

+61-24
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ export interface ImageGalleryProps
6464
showToolbar?: boolean;
6565
/** 是否内嵌 */
6666
embed?: boolean;
67-
items: Array<ImageGalleryItem>;
67+
items?: Array<ImageGalleryItem>;
6868
position?: ImageGalleryPosition;
69+
enlargeWithGallary?: boolean;
6970
}
7071

7172
export interface ImageGalleryState {
@@ -74,6 +75,8 @@ export interface ImageGalleryState {
7475
items: Array<ImageGalleryItem>;
7576
/** 图片缩放比例尺 */
7677
scale: number;
78+
/** 默认图片缩放比例尺 */
79+
defaultScale: number;
7780
/** 图片旋转角度 */
7881
rotate: number;
7982
/**
@@ -95,7 +98,7 @@ export interface ImageGalleryState {
9598
/** 图片是否加载中 */
9699
imageLoading: boolean;
97100
/** 图片信息 */
98-
imageLoadInfo?: {
101+
imageLoadInfo: {
99102
naturalWidth: number;
100103
naturalHeight: number;
101104
url: string;
@@ -149,33 +152,37 @@ export class ImageGallery extends React.Component<
149152
tx: 0,
150153
ty: 0,
151154
scale: 1,
155+
defaultScale: 1,
152156
rotate: 0,
153157
showToolbar: false,
154158
imageGallaryClassName: '',
155159
actions: ImageGallery.defaultProps.actions,
156-
imageLoading: false,
157-
isNaturalSize: false
160+
imageLoading: true,
161+
isNaturalSize: false,
162+
imageLoadInfo: {
163+
naturalWidth: 0,
164+
naturalHeight: 0,
165+
url: ''
166+
}
158167
};
159168

160169
galleryMain?: HTMLDivElement;
161170

162171
constructor(props: ImageGalleryProps) {
163172
super(props);
164173

165-
const hasItems = !!props?.items;
166-
167174
this.state = {
168175
...this.state,
169-
items: hasItems ? props.items : [],
170-
index: hasItems ? 0 : -1,
176+
items: props.items ?? [],
177+
index: !!props?.items ? 0 : -1,
171178
showToolbar: !!props?.showToolbar
172179
};
173180
}
174181

175182
componentDidUpdate(prevProps: Readonly<ImageGalleryProps>): void {
176183
if (this.props.items !== prevProps.items) {
177184
this.setState({
178-
items: this.props.items
185+
items: this.props.items ?? []
179186
});
180187
}
181188
if (this.props?.showToolbar !== prevProps?.showToolbar) {
@@ -189,6 +196,12 @@ export class ImageGallery extends React.Component<
189196
position: this.props.position
190197
});
191198
}
199+
200+
if (this.props.enlargeWithGallary !== prevProps.enlargeWithGallary) {
201+
this.setState({
202+
enlargeWithGallary: this.props.enlargeWithGallary
203+
});
204+
}
192205
}
193206

194207
@autobind
@@ -291,6 +304,7 @@ export class ImageGallery extends React.Component<
291304
enlargeWithGallary: info.enlargeWithGallary,
292305
imageGallaryClassName: info.imageGallaryClassName,
293306
position: info?.position,
307+
imageLoading: true,
294308
/** 外部传入合法key值的actions才会生效 */
295309
actions: Array.isArray(info.toolbarActions)
296310
? info.toolbarActions.filter(action =>
@@ -301,8 +315,9 @@ export class ImageGallery extends React.Component<
301315
}
302316

303317
resetImageAction() {
318+
const {defaultScale} = this.state;
304319
this.setState({
305-
scale: 1,
320+
scale: defaultScale,
306321
rotate: 0,
307322
isNaturalSize: false
308323
});
@@ -319,15 +334,13 @@ export class ImageGallery extends React.Component<
319334
@autobind
320335
prev() {
321336
const index = this.state.index;
322-
this.setState({index: index - 1, imageLoading: true});
323-
this.resetImageAction();
337+
this.setIndex(index - 1);
324338
}
325339

326340
@autobind
327341
next() {
328342
const index = this.state.index;
329-
this.setState({index: index + 1, imageLoading: true});
330-
this.resetImageAction();
343+
this.setIndex(index + 1);
331344
}
332345

333346
@autobind
@@ -340,8 +353,16 @@ export class ImageGallery extends React.Component<
340353
* 设置当前选中
341354
*/
342355
@autobind
343-
setIndex(index: number) {
344-
this.setState({index, imageLoading: true});
356+
setIndex(cIndex: number) {
357+
const {items, index} = this.state;
358+
const bool = items[index].originalSrc === items[cIndex].originalSrc;
359+
console.log(bool);
360+
this.setState({
361+
index: cIndex,
362+
imageLoading: !bool,
363+
tx: 0,
364+
ty: 0
365+
});
345366
this.resetImageAction();
346367
}
347368

@@ -379,10 +400,11 @@ export class ImageGallery extends React.Component<
379400
return;
380401
}
381402

403+
const {defaultScale} = this.state;
382404
switch (action.key) {
383405
case ImageActionKey.DEFAULT_VIEW:
384406
this.setState({
385-
scale: 1,
407+
scale: defaultScale,
386408
isNaturalSize: false,
387409
tx: 0,
388410
ty: 0
@@ -421,13 +443,24 @@ export class ImageGallery extends React.Component<
421443
@autobind
422444
handleImageLoad(e: React.SyntheticEvent<HTMLImageElement>) {
423445
const {index, items} = this.state;
446+
const {clientWidth, clientHeight} = this.galleryMain!;
447+
// @ts-ignore
448+
const naturalHeight = e.target?.naturalHeight;
449+
// @ts-ignore
450+
const naturalWidth = e.target?.naturalWidth;
451+
let scale = 1;
452+
if (naturalHeight >= clientHeight || naturalWidth >= clientWidth) {
453+
const p1 = clientHeight / naturalHeight;
454+
const p2 = clientWidth / naturalWidth;
455+
scale = p1 > p2 ? p2 : p1;
456+
}
424457
this.setState({
458+
scale,
459+
defaultScale: scale,
425460
imageLoadInfo: {
426461
url: items[index]?.src,
427-
// @ts-ignore
428-
naturalHeight: e.target?.naturalHeight,
429-
// @ts-ignore
430-
naturalWidth: e.target?.naturalWidth
462+
naturalHeight,
463+
naturalWidth
431464
},
432465
imageLoading: false
433466
});
@@ -465,9 +498,10 @@ export class ImageGallery extends React.Component<
465498
if (action.key === ImageActionKey.DRAG) {
466499
return (
467500
<DragProgress
468-
value={1}
501+
value={scale}
469502
onChange={this.handleDragProgress}
470503
skin={embed ? 'light' : 'dark'}
504+
max={2}
471505
/>
472506
);
473507
}
@@ -559,7 +593,7 @@ export class ImageGallery extends React.Component<
559593
return [
560594
~index && items[index] ? (
561595
<>
562-
<div className={cx('ImageGallery-main')} ref={this.galleryMainRef}>
596+
<div className={cx('ImageGallery-main')}>
563597
<div
564598
className={cx(
565599
'ImageGallery-preview',
@@ -576,7 +610,10 @@ export class ImageGallery extends React.Component<
576610
: ''
577611
)}
578612
>
579-
<div className={cx('ImageGallery-image-wrap')}>
613+
<div
614+
className={cx('ImageGallery-image-wrap')}
615+
ref={this.galleryMainRef}
616+
>
580617
<img
581618
draggable={false}
582619
src={items[index].originalSrc}

0 commit comments

Comments
 (0)