mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-09 04:31:35 +08:00
feat(image): toolbar
This commit is contained in:
parent
ab24d61f45
commit
67fea9eed3
@ -13,11 +13,18 @@ group
|
|||||||
|
|
||||||
### Image Props
|
### Image Props
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| ------ | ------------------ | ----------- | ----------- |
|
| ------------ | ------------------ | ----------- | ----------- |
|
||||||
| src | `string` | `undefined` | |
|
| src | `string` | `undefined` | |
|
||||||
| width | `string \| number` | `undefined` | |
|
| width | `string \| number` | `undefined` | |
|
||||||
| height | `string \| number` | `undefined` | |
|
| height | `string \| number` | `undefined` | |
|
||||||
|
| show-toolbar | `boolean` | `true` | |
|
||||||
|
|
||||||
|
### ImageGroup Props
|
||||||
|
|
||||||
|
| 名称 | 类型 | 默认值 | 说明 |
|
||||||
|
| ------------ | --------- | ------ | ---- |
|
||||||
|
| show-toolbar | `boolean` | `true` | |
|
||||||
|
|
||||||
## Slots
|
## Slots
|
||||||
|
|
||||||
|
@ -13,11 +13,18 @@ group
|
|||||||
|
|
||||||
### Image Props
|
### Image Props
|
||||||
|
|
||||||
| 名称 | 类型 | 默认值 | 说明 |
|
| 名称 | 类型 | 默认值 | 说明 |
|
||||||
| ------ | ------------------ | ----------- | ---- |
|
| ------------ | ------------------ | ----------- | ---- |
|
||||||
| src | `string` | `undefined` | |
|
| src | `string` | `undefined` | |
|
||||||
| width | `string \| number` | `undefined` | |
|
| width | `string \| number` | `undefined` | |
|
||||||
| height | `string \| number` | `undefined` | |
|
| height | `string \| number` | `undefined` | |
|
||||||
|
| show-toolbar | `boolean` | `true` | |
|
||||||
|
|
||||||
|
### ImageGroup Props
|
||||||
|
|
||||||
|
| 名称 | 类型 | 默认值 | 说明 |
|
||||||
|
| ------------ | --------- | ------ | ---- |
|
||||||
|
| show-toolbar | `boolean` | `true` | |
|
||||||
|
|
||||||
## Slots
|
## Slots
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
width: [String, Number],
|
width: [String, Number],
|
||||||
height: [String, Number],
|
height: [String, Number],
|
||||||
src: String
|
src: String,
|
||||||
|
showToolbar: { type: Boolean, default: true }
|
||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
const imageRef = ref<HTMLImageElement | null>(null)
|
const imageRef = ref<HTMLImageElement | null>(null)
|
||||||
@ -46,7 +47,7 @@ export default defineComponent({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<NImagePreview ref="previewInstRef">
|
<NImagePreview ref="previewInstRef" showToolbar={this.showToolbar}>
|
||||||
{{
|
{{
|
||||||
default: () => {
|
default: () => {
|
||||||
return (
|
return (
|
||||||
|
@ -17,6 +17,9 @@ ImagePreviewInst & { groupId: string }
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ImageGroup',
|
name: 'ImageGroup',
|
||||||
|
props: {
|
||||||
|
showToolbar: { type: Boolean, default: true }
|
||||||
|
},
|
||||||
setup () {
|
setup () {
|
||||||
let currentSrc: string | undefined
|
let currentSrc: string | undefined
|
||||||
const groupId = createId()
|
const groupId = createId()
|
||||||
@ -59,7 +62,12 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<NImagePreview ref="previewInstRef" onPrev={this.prev} onNext={this.next}>
|
<NImagePreview
|
||||||
|
ref="previewInstRef"
|
||||||
|
onPrev={this.prev}
|
||||||
|
onNext={this.next}
|
||||||
|
showToolbar={this.showToolbar}
|
||||||
|
>
|
||||||
{{
|
{{
|
||||||
default: () => renderSlot(this.$slots, 'default')
|
default: () => renderSlot(this.$slots, 'default')
|
||||||
}}
|
}}
|
||||||
|
@ -7,7 +7,10 @@ import {
|
|||||||
Transition,
|
Transition,
|
||||||
vShow,
|
vShow,
|
||||||
renderSlot,
|
renderSlot,
|
||||||
watch
|
watch,
|
||||||
|
computed,
|
||||||
|
CSSProperties,
|
||||||
|
PropType
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { zindexable } from 'vdirs'
|
import { zindexable } from 'vdirs'
|
||||||
import { useIsMounted } from 'vooks'
|
import { useIsMounted } from 'vooks'
|
||||||
@ -15,7 +18,16 @@ import { LazyTeleport } from 'vueuc'
|
|||||||
import { on, off } from 'evtd'
|
import { on, off } from 'evtd'
|
||||||
import { beforeNextFrameOnce } from 'seemly'
|
import { beforeNextFrameOnce } from 'seemly'
|
||||||
import { useTheme } from '../../_mixins'
|
import { useTheme } from '../../_mixins'
|
||||||
|
import { NBaseIcon } from '../../_internal'
|
||||||
import { imageLight } from '../styles'
|
import { imageLight } from '../styles'
|
||||||
|
import {
|
||||||
|
zoomInIcon,
|
||||||
|
zoomOutIcon,
|
||||||
|
rotateCounterclockwise,
|
||||||
|
rotateClockwise,
|
||||||
|
prevIcon,
|
||||||
|
nextIcon
|
||||||
|
} from './icons'
|
||||||
import style from './styles/index.cssr'
|
import style from './styles/index.cssr'
|
||||||
|
|
||||||
export interface ImagePreviewInst {
|
export interface ImagePreviewInst {
|
||||||
@ -27,28 +39,27 @@ export interface ImagePreviewInst {
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Image',
|
name: 'Image',
|
||||||
props: {
|
props: {
|
||||||
onNext: Function,
|
showToolbar: Boolean,
|
||||||
onPrev: Function
|
onNext: Function as PropType<() => void>,
|
||||||
|
onPrev: Function as PropType<() => void>
|
||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
useTheme('Image', 'Image', style, imageLight, {})
|
const themeRef = useTheme('Image', 'Image', style, imageLight, {})
|
||||||
let thumbnailEl: HTMLImageElement | null = null
|
let thumbnailEl: HTMLImageElement | null = null
|
||||||
const previewRef = ref<HTMLImageElement | null>(null)
|
const previewRef = ref<HTMLImageElement | null>(null)
|
||||||
|
const previewWrapperRef = ref<HTMLDivElement | null>(null)
|
||||||
const previewSrcRef = ref<string | undefined>(undefined)
|
const previewSrcRef = ref<string | undefined>(undefined)
|
||||||
const showRef = ref(false)
|
const showRef = ref(false)
|
||||||
const displayedRef = ref(false)
|
const displayedRef = ref(false)
|
||||||
|
|
||||||
function syncTransformOrigin (): void {
|
function syncTransformOrigin (): void {
|
||||||
const { value: preview } = previewRef
|
const { value: previewWrapper } = previewWrapperRef
|
||||||
if (!thumbnailEl || !preview) return
|
if (!thumbnailEl || !previewWrapper) return
|
||||||
|
const { style } = previewWrapper
|
||||||
const tbox = thumbnailEl.getBoundingClientRect()
|
const tbox = thumbnailEl.getBoundingClientRect()
|
||||||
const tx = tbox.left + tbox.width / 2
|
const tx = tbox.left + tbox.width / 2
|
||||||
const ty = tbox.top + tbox.height / 2
|
const ty = tbox.top + tbox.height / 2
|
||||||
preview.style.transform = 'none'
|
style.transformOrigin = `${tx}px ${ty}px`
|
||||||
const pbox = preview.getBoundingClientRect()
|
|
||||||
const px = pbox.left
|
|
||||||
const py = pbox.top
|
|
||||||
preview.style.transform = ''
|
|
||||||
preview.style.transformOrigin = `${tx - px}px ${ty - py}px`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeyup (e: KeyboardEvent): void {
|
function handleKeyup (e: KeyboardEvent): void {
|
||||||
@ -80,33 +91,102 @@ export default defineComponent({
|
|||||||
offsetY = clientY - startY
|
offsetY = clientY - startY
|
||||||
beforeNextFrameOnce(derivePreviewStyle)
|
beforeNextFrameOnce(derivePreviewStyle)
|
||||||
}
|
}
|
||||||
|
// avoid image move outside viewport
|
||||||
|
function getDerivedOffset (): {
|
||||||
|
offsetX: number
|
||||||
|
offsetY: number
|
||||||
|
} {
|
||||||
|
const { value: preview } = previewRef
|
||||||
|
if (!preview) return { offsetX: 0, offsetY: 0 }
|
||||||
|
const pbox = preview.getBoundingClientRect()
|
||||||
|
let nextOffsetX = 0
|
||||||
|
let nextOffsetY = 0
|
||||||
|
if (pbox.width <= window.innerWidth) {
|
||||||
|
nextOffsetX = 0
|
||||||
|
} else if (pbox.left > 0) {
|
||||||
|
nextOffsetX = (pbox.width - window.innerWidth) / 2
|
||||||
|
} else if (pbox.right < window.innerWidth) {
|
||||||
|
nextOffsetX = -(pbox.width - window.innerWidth) / 2
|
||||||
|
}
|
||||||
|
if (pbox.height <= window.innerHeight) {
|
||||||
|
nextOffsetY = 0
|
||||||
|
} else if (pbox.top > 0) {
|
||||||
|
nextOffsetY = (pbox.height - window.innerHeight) / 2
|
||||||
|
} else if (pbox.bottom < window.innerHeight) {
|
||||||
|
nextOffsetY = -(pbox.height - window.innerHeight) / 2
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
offsetX: nextOffsetX,
|
||||||
|
offsetY: nextOffsetY
|
||||||
|
}
|
||||||
|
}
|
||||||
function handleMouseUp (): void {
|
function handleMouseUp (): void {
|
||||||
off('mousemove', document, handleMouseMove)
|
off('mousemove', document, handleMouseMove)
|
||||||
off('mouseup', document, handleMouseUp)
|
off('mouseup', document, handleMouseUp)
|
||||||
dragging = false
|
dragging = false
|
||||||
beforeNextFrameOnce(derivePreviewStyle)
|
const offset = getDerivedOffset()
|
||||||
|
offsetX = offset.offsetX
|
||||||
|
offsetY = offset.offsetY
|
||||||
|
derivePreviewStyle()
|
||||||
}
|
}
|
||||||
function handlePreviewMousedown (e: MouseEvent): void {
|
function handlePreviewMousedown (e: MouseEvent): void {
|
||||||
const { clientX, clientY } = e
|
const { clientX, clientY } = e
|
||||||
dragging = true
|
dragging = true
|
||||||
offsetX = 0
|
startX = clientX - offsetX
|
||||||
offsetY = 0
|
startY = clientY - offsetY
|
||||||
startX = clientX
|
derivePreviewStyle()
|
||||||
startY = clientY
|
|
||||||
beforeNextFrameOnce(derivePreviewStyle)
|
|
||||||
on('mousemove', document, handleMouseMove)
|
on('mousemove', document, handleMouseMove)
|
||||||
on('mouseup', document, handleMouseUp)
|
on('mouseup', document, handleMouseUp)
|
||||||
}
|
}
|
||||||
function derivePreviewStyle (): void {
|
|
||||||
|
let scale = 1
|
||||||
|
let rotate = 0
|
||||||
|
function rotateCounterclockwise (): void {
|
||||||
|
rotate -= 90
|
||||||
|
derivePreviewStyle()
|
||||||
|
}
|
||||||
|
function rotateClockwise (): void {
|
||||||
|
rotate += 90
|
||||||
|
derivePreviewStyle()
|
||||||
|
}
|
||||||
|
function zoomIn (): void {
|
||||||
|
if (scale < 3) {
|
||||||
|
scale += 0.5
|
||||||
|
derivePreviewStyle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function zoomOut (): void {
|
||||||
|
if (scale > 0.5) {
|
||||||
|
scale -= 0.5
|
||||||
|
derivePreviewStyle(false)
|
||||||
|
const offset = getDerivedOffset()
|
||||||
|
scale += 0.5
|
||||||
|
derivePreviewStyle(false)
|
||||||
|
scale -= 0.5
|
||||||
|
offsetX = offset.offsetX
|
||||||
|
offsetY = offset.offsetY
|
||||||
|
derivePreviewStyle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function derivePreviewStyle (transition: boolean = true): void {
|
||||||
const { value: preview } = previewRef
|
const { value: preview } = previewRef
|
||||||
if (!preview) return
|
if (!preview) return
|
||||||
const { style } = preview
|
const { style } = preview
|
||||||
|
const transformStyle = `transform-origin: center; transform: translateX(${offsetX}px) translateY(${offsetY}px) rotate(${rotate}deg) scale(${scale});`
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
style.cssText = `cursor: grabbing; transition: none; transform: translateX(${offsetX}px) translateY(${offsetY}px);`
|
style.cssText = 'cursor: grabbing; transition: none;' + transformStyle
|
||||||
} else {
|
} else {
|
||||||
style.cssText = 'cursor: grab;'
|
style.cssText =
|
||||||
|
'cursor: grab;' +
|
||||||
|
transformStyle +
|
||||||
|
(transition ? '' : 'transition: none;')
|
||||||
|
}
|
||||||
|
if (!transition) {
|
||||||
|
void preview.offsetHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleShow (): void {
|
function toggleShow (): void {
|
||||||
showRef.value = !showRef.value
|
showRef.value = !showRef.value
|
||||||
displayedRef.value = true
|
displayedRef.value = true
|
||||||
@ -123,6 +203,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
previewRef,
|
previewRef,
|
||||||
|
previewWrapperRef,
|
||||||
previewSrc: previewSrcRef,
|
previewSrc: previewSrcRef,
|
||||||
show: showRef,
|
show: showRef,
|
||||||
appear: useIsMounted(),
|
appear: useIsMounted(),
|
||||||
@ -130,9 +211,25 @@ export default defineComponent({
|
|||||||
handlePreviewMousedown,
|
handlePreviewMousedown,
|
||||||
syncTransformOrigin,
|
syncTransformOrigin,
|
||||||
handleAfterLeave: () => {
|
handleAfterLeave: () => {
|
||||||
|
rotate = 0
|
||||||
|
scale = 1
|
||||||
displayedRef.value = false
|
displayedRef.value = false
|
||||||
},
|
},
|
||||||
...exposedMethods
|
zoomIn,
|
||||||
|
zoomOut,
|
||||||
|
rotateCounterclockwise,
|
||||||
|
rotateClockwise,
|
||||||
|
...exposedMethods,
|
||||||
|
cssVars: computed(() => {
|
||||||
|
const {
|
||||||
|
common: { cubicBezierEaseInOut },
|
||||||
|
self: { iconColor }
|
||||||
|
} = themeRef.value
|
||||||
|
return {
|
||||||
|
'--bezier': cubicBezierEaseInOut,
|
||||||
|
'--icon-color': iconColor
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
@ -144,7 +241,10 @@ export default defineComponent({
|
|||||||
default: () =>
|
default: () =>
|
||||||
this.show || this.displayed
|
this.show || this.displayed
|
||||||
? withDirectives(
|
? withDirectives(
|
||||||
<div class="n-image-preview-container">
|
<div
|
||||||
|
class="n-image-preview-container"
|
||||||
|
style={this.cssVars as CSSProperties}
|
||||||
|
>
|
||||||
<Transition
|
<Transition
|
||||||
name="n-fade-in-transition"
|
name="n-fade-in-transition"
|
||||||
appear={this.appear}
|
appear={this.appear}
|
||||||
@ -159,6 +259,44 @@ export default defineComponent({
|
|||||||
) : null
|
) : null
|
||||||
}}
|
}}
|
||||||
</Transition>
|
</Transition>
|
||||||
|
{this.showToolbar ? (
|
||||||
|
<Transition
|
||||||
|
name="n-fade-in-transition"
|
||||||
|
appear={this.appear}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () =>
|
||||||
|
this.show ? (
|
||||||
|
<div class="n-image-preview-toolbar">
|
||||||
|
{this.onPrev ? (
|
||||||
|
<>
|
||||||
|
<NBaseIcon onClick={this.onPrev}>
|
||||||
|
{{ default: () => prevIcon }}
|
||||||
|
</NBaseIcon>
|
||||||
|
<NBaseIcon onClick={this.onNext}>
|
||||||
|
{{ default: () => nextIcon }}
|
||||||
|
</NBaseIcon>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
<NBaseIcon
|
||||||
|
onClick={this.rotateCounterclockwise}
|
||||||
|
>
|
||||||
|
{{ default: () => rotateCounterclockwise }}
|
||||||
|
</NBaseIcon>
|
||||||
|
<NBaseIcon onClick={this.rotateClockwise}>
|
||||||
|
{{ default: () => rotateClockwise }}
|
||||||
|
</NBaseIcon>
|
||||||
|
<NBaseIcon onClick={this.zoomOut}>
|
||||||
|
{{ default: () => zoomOutIcon }}
|
||||||
|
</NBaseIcon>
|
||||||
|
<NBaseIcon onClick={this.zoomIn}>
|
||||||
|
{{ default: () => zoomInIcon }}
|
||||||
|
</NBaseIcon>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
}}
|
||||||
|
</Transition>
|
||||||
|
) : null}
|
||||||
<Transition
|
<Transition
|
||||||
name="n-fade-in-scale-up-transition"
|
name="n-fade-in-scale-up-transition"
|
||||||
onAfterLeave={this.handleAfterLeave}
|
onAfterLeave={this.handleAfterLeave}
|
||||||
@ -169,13 +307,18 @@ export default defineComponent({
|
|||||||
{{
|
{{
|
||||||
default: () =>
|
default: () =>
|
||||||
withDirectives(
|
withDirectives(
|
||||||
<img
|
<div
|
||||||
draggable={false}
|
class="n-image-preview-wrapper"
|
||||||
onMousedown={this.handlePreviewMousedown}
|
ref="previewWrapperRef"
|
||||||
class="n-image-preview"
|
>
|
||||||
src={this.previewSrc}
|
<img
|
||||||
ref="previewRef"
|
draggable={false}
|
||||||
/>,
|
onMousedown={this.handlePreviewMousedown}
|
||||||
|
class="n-image-preview"
|
||||||
|
src={this.previewSrc}
|
||||||
|
ref="previewRef"
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
[[vShow, this.show]]
|
[[vShow, this.show]]
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
71
src/image/src/icons.tsx
Normal file
71
src/image/src/icons.tsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { h } from 'vue'
|
||||||
|
|
||||||
|
export const rotateClockwise = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 12.7916 15.3658 15.2026 13 16.3265V14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5V17.5C12 17.7761 12.2239 18 12.5 18H15.5C15.7761 18 16 17.7761 16 17.5C16 17.2239 15.7761 17 15.5 17H13.8758C16.3346 15.6357 18 13.0128 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 10.2761 2.22386 10.5 2.5 10.5C2.77614 10.5 3 10.2761 3 10Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M10 12C11.1046 12 12 11.1046 12 10C12 8.89543 11.1046 8 10 8C8.89543 8 8 8.89543 8 10C8 11.1046 8.89543 12 10 12ZM10 11C9.44772 11 9 10.5523 9 10C9 9.44772 9.44772 9 10 9C10.5523 9 11 9.44772 11 10C11 10.5523 10.5523 11 10 11Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const rotateCounterclockwise = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M17 10C17 6.13401 13.866 3 10 3C6.13401 3 3 6.13401 3 10C3 12.7916 4.63419 15.2026 7 16.3265V14.5C7 14.2239 7.22386 14 7.5 14C7.77614 14 8 14.2239 8 14.5V17.5C8 17.7761 7.77614 18 7.5 18H4.5C4.22386 18 4 17.7761 4 17.5C4 17.2239 4.22386 17 4.5 17H6.12422C3.66539 15.6357 2 13.0128 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10C18 10.2761 17.7761 10.5 17.5 10.5C17.2239 10.5 17 10.2761 17 10Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M10 12C8.89543 12 8 11.1046 8 10C8 8.89543 8.89543 8 10 8C11.1046 8 12 8.89543 12 10C12 11.1046 11.1046 12 10 12ZM10 11C10.5523 11 11 10.5523 11 10C11 9.44772 10.5523 9 10 9C9.44772 9 9 9.44772 9 10C9 10.5523 9.44772 11 10 11Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const zoomInIcon = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M11.5 8.5C11.5 8.22386 11.2761 8 11 8H9V6C9 5.72386 8.77614 5.5 8.5 5.5C8.22386 5.5 8 5.72386 8 6V8H6C5.72386 8 5.5 8.22386 5.5 8.5C5.5 8.77614 5.72386 9 6 9H8V11C8 11.2761 8.22386 11.5 8.5 11.5C8.77614 11.5 9 11.2761 9 11V9H11C11.2761 9 11.5 8.77614 11.5 8.5Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M8.5 3C11.5376 3 14 5.46243 14 8.5C14 9.83879 13.5217 11.0659 12.7266 12.0196L16.8536 16.1464C17.0488 16.3417 17.0488 16.6583 16.8536 16.8536C16.68 17.0271 16.4106 17.0464 16.2157 16.9114L16.1464 16.8536L12.0196 12.7266C11.0659 13.5217 9.83879 14 8.5 14C5.46243 14 3 11.5376 3 8.5C3 5.46243 5.46243 3 8.5 3ZM8.5 4C6.01472 4 4 6.01472 4 8.5C4 10.9853 6.01472 13 8.5 13C10.9853 13 13 10.9853 13 8.5C13 6.01472 10.9853 4 8.5 4Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const zoomOutIcon = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M11 8C11.2761 8 11.5 8.22386 11.5 8.5C11.5 8.77614 11.2761 9 11 9H6C5.72386 9 5.5 8.77614 5.5 8.5C5.5 8.22386 5.72386 8 6 8H11Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M14 8.5C14 5.46243 11.5376 3 8.5 3C5.46243 3 3 5.46243 3 8.5C3 11.5376 5.46243 14 8.5 14C9.83879 14 11.0659 13.5217 12.0196 12.7266L16.1464 16.8536L16.2157 16.9114C16.4106 17.0464 16.68 17.0271 16.8536 16.8536C17.0488 16.6583 17.0488 16.3417 16.8536 16.1464L12.7266 12.0196C13.5217 11.0659 14 9.83879 14 8.5ZM4 8.5C4 6.01472 6.01472 4 8.5 4C10.9853 4 13 6.01472 13 8.5C13 10.9853 10.9853 13 8.5 13C6.01472 13 4 10.9853 4 8.5Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const prevIcon = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M6 5C5.75454 5 5.55039 5.17688 5.50806 5.41012L5.5 5.5V14.5C5.5 14.7761 5.72386 15 6 15C6.24546 15 6.44961 14.8231 6.49194 14.5899L6.5 14.5V5.5C6.5 5.22386 6.27614 5 6 5ZM13.8536 5.14645C13.68 4.97288 13.4106 4.9536 13.2157 5.08859L13.1464 5.14645L8.64645 9.64645C8.47288 9.82001 8.4536 10.0894 8.58859 10.2843L8.64645 10.3536L13.1464 14.8536C13.3417 15.0488 13.6583 15.0488 13.8536 14.8536C14.0271 14.68 14.0464 14.4106 13.9114 14.2157L13.8536 14.1464L9.70711 10L13.8536 5.85355C14.0488 5.65829 14.0488 5.34171 13.8536 5.14645Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const nextIcon = (
|
||||||
|
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M13.5 5C13.7455 5 13.9496 5.17688 13.9919 5.41012L14 5.5V14.5C14 14.7761 13.7761 15 13.5 15C13.2545 15 13.0504 14.8231 13.0081 14.5899L13 14.5V5.5C13 5.22386 13.2239 5 13.5 5ZM5.64645 5.14645C5.82001 4.97288 6.08944 4.9536 6.28431 5.08859L6.35355 5.14645L10.8536 9.64645C11.0271 9.82001 11.0464 10.0894 10.9114 10.2843L10.8536 10.3536L6.35355 14.8536C6.15829 15.0488 5.84171 15.0488 5.64645 14.8536C5.47288 14.68 5.4536 14.4106 5.58859 14.2157L5.64645 14.1464L9.79289 10L5.64645 5.85355C5.45118 5.65829 5.45118 5.34171 5.64645 5.14645Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
)
|
@ -1,7 +1,10 @@
|
|||||||
import { c, cB } from '../../../_utils/cssr'
|
import { c, cB } from '../../../_utils/cssr'
|
||||||
import fadeInTransition from '../../../_styles/transitions/fade-in'
|
import fadeInTransition from '../../../_styles/transitions/fade-in'
|
||||||
import fadeInScaleUpTransiton from '../../../_styles/transitions/fade-in-scale-up'
|
import fadeInzoomInTransiton from '../../../_styles/transitions/fade-in-scale-up'
|
||||||
|
|
||||||
|
// vars:
|
||||||
|
// --icon-color
|
||||||
|
// --bezier
|
||||||
export default c([
|
export default c([
|
||||||
c('body >', [
|
c('body >', [
|
||||||
cB('image-container', 'position: fixed;')
|
cB('image-container', 'position: fixed;')
|
||||||
@ -25,13 +28,47 @@ export default c([
|
|||||||
`, [
|
`, [
|
||||||
fadeInTransition()
|
fadeInTransition()
|
||||||
]),
|
]),
|
||||||
|
cB('image-preview-toolbar', `
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border-radius: 24px;
|
||||||
|
height: 48px;
|
||||||
|
bottom: 40px;
|
||||||
|
padding: 0 12px;
|
||||||
|
background: rgba(0, 0, 0, .35);
|
||||||
|
color: var(--icon-color);
|
||||||
|
transition: color .3s var(--bezier);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`, [
|
||||||
|
cB('base-icon', `
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 28px;
|
||||||
|
cursor: pointer;
|
||||||
|
`),
|
||||||
|
fadeInTransition()
|
||||||
|
]),
|
||||||
|
cB('image-preview-wrapper', `
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
pointer-events: none;
|
||||||
|
`, [
|
||||||
|
fadeInzoomInTransiton()
|
||||||
|
]),
|
||||||
cB('image-preview', `
|
cB('image-preview', `
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: all;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
transition: transform .3s cubic-bezier(.4, 0, .2, 1);
|
max-width: 100vw;
|
||||||
`, [
|
transition: transform .3s var(--bezier);
|
||||||
fadeInScaleUpTransiton()
|
`),
|
||||||
]),
|
|
||||||
cB('image', `
|
cB('image', `
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -4,7 +4,10 @@ import type { ImageTheme } from './light'
|
|||||||
export const imageDark: ImageTheme = {
|
export const imageDark: ImageTheme = {
|
||||||
name: 'Image',
|
name: 'Image',
|
||||||
common: commonDark,
|
common: commonDark,
|
||||||
self: () => {
|
self: (vars) => {
|
||||||
return {}
|
const { textColor2 } = vars
|
||||||
|
return {
|
||||||
|
iconColor: textColor2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ import { createTheme } from '../../_mixins'
|
|||||||
import { commonLight } from '../../_styles/common'
|
import { commonLight } from '../../_styles/common'
|
||||||
|
|
||||||
function self () {
|
function self () {
|
||||||
return {}
|
return {
|
||||||
|
iconColor: 'rgba(255, 255, 255, .9)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const imageLight = createTheme({
|
export const imageLight = createTheme({
|
||||||
name: 'Image',
|
name: 'Image',
|
||||||
common: commonLight,
|
common: commonLight,
|
||||||
|
Loading…
Reference in New Issue
Block a user