Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
e23bd269
提交
e23bd269
authored
7月 26, 2021
作者:
无木
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(preview): add more features
为Preview组件添加新的属性及事件
上级
98749ec6
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
149 行增加
和
14 行删除
+149
-14
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+4
-0
Functional.vue
src/components/Preview/src/Functional.vue
+118
-8
functional.ts
src/components/Preview/src/functional.ts
+2
-5
typing.ts
src/components/Preview/src/typing.ts
+19
-0
index.vue
src/views/demo/feat/img-preview/index.vue
+6
-1
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
e23bd269
### ✨ Features
-
**Preview**
添加新的属性及事件
### 🐛 Bug Fixes
### 🐛 Bug Fixes
-
**ApiTreeSelect**
修复未能正确监听
`params`
变化的问题
-
**ApiTreeSelect**
修复未能正确监听
`params`
变化的问题
...
...
src/components/Preview/src/Functional.vue
浏览文件 @
e23bd269
...
@@ -38,13 +38,33 @@
...
@@ -38,13 +38,33 @@
type
:
Number
as
PropType
<
number
>
,
type
:
Number
as
PropType
<
number
>
,
default
:
0
,
default
:
0
,
},
},
scaleStep
:
{
type
:
Number
as
PropType
<
number
>
,
},
defaultWidth
:
{
type
:
Number
as
PropType
<
number
>
,
},
maskClosable
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
},
rememberState
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
},
};
};
const
prefixCls
=
'img-preview'
;
const
prefixCls
=
'img-preview'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'ImagePreview'
,
name
:
'ImagePreview'
,
props
,
props
,
setup
(
props
:
Props
)
{
emits
:
[
'img-load'
,
'img-error'
],
setup
(
props
:
Props
,
{
expose
,
emit
})
{
interface
stateInfo
{
scale
:
number
;
rotate
:
number
;
top
:
number
;
left
:
number
;
}
const
stateMap
=
new
Map
<
string
,
stateInfo
>
();
const
imgState
=
reactive
<
ImgState
>
({
const
imgState
=
reactive
<
ImgState
>
({
currentUrl
:
''
,
currentUrl
:
''
,
imgScale
:
1
,
imgScale
:
1
,
...
@@ -96,6 +116,14 @@
...
@@ -96,6 +116,14 @@
};
};
}
}
const
getScaleStep
=
computed
(()
=>
{
if
(
props
.
scaleStep
>
0
&&
props
.
scaleStep
<
100
)
{
return
props
.
scaleStep
/
100
;
}
else
{
return
imgState
.
imgScale
/
10
;
}
});
// 监听鼠标滚轮
// 监听鼠标滚轮
function
scrollFunc
(
e
:
any
)
{
function
scrollFunc
(
e
:
any
)
{
e
=
e
||
window
.
event
;
e
=
e
||
window
.
event
;
...
@@ -104,11 +132,11 @@
...
@@ -104,11 +132,11 @@
e
.
preventDefault
();
e
.
preventDefault
();
if
(
e
.
delta
>
0
)
{
if
(
e
.
delta
>
0
)
{
// 滑轮向上滚动
// 滑轮向上滚动
scaleFunc
(
0.015
);
scaleFunc
(
getScaleStep
.
value
);
}
}
if
(
e
.
delta
<
0
)
{
if
(
e
.
delta
<
0
)
{
// 滑轮向下滚动
// 滑轮向下滚动
scaleFunc
(
-
0.015
);
scaleFunc
(
-
getScaleStep
.
value
);
}
}
}
}
// 缩放函数
// 缩放函数
...
@@ -134,11 +162,54 @@
...
@@ -134,11 +162,54 @@
imgState
.
status
=
StatueEnum
.
LOADING
;
imgState
.
status
=
StatueEnum
.
LOADING
;
const
img
=
new
Image
();
const
img
=
new
Image
();
img
.
src
=
url
;
img
.
src
=
url
;
img
.
onload
=
()
=>
{
img
.
onload
=
(
e
:
Event
)
=>
{
if
(
imgState
.
currentUrl
!==
url
)
{
const
ele
:
HTMLElement
[]
=
e
.
composedPath
();
if
(
props
.
rememberState
)
{
// 保存当前图片的缩放信息
stateMap
.
set
(
imgState
.
currentUrl
,
{
scale
:
imgState
.
imgScale
,
top
:
imgState
.
imgTop
,
left
:
imgState
.
imgLeft
,
rotate
:
imgState
.
imgRotate
,
});
// 如果之前已存储缩放信息,就应用
const
stateInfo
=
stateMap
.
get
(
url
);
if
(
stateInfo
)
{
imgState
.
imgScale
=
stateInfo
.
scale
;
imgState
.
imgTop
=
stateInfo
.
top
;
imgState
.
imgRotate
=
stateInfo
.
rotate
;
imgState
.
imgLeft
=
stateInfo
.
left
;
}
else
{
initState
();
if
(
props
.
defaultWidth
)
{
imgState
.
imgScale
=
props
.
defaultWidth
/
ele
[
0
].
naturalWidth
;
}
}
}
else
{
if
(
props
.
defaultWidth
)
{
imgState
.
imgScale
=
props
.
defaultWidth
/
ele
[
0
].
naturalWidth
;
}
}
ele
&&
emit
(
'img-load'
,
{
index
:
imgState
.
currentIndex
,
dom
:
ele
[
0
]
as
HTMLImageElement
,
url
,
});
}
imgState
.
currentUrl
=
url
;
imgState
.
currentUrl
=
url
;
imgState
.
status
=
StatueEnum
.
DONE
;
imgState
.
status
=
StatueEnum
.
DONE
;
};
};
img
.
onerror
=
()
=>
{
img
.
onerror
=
(
e
:
Event
)
=>
{
const
ele
:
EventTarget
[]
=
e
.
composedPath
();
ele
&&
emit
(
'img-error'
,
{
index
:
imgState
.
currentIndex
,
dom
:
ele
[
0
]
as
HTMLImageElement
,
url
,
});
imgState
.
status
=
StatueEnum
.
FAIL
;
imgState
.
status
=
StatueEnum
.
FAIL
;
};
};
}
}
...
@@ -146,6 +217,10 @@
...
@@ -146,6 +217,10 @@
// 关闭
// 关闭
function
handleClose
(
e
:
MouseEvent
)
{
function
handleClose
(
e
:
MouseEvent
)
{
e
&&
e
.
stopPropagation
();
e
&&
e
.
stopPropagation
();
close
();
}
function
close
()
{
imgState
.
show
=
false
;
imgState
.
show
=
false
;
// 移除火狐浏览器下的鼠标滚动事件
// 移除火狐浏览器下的鼠标滚动事件
document
.
body
.
removeEventListener
(
'DOMMouseScroll'
,
scrollFunc
);
document
.
body
.
removeEventListener
(
'DOMMouseScroll'
,
scrollFunc
);
...
@@ -158,6 +233,19 @@
...
@@ -158,6 +233,19 @@
initState
();
initState
();
}
}
expose
({
resume
,
close
,
prev
:
handleChange
.
bind
(
null
,
'left'
),
next
:
handleChange
.
bind
(
null
,
'right'
),
setScale
:
(
scale
:
number
)
=>
{
if
(
scale
>
0
&&
scale
<=
10
)
imgState
.
imgScale
=
scale
;
},
setRotate
:
(
rotate
:
number
)
=>
{
imgState
.
imgRotate
=
rotate
;
},
}
as
PreviewActions
);
// 上一页下一页
// 上一页下一页
function
handleChange
(
direction
:
'left'
|
'right'
)
{
function
handleChange
(
direction
:
'left'
|
'right'
)
{
const
{
currentIndex
}
=
imgState
;
const
{
currentIndex
}
=
imgState
;
...
@@ -205,6 +293,7 @@
...
@@ -205,6 +293,7 @@
transform
:
`scale(
${
imgScale
}
) rotate(
${
imgRotate
}
deg)`
,
transform
:
`scale(
${
imgScale
}
) rotate(
${
imgRotate
}
deg)`
,
marginTop
:
`
${
imgTop
}
px`
,
marginTop
:
`
${
imgTop
}
px`
,
marginLeft
:
`
${
imgLeft
}
px`
,
marginLeft
:
`
${
imgLeft
}
px`
,
maxWidth
:
props
.
defaultWidth
?
'unset'
:
'100%'
,
};
};
});
});
...
@@ -222,6 +311,16 @@
...
@@ -222,6 +311,16 @@
}
}
});
});
const
handleMaskClick
=
(
e
:
MouseEvent
)
=>
{
if
(
props
.
maskClosable
&&
e
.
target
&&
(
e
.
target
as
HTMLDivElement
).
classList
.
contains
(
`
${
prefixCls
}
-content`
)
)
{
handleClose
(
e
);
}
};
const
renderClose
=
()
=>
{
const
renderClose
=
()
=>
{
return
(
return
(
<
div
class
=
{
`
${
prefixCls
}
__close`
}
onClick
=
{
handleClose
}
>
<
div
class
=
{
`
${
prefixCls
}
__close`
}
onClick
=
{
handleClose
}
>
...
@@ -246,10 +345,16 @@
...
@@ -246,10 +345,16 @@
const
renderController
=
()
=>
{
const
renderController
=
()
=>
{
return
(
return
(
<
div
class
=
{
`
${
prefixCls
}
__controller`
}
>
<
div
class
=
{
`
${
prefixCls
}
__controller`
}
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{()
=>
scaleFunc
(
-
0.15
)}
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{()
=>
scaleFunc
(
-
getScaleStep
.
value
)}
>
<
img
src
=
{
unScaleSvg
}
/
>
<
img
src
=
{
unScaleSvg
}
/
>
<
/div
>
<
/div
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{()
=>
scaleFunc
(
0.15
)}
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{()
=>
scaleFunc
(
getScaleStep
.
value
)}
>
<
img
src
=
{
scaleSvg
}
/
>
<
img
src
=
{
scaleSvg
}
/
>
<
/div
>
<
/div
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{
resume
}
>
<
div
class
=
{
`
${
prefixCls
}
__controller-item`
}
onClick
=
{
resume
}
>
...
@@ -279,7 +384,12 @@
...
@@ -279,7 +384,12 @@
return
()
=>
{
return
()
=>
{
return
(
return
(
imgState
.
show
&&
(
imgState
.
show
&&
(
<
div
class
=
{
prefixCls
}
ref
=
{
wrapElRef
}
onMouseup
=
{
handleMouseUp
}
>
<
div
class
=
{
prefixCls
}
ref
=
{
wrapElRef
}
onMouseup
=
{
handleMouseUp
}
onClick
=
{
handleMaskClick
}
>
<
div
class
=
{
`
${
prefixCls
}
-content`
}
>
<
div
class
=
{
`
${
prefixCls
}
-content`
}
>
{
/*<Spin*/
}
{
/*<Spin*/
}
{
/* indicator={<LoadingOutlined style="font-size: 24px" spin />}*/
}
{
/* indicator={<LoadingOutlined style="font-size: 24px" spin />}*/
}
...
...
src/components/Preview/src/functional.ts
浏览文件 @
e23bd269
...
@@ -6,15 +6,12 @@ import { createVNode, render } from 'vue';
...
@@ -6,15 +6,12 @@ import { createVNode, render } from 'vue';
let
instance
:
ReturnType
<
typeof
createVNode
>
|
null
=
null
;
let
instance
:
ReturnType
<
typeof
createVNode
>
|
null
=
null
;
export
function
createImgPreview
(
options
:
Options
)
{
export
function
createImgPreview
(
options
:
Options
)
{
if
(
!
isClient
)
return
;
if
(
!
isClient
)
return
;
const
{
imageList
,
show
=
true
,
index
=
0
}
=
options
;
const
propsData
:
Partial
<
Props
>
=
{};
const
propsData
:
Partial
<
Props
>
=
{};
const
container
=
document
.
createElement
(
'div'
);
const
container
=
document
.
createElement
(
'div'
);
propsData
.
imageList
=
imageList
;
Object
.
assign
(
propsData
,
{
show
:
true
,
index
:
0
,
scaleStep
:
100
},
options
);
propsData
.
show
=
show
;
propsData
.
index
=
index
;
instance
=
createVNode
(
ImgPreview
,
propsData
);
instance
=
createVNode
(
ImgPreview
,
propsData
);
render
(
instance
,
container
);
render
(
instance
,
container
);
document
.
body
.
appendChild
(
container
);
document
.
body
.
appendChild
(
container
);
return
instance
.
component
?.
exposed
;
}
}
src/components/Preview/src/typing.ts
浏览文件 @
e23bd269
...
@@ -2,6 +2,12 @@ export interface Options {
...
@@ -2,6 +2,12 @@ export interface Options {
show
?:
boolean
;
show
?:
boolean
;
imageList
:
string
[];
imageList
:
string
[];
index
?:
number
;
index
?:
number
;
scaleStep
?:
number
;
defaultWidth
?:
number
;
maskClosable
?:
boolean
;
rememberState
?:
boolean
;
onImgLoad
?:
(
img
:
HTMLImageElement
)
=>
void
;
onImgError
?:
(
img
:
HTMLImageElement
)
=>
void
;
}
}
export
interface
Props
{
export
interface
Props
{
...
@@ -9,6 +15,19 @@ export interface Props {
...
@@ -9,6 +15,19 @@ export interface Props {
instance
:
Props
;
instance
:
Props
;
imageList
:
string
[];
imageList
:
string
[];
index
:
number
;
index
:
number
;
scaleStep
:
number
;
defaultWidth
:
number
;
maskClosable
:
boolean
;
rememberState
:
boolean
;
}
export
interface
PreviewActions
{
resume
:
()
=>
void
;
close
:
()
=>
void
;
prev
:
()
=>
void
;
next
:
()
=>
void
;
setScale
:
(
scale
:
number
)
=>
void
;
setRotate
:
(
rotate
:
number
)
=>
void
;
}
}
export
interface
ImageProps
{
export
interface
ImageProps
{
...
...
src/views/demo/feat/img-preview/index.vue
浏览文件 @
e23bd269
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
import
{
defineComponent
}
from
'vue'
;
import
{
defineComponent
}
from
'vue'
;
import
{
createImgPreview
,
ImagePreview
}
from
'/@/components/Preview/index'
;
import
{
createImgPreview
,
ImagePreview
}
from
'/@/components/Preview/index'
;
import
{
PageWrapper
}
from
'/@/components/Page'
;
import
{
PageWrapper
}
from
'/@/components/Page'
;
// import { PreviewActions } from '/@/components/Preview/src/typing';
const
imgList
:
string
[]
=
[
const
imgList
:
string
[]
=
[
'https://picsum.photos/id/66/346/216'
,
'https://picsum.photos/id/66/346/216'
,
...
@@ -18,7 +19,11 @@
...
@@ -18,7 +19,11 @@
components
:
{
PageWrapper
,
ImagePreview
},
components
:
{
PageWrapper
,
ImagePreview
},
setup
()
{
setup
()
{
function
openImg
()
{
function
openImg
()
{
createImgPreview
({
imageList
:
imgList
});
const
onImgLoad
=
({
index
,
url
,
dom
})
=>
{
console
.
log
(
`第
${
index
+
1
}
张图片已加载,URL为:
${
url
}
`
,
dom
);
};
// 可以使用createImgPreview返回的 PreviewActions 来控制预览逻辑,实现类似幻灯片、自动旋转之类的骚操作
createImgPreview
({
imageList
:
imgList
,
defaultWidth
:
700
,
rememberState
:
true
,
onImgLoad
});
}
}
return
{
imgList
,
openImg
};
return
{
imgList
,
openImg
};
},
},
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论