From 0fae923b93e096d9e06c7b46fa70aa7d17363140 Mon Sep 17 00:00:00 2001 From: liaoxuezhi Date: Thu, 19 Aug 2021 15:06:29 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E8=B0=83=E6=95=B4=20image=20=E5=92=8C?= =?UTF-8?q?=20carousel=20(#2412)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 调整 image 和 carousel 1. image 扩充源码模式 2. carousel 扩充图片裁剪模式 cover | contain * 更新 snapshot * 补充样式 --- .../__snapshots__/Carousel.test.tsx.snap | 122 ++++++++---------- .../__snapshots__/Image.test.tsx.snap | 6 +- docs/zh-CN/components/carousel.md | 49 ++++--- docs/zh-CN/components/image.md | 34 ++++- docs/zh-CN/components/images.md | 8 +- scss/components/_carousel.scss | 22 +++- scss/components/_images.scss | 40 +++++- src/renderers/Carousel.tsx | 59 ++++++--- src/renderers/Image.tsx | 99 +++++++++----- 9 files changed, 279 insertions(+), 160 deletions(-) diff --git a/__tests__/renderers/__snapshots__/Carousel.test.tsx.snap b/__tests__/renderers/__snapshots__/Carousel.test.tsx.snap index 1327e86f4..27a42f4de 100644 --- a/__tests__/renderers/__snapshots__/Carousel.test.tsx.snap +++ b/__tests__/renderers/__snapshots__/Carousel.test.tsx.snap @@ -12,95 +12,77 @@ exports[`Renderer:carousel 1`] = ` + + + diff --git a/__tests__/renderers/__snapshots__/Image.test.tsx.snap b/__tests__/renderers/__snapshots__/Image.test.tsx.snap index bb46b0051..a391a0313 100644 --- a/__tests__/renderers/__snapshots__/Image.test.tsx.snap +++ b/__tests__/renderers/__snapshots__/Image.test.tsx.snap @@ -3,10 +3,10 @@ exports[`Renderer:image 1`] = `
diff --git a/docs/zh-CN/components/carousel.md b/docs/zh-CN/components/carousel.md index a2f42d20f..be18af56e 100755 --- a/docs/zh-CN/components/carousel.md +++ b/docs/zh-CN/components/carousel.md @@ -13,6 +13,10 @@ order: 33 ```schema: scope="body" { "type": "carousel", + "auto": false, + "thumbMode": "cover", + "animation": "slide", + "height": 300, "options": [ { "image": "https://internal-amis-res.cdn.bcebos.com/images/2019-12/1577157239810/da6376bf988c.png" @@ -21,6 +25,7 @@ order: 33 "html": "
carousel data
" }, { + "thumbMode": "contain", "image": "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3893101144,2877209892&fm=23&gp=0.jpg" } ] @@ -74,27 +79,28 @@ itemSchema: { ## 属性表 -| 属性名 | 类型 | 默认值 | 说明 | -| ---------------------------- | --------- | -------------------- | ------------------------------------------------------- | -| type | `string` | `"carousel"` | 指定为 Carousel 渲染器 | -| className | `string` | `"panel-default"` | 外层 Dom 的类名 | -| options | `array` | `[]` | 轮播面板数据 | -| options.image | `string` | | 图片链接 | -| options.imageClassName | `string` | | 图片类名 | -| options.title | `string` | | 图片标题 | -| options.titleClassName | `string` | | 图片标题类名 | -| options.description | `string` | | 图片描述 | -| options.descriptionClassName | `string` | | 图片描述类名 | -| options.html | `string` | | HTML 自定义,同[Tpl](./tpl)一致 | -| itemSchema | `object` | | 自定义`schema`来展示数据 | -| auto | `boolean` | `true` | 是否自动轮播 | -| interval | `string` | `5s` | 切换动画间隔 | -| duration | `string` | `0.5s` | 切换动画时长 | -| width | `string` | `auto` | 宽度 | -| height | `string` | `200px` | 高度 | -| controls | `array` | `['dots', 'arrows']` | 显示左右箭头、底部圆点索引 | -| controlsTheme | `string` | `light` | 左右箭头、底部圆点索引颜色,默认`light`,另有`dark`模式 | -| animation | `string` | fade | 切换动画效果,默认`fade`,另有`slide`模式 | +| 属性名 | 类型 | 默认值 | 说明 | +| ---------------------------- | --------- | ---------------------- | ------------------------------------------------------- | +| type | `string` | `"carousel"` | 指定为 Carousel 渲染器 | +| className | `string` | `"panel-default"` | 外层 Dom 的类名 | +| options | `array` | `[]` | 轮播面板数据 | +| options.image | `string` | | 图片链接 | +| options.imageClassName | `string` | | 图片类名 | +| options.title | `string` | | 图片标题 | +| options.titleClassName | `string` | | 图片标题类名 | +| options.description | `string` | | 图片描述 | +| options.descriptionClassName | `string` | | 图片描述类名 | +| options.html | `string` | | HTML 自定义,同[Tpl](./tpl)一致 | +| itemSchema | `object` | | 自定义`schema`来展示数据 | +| auto | `boolean` | `true` | 是否自动轮播 | +| interval | `string` | `5s` | 切换动画间隔 | +| duration | `string` | `0.5s` | 切换动画时长 | +| width | `string` | `auto` | 宽度 | +| height | `string` | `200px` | 高度 | +| controls | `array` | `['dots', 'arrows']` | 显示左右箭头、底部圆点索引 | +| controlsTheme | `string` | `light` | 左右箭头、底部圆点索引颜色,默认`light`,另有`dark`模式 | +| animation | `string` | fade | 切换动画效果,默认`fade`,另有`slide`模式 | +| thumbMode | `string` | `"cover" \| "contain"` | 图片默认缩放模式 | - `type` 请设置成 `carousel` - `className` 外层 Dom 的类名 @@ -116,3 +122,4 @@ itemSchema: { - `controls` 显示左右箭头、底部圆点索引,默认`['dots', 'arrows']` - `controlsTheme` 左右箭头、底部圆点索引颜色,默认`light`,另有`dark`模式 - `animation` 切换动画效果,默认`fade`,另有`slide`模式 +- `thumbMode` 图片默认缩放模式,可以配置 `"cover" | "contain"` diff --git a/docs/zh-CN/components/image.md b/docs/zh-CN/components/image.md index 27dab189c..7e03af0f7 100755 --- a/docs/zh-CN/components/image.md +++ b/docs/zh-CN/components/image.md @@ -104,20 +104,23 @@ order: 52 "type": "static-image", "name": "image", "label": "1比1", - "thumbRatio": "1:1" + "thumbRatio": "1:1", + "thumbMode": "cover" }, { "type": "static-image", "name": "image", "label": "4比3", - "thumbRatio": "4:3" + "thumbRatio": "4:3", + "thumbMode": "cover" }, { "type": "static-image", "name": "image", "label": "颜色", "label": "16比9", - "thumbRatio": "16:9" + "thumbRatio": "16:9", + "thumbMode": "cover" } ] } @@ -179,7 +182,29 @@ order: 52 "type": "image", "width": "200px", "height": "200px", - "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_216,l_1,f_jpg,q_80" + "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg@s_0,w_400,l_1,f_jpg,q_80" + } +} +``` + +## 原图模式 + +> since 1.2.3 + +默认图片为缩略图模式,可以通过配置 imageMode: "original" 修改为原图模式,原图模式为块状展示,宽度尽可能占满。 + +```schema +{ + "type": "page", + "data": { + "imageUrl": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg" + }, + "body": { + "type": "image", + "imageMode": "original", + "name": "imageUrl", + "title": "这是标题", + "imageCaption": "这是一段说明" } } ``` @@ -265,3 +290,4 @@ List 的内容、Card 卡片的内容配置同上 | enlargeCaption | `string` | | 放大预览的描述 | | thumbMode | `string` | `contain` | 预览图模式,可选:`'w-full'`, `'h-full'`, `'contain'`, `'cover'` | | thumbRatio | `string` | `1:1` | 预览图比例,可选:`'1:1'`, `'4:3'`, `'16:9'` | +| imageMode | `string` | `thumb` | 图片展示模式,可选:`'thumb'`, `'original'` 即:缩略图模式 或者 原图模式 | diff --git a/docs/zh-CN/components/images.md b/docs/zh-CN/components/images.md index bd7ff0c5c..37e0334f4 100755 --- a/docs/zh-CN/components/images.md +++ b/docs/zh-CN/components/images.md @@ -176,25 +176,25 @@ Array<{ }, { "image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692942/d8e4992057f9.jpeg@s_0,w_216,l_1,f_jpg,q_80", - "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg", + "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692942/d8e4992057f9.jpeg", "a": "aaa2", "b": "bbb2" }, { "image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693148/1314a2a3d3f6.jpeg@s_0,w_216,l_1,f_jpg,q_80", - "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg", + "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693148/1314a2a3d3f6.jpeg", "a": "aaa3", "b": "bbb3" }, { "image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693379/8f2e79f82be0.jpeg@s_0,w_216,l_1,f_jpg,q_80", - "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg", + "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693379/8f2e79f82be0.jpeg", "a": "aaa4", "b": "bbb4" }, { "image": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693566/552b175ef11d.jpeg@s_0,w_216,l_1,f_jpg,q_80", - "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395692722/4f3cb4202335.jpeg", + "src": "https://internal-amis-res.cdn.bcebos.com/images/2020-1/1578395693566/552b175ef11d.jpeg", "a": "aaa5", "b": "bbb5" } diff --git a/scss/components/_carousel.scss b/scss/components/_carousel.scss index d9052860b..5dcb24523 100644 --- a/scss/components/_carousel.scss +++ b/scss/components/_carousel.scss @@ -58,16 +58,20 @@ } &-container { + position: relative; width: 100%; height: 100%; - position: relative; overflow: hidden; .#{$ns}Carousel-item { width: 100%; height: 100%; position: absolute; - transition: ease-out all var(--Carousel-transitionDuration); + left: 0; + top: 0; + transition-duration: var(--Carousel-transitionDuration); + transition-timing-function: ease-out; + transition-property: transform, opacity; &.fade { opacity: 0; @@ -125,6 +129,16 @@ } } + &-image { + width: 100%; + height: 100%; + } + + &-image .#{$ns}Image-origin { + height: 100%; + width: 100%; + } + &-dotsControl { position: absolute; bottom: 0px; @@ -150,7 +164,9 @@ &-arrowsControl { position: absolute; width: 100%; - height: inherit; + height: 100%; + top: 0; + left: 0; z-index: 100; text-align: center; diff --git a/scss/components/_images.scss b/scss/components/_images.scss index 5db1ff1d4..ea84bb985 100644 --- a/scss/components/_images.scss +++ b/scss/components/_images.scss @@ -10,14 +10,28 @@ } .#{$ns}Image { - display: inline-block; border: var(--borderWidth) solid var(--borderColor); - padding: var(--gap-xs); + + &--thumb { + display: inline-block; + padding: var(--gap-xs); + } &-thumbWrap { position: relative; } + &-image { + display: block; + } + + &--original &-image { + max-width: 100%; + max-height: 100%; + width: auto; + margin: auto; + } + &-thumb { width: px2rem(110px); height: px2rem(110px); @@ -36,7 +50,12 @@ } &-info { + padding: 5px 10px; + } + + &--thumb &-info { width: px2rem(110px); + padding: 0; } &-thumb--4-3 { @@ -80,6 +99,12 @@ left: 0; object-fit: contain; } + + &-origin--contain > img { + width: 100% !important; + height: 100% !important; + object-fit: contain; + } } @supports (object-fit: cover) { @@ -92,6 +117,12 @@ left: 0; object-fit: cover; } + + &-origin--cover > img { + width: 100% !important; + height: 100% !important; + object-fit: cover; + } } &-caption { @@ -99,7 +130,8 @@ } &-title { - font-size: var(--fontSizeSm); + font-size: var(--fontSizeBase); + color: var(--text--loud-color); } &-overlay { @@ -138,7 +170,7 @@ } } -.#{$ns}ImageField { +.#{$ns}ImageField--thumb { display: inline-block; position: relative; @include clearfix(); diff --git a/src/renderers/Carousel.tsx b/src/renderers/Carousel.tsx index 95a171bc0..81427977e 100644 --- a/src/renderers/Carousel.tsx +++ b/src/renderers/Carousel.tsx @@ -15,6 +15,8 @@ import { } from '../utils/helper'; import {Icon} from '../components/icons'; import {BaseSchema, SchemaCollection, SchemaName, SchemaTpl} from '../Schema'; +import Html from '../components/Html'; +import Image from '../renderers/Image'; /** * Carousel 轮播图渲染器。 @@ -75,6 +77,11 @@ export interface CarouselSchema extends BaseSchema { name?: SchemaName; + /** + * 预览图模式 + */ + thumbMode?: 'contain' | 'cover'; + /** * 配置固定值 */ @@ -102,24 +109,32 @@ export interface CarouselState { } const defaultSchema = { - type: 'tpl', - tpl: ` - <% if (data.hasOwnProperty('image')) { %> -
- <% if (data.hasOwnProperty('title')) { %> -
<%= data.title %>
- <% } %> - <% if (data.hasOwnProperty('description')) { %> -
<%= data.description %>
- <% } %> - <% } else if (data.hasOwnProperty('html')) { %> - <%= data.html %> - <% } else if (data.hasOwnProperty('item')) { %> - <%= data.item %> - <% } else { %> - <%= '未找到渲染数据' %> - <% } %> - ` + component: (props: any) => { + const data = props.data || {}; + const thumbMode = props.thumbMode; + const cx = props.classnames; + + return ( + <> + {data.hasOwnProperty('image') ? ( + + ) : data.hasOwnProperty('html') ? ( + + ) : data.hasOwnProperty('item') ? ( + {data.item} + ) : ( +

+ )} + + ); + } }; export class Carousel extends React.Component { @@ -370,8 +385,9 @@ export class Carousel extends React.Component { > {render( `${current}/body`, - itemSchema ? itemSchema : defaultSchema, + itemSchema ? itemSchema : (defaultSchema as any), { + thumbMode: this.props.thumbMode, data: createObject( data, isObject(option) @@ -385,8 +401,6 @@ export class Carousel extends React.Component { }} ))} - {dots ? this.renderDots() : null} - {arrows ? this.renderArrows() : null}
); } @@ -397,6 +411,9 @@ export class Carousel extends React.Component { style={carouselStyles} > {body ? body : placeholder} + + {dots ? this.renderDots() : null} + {arrows ? this.renderArrows() : null}
); } diff --git a/src/renderers/Image.tsx b/src/renderers/Image.tsx index 04db3f650..8ad892ffe 100644 --- a/src/renderers/Image.tsx +++ b/src/renderers/Image.tsx @@ -56,7 +56,7 @@ export interface ImageSchema extends BaseSchema { /** * 是否显示尺寸。 */ - showDimensions?: boolean; + // showDimensions?: boolean; /** * 图片无法显示时的替换文本 @@ -90,6 +90,11 @@ export interface ImageSchema extends BaseSchema { caption?: SchemaTpl; + /** + * 图片展示模式,默认为缩略图模式、可以配置成原图模式 + */ + imageMode?: 'thumb' | 'original'; + /** * 预览图模式 */ @@ -135,44 +140,71 @@ export class ImageThumb extends React.Component { onLoad, enlargeAble, translate: __, - overlays + overlays, + imageMode } = this.props; return ( -
-
+
+ {imageMode === 'original' ? (
{alt}
- {enlargeAble || overlays ? ( -
- {enlargeAble ? ( - - - - ) : null} - {overlays} + ) : ( +
+
+ {alt}
- ) : null} -
+ {enlargeAble || overlays ? ( +
+ {enlargeAble ? ( + + + + ) : null} + {overlays} +
+ ) : null} +
+ )} + {title || caption ? (
{title ? ( @@ -204,6 +236,7 @@ export interface ImageFieldProps extends RendererProps { description?: string; enlargeTitle?: string; enlargeCaption?: string; + imageMode?: 'thumb' | 'original'; thumbMode: 'w-full' | 'h-full' | 'contain' | 'cover'; thumbRatio: '1:1' | '4:3' | '16:9'; originalSrc?: string; // 原图 @@ -219,7 +252,6 @@ export interface ImageFieldProps extends RendererProps { }, target: any ) => void; - showDimensions?: boolean; } export class ImageField extends React.Component { @@ -276,8 +308,7 @@ export class ImageField extends React.Component { placeholder, originalSrc, enlargeAble, - showDimensions, - name + imageMode } = this.props; const finnalSrc = src ? filter(src, data, '| raw') : ''; @@ -285,7 +316,15 @@ export class ImageField extends React.Component { finnalSrc || getPropValue(this.props) || defaultImage || imagePlaceholder; return ( -
+
{value ? ( { caption={filter(imageCaption, data)} thumbMode={thumbMode} thumbRatio={thumbRatio} - originalSrc={filter(originalSrc, data, '| raw')} + originalSrc={filter(originalSrc, data, '| raw') ?? value} enlargeAble={enlargeAble && value !== defaultImage} onEnlarge={this.handleEnlarge} - showDimensions={showDimensions} + imageMode={imageMode} /> ) : ( {placeholder}