mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [image-viewer] add toolbar slot (#19497)
* feat(components): [image-viewer] add toolbar slot * feat(docs): add docs * docs: update * docs: update * docs: update image viewer API types for clarity * docs: update custom toolbar version in image documentation to 2.9.4 * Update docs/examples/image/custom-toolbar.vue Co-authored-by: sea <45450994+warmthsea@users.noreply.github.com> * style: remove dividers * revert: style * docs: format --------- Co-authored-by: sea <45450994+warmthsea@users.noreply.github.com>
This commit is contained in:
@@ -63,6 +63,14 @@ image/manually-preview
|
||||
|
||||
:::
|
||||
|
||||
## Custom Toolbar ^(2.9.4)
|
||||
|
||||
:::demo Custom toolbar content by `slot = toolbar`
|
||||
|
||||
image/custom-toolbar
|
||||
|
||||
:::
|
||||
|
||||
## Image API
|
||||
|
||||
### Image Attributes
|
||||
@@ -100,12 +108,13 @@ image/manually-preview
|
||||
|
||||
### Image Slots
|
||||
|
||||
| Name | Description | Type |
|
||||
| ----------------- | -------------------------------------------------------- | ------------------------------------------------- |
|
||||
| placeholder | custom placeholder content when image hasn't loaded yet. | - |
|
||||
| error | custom image load failed content. | - |
|
||||
| viewer | custom content when image preview. | - |
|
||||
| progress ^(2.9.4) | custom progress content when image preview. | ^[object]`{ activeIndex: number, total: number }` |
|
||||
| Name | Description | Type |
|
||||
| ----------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| placeholder | custom placeholder content when image hasn't loaded yet. | - |
|
||||
| error | custom image load failed content. | - |
|
||||
| viewer | custom content when image preview. | - |
|
||||
| progress ^(2.9.4) | custom progress content when image preview. | ^[object]`{ activeIndex: number, total: number }` |
|
||||
| toolbar ^(2.9.4) | custom toolbar content when image preview. | ^[object]`{actions: (action: ImageViewerAction, options?: ImageViewerActionOptions ) => void, prev: ()=> void, next: () => void,reset: () => void, activeIndex: number }` |
|
||||
|
||||
## Image Viewer API
|
||||
|
||||
@@ -123,7 +132,7 @@ image/manually-preview
|
||||
| min-scale ^(2.4.0) | the min scale of the image viewer zoom event. | ^[number] | 0.2 |
|
||||
| max-scale ^(2.4.0) | the max scale of the image viewer zoom event. | ^[number] | 7 |
|
||||
| close-on-press-escape | whether the image-viewer can be closed by pressing ESC. | ^[boolean] | true |
|
||||
| show-progress ^(2.9.4) | whether to display the preview image progress content | ^[boolean] | false |
|
||||
| show-progress ^(2.9.4) | whether to display the preview image progress content | ^[boolean] | false |
|
||||
|
||||
### Image Viewer Events
|
||||
|
||||
@@ -139,3 +148,19 @@ image/manually-preview
|
||||
| -------------------- | ------------------------------- | ------------------------------------ |
|
||||
| setActiveItem | manually switch image | ^[Function]`(index: number) => void` |
|
||||
| showPreview ^(2.9.4) | manually open preview big image | ^[Function]`() => void` |
|
||||
|
||||
## Type Declarations
|
||||
|
||||
<details>
|
||||
<summary>Show declarations</summary>
|
||||
|
||||
```ts
|
||||
type ImageViewerAction = 'zoomIn' | 'zoomOut' | 'clockwise' | 'anticlockwise'
|
||||
type ImageViewerActionOptions = {
|
||||
enableTransition?: boolean
|
||||
zoomRate?: number
|
||||
rotateDeg?: number
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
76
docs/examples/image/custom-toolbar.vue
Normal file
76
docs/examples/image/custom-toolbar.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="demo-image__custom-toolbar">
|
||||
<el-image
|
||||
style="width: 100px; height: 100px"
|
||||
:src="url"
|
||||
:preview-src-list="srcList"
|
||||
fit="cover"
|
||||
>
|
||||
<template #toolbar="{ actions, prev, next, reset, activeIndex }">
|
||||
<el-icon @click="prev"><DArrowLeft /></el-icon>
|
||||
<el-icon @click="next"><DArrowRight /></el-icon>
|
||||
<el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
|
||||
<el-icon
|
||||
@click="actions('zoomIn', { enableTransition: false, zoomRate: 2 })"
|
||||
>
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
@click="
|
||||
actions('clockwise', { rotateDeg: 180, enableTransition: false })
|
||||
"
|
||||
>
|
||||
<RefreshRight />
|
||||
</el-icon>
|
||||
<el-icon @click="actions('anticlockwise')"><RefreshLeft /></el-icon>
|
||||
<el-icon @click="reset"><Refresh /></el-icon>
|
||||
<el-icon @click="download(activeIndex)"><Download /></el-icon>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ElIcon from '@element-plus/components/icon'
|
||||
import {
|
||||
DArrowLeft,
|
||||
DArrowRight,
|
||||
Download,
|
||||
Refresh,
|
||||
RefreshLeft,
|
||||
RefreshRight,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
const url =
|
||||
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg'
|
||||
const srcList = [
|
||||
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
|
||||
'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg',
|
||||
]
|
||||
|
||||
const download = (index: number) => {
|
||||
const url = srcList[index]
|
||||
const suffix = url.slice(url.lastIndexOf('.'))
|
||||
const filename = Date.now() + suffix
|
||||
|
||||
fetch(url)
|
||||
.then((response) => response.blob())
|
||||
.then((blob) => {
|
||||
const blobUrl = URL.createObjectURL(new Blob([blob]))
|
||||
const link = document.createElement('a')
|
||||
link.href = blobUrl
|
||||
link.download = filename
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
URL.revokeObjectURL(blobUrl)
|
||||
link.remove()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -49,23 +49,32 @@
|
||||
<!-- ACTIONS -->
|
||||
<div :class="[ns.e('btn'), ns.e('actions')]">
|
||||
<div :class="ns.e('actions__inner')">
|
||||
<el-icon @click="handleActions('zoomOut')">
|
||||
<ZoomOut />
|
||||
</el-icon>
|
||||
<el-icon @click="handleActions('zoomIn')">
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
<i :class="ns.e('actions__divider')" />
|
||||
<el-icon @click="toggleMode">
|
||||
<component :is="mode.icon" />
|
||||
</el-icon>
|
||||
<i :class="ns.e('actions__divider')" />
|
||||
<el-icon @click="handleActions('anticlockwise')">
|
||||
<RefreshLeft />
|
||||
</el-icon>
|
||||
<el-icon @click="handleActions('clockwise')">
|
||||
<RefreshRight />
|
||||
</el-icon>
|
||||
<slot
|
||||
name="toolbar"
|
||||
:actions="handleActions"
|
||||
:prev="prev"
|
||||
:next="next"
|
||||
:reset="toggleMode"
|
||||
:active-index="activeIndex"
|
||||
>
|
||||
<el-icon @click="handleActions('zoomOut')">
|
||||
<ZoomOut />
|
||||
</el-icon>
|
||||
<el-icon @click="handleActions('zoomIn')">
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
<i :class="ns.e('actions__divider')" />
|
||||
<el-icon @click="toggleMode">
|
||||
<component :is="mode.icon" />
|
||||
</el-icon>
|
||||
<i :class="ns.e('actions__divider')" />
|
||||
<el-icon @click="handleActions('anticlockwise')">
|
||||
<RefreshLeft />
|
||||
</el-icon>
|
||||
<el-icon @click="handleActions('clockwise')">
|
||||
<RefreshRight />
|
||||
</el-icon>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<!-- CANVAS -->
|
||||
|
||||
@@ -43,8 +43,11 @@
|
||||
<div v-if="$slots.viewer">
|
||||
<slot name="viewer" />
|
||||
</div>
|
||||
<template #progress="scoped">
|
||||
<slot name="progress" v-bind="scoped" />
|
||||
<template #progress="progress">
|
||||
<slot name="progress" v-bind="progress" />
|
||||
</template>
|
||||
<template #toolbar="toolbar">
|
||||
<slot name="toolbar" v-bind="toolbar" />
|
||||
</template>
|
||||
</image-viewer>
|
||||
</template>
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
user-select: none;
|
||||
|
||||
.#{$namespace}-icon {
|
||||
font-size: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -63,7 +62,6 @@
|
||||
left: 50%;
|
||||
bottom: 30px;
|
||||
transform: translateX(-50%);
|
||||
width: 282px;
|
||||
height: 44px;
|
||||
padding: 0 23px;
|
||||
background-color: getCssVar('text-color', 'regular');
|
||||
@@ -79,6 +77,12 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
gap: 22px;
|
||||
padding: 0 6px;
|
||||
|
||||
@include e(actions__divider) {
|
||||
margin: 0 -6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user