Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qianlong66
uni-app
提交
21457d96
U
uni-app
项目概览
qianlong66
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
21457d96
编写于
9月 16, 2022
作者:
D
DCloud_LXH
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(h5): swiper add navigation
上级
e276e040
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
265 addition
and
4 deletion
+265
-4
packages/uni-components/src/vue/swiper/index.tsx
packages/uni-components/src/vue/swiper/index.tsx
+198
-4
packages/uni-components/style/swiper.css
packages/uni-components/style/swiper.css
+67
-0
未找到文件。
packages/uni-components/src/vue/swiper/index.tsx
浏览文件 @
21457d96
...
@@ -11,13 +11,16 @@ import {
...
@@ -11,13 +11,16 @@ import {
VNode
,
VNode
,
markRaw
,
markRaw
,
SetupContext
,
SetupContext
,
watchEffect
,
}
from
'
vue
'
}
from
'
vue
'
import
{
extend
}
from
'
@vue/shared
'
import
{
defineBuiltInComponent
}
from
'
../../helpers/component
'
import
{
defineBuiltInComponent
}
from
'
../../helpers/component
'
import
{
useCustomEvent
,
CustomEventTrigger
}
from
'
../../helpers/useEvent
'
import
{
useCustomEvent
,
CustomEventTrigger
}
from
'
../../helpers/useEvent
'
import
{
useTouchtrack
}
from
'
../../helpers/useTouchtrack
'
import
{
useTouchtrack
}
from
'
../../helpers/useTouchtrack
'
import
{
flatVNode
}
from
'
../../helpers/flatVNode
'
import
{
flatVNode
}
from
'
../../helpers/flatVNode
'
import
{
useRebuild
}
from
'
../../helpers/useRebuild
'
import
{
useRebuild
}
from
'
../../helpers/useRebuild
'
import
{
rpx2px
}
from
'
@dcloudio/uni-core
'
import
{
rpx2px
}
from
'
@dcloudio/uni-core
'
import
{
createSvgIconVNode
,
ICON_PATH_BACK
}
from
'
@dcloudio/uni-core
'
const
props
=
{
const
props
=
{
indicatorDots
:
{
indicatorDots
:
{
...
@@ -80,9 +83,22 @@ const props = {
...
@@ -80,9 +83,22 @@ const props = {
type
:
[
Boolean
,
String
],
type
:
[
Boolean
,
String
],
default
:
false
,
default
:
false
,
},
},
navigation
:
{
type
:
[
Boolean
,
String
],
default
:
false
,
},
navigationColor
:
{
type
:
String
,
default
:
'
#fff
'
,
},
navigationActiveColor
:
{
type
:
String
,
default
:
'
rgba(53, 53, 53, 0.6)
'
,
},
}
}
type
Props
=
Record
<
keyof
typeof
props
,
any
>
type
Props
=
Record
<
keyof
typeof
props
,
any
>
type
CurrentChangeSource
=
'
click
'
|
'
touch
'
|
'
autoplay
'
|
''
export
interface
SwiperContext
{
export
interface
SwiperContext
{
rootRef
:
Ref
<
HTMLElement
|
null
>
rootRef
:
Ref
<
HTMLElement
|
null
>
...
@@ -154,9 +170,11 @@ function useLayout(
...
@@ -154,9 +170,11 @@ function useLayout(
let
transitionStart
:
number
|
null
let
transitionStart
:
number
|
null
let
currentChangeSource
=
''
let
currentChangeSource
=
''
let
animationFrame
:
number
let
animationFrame
:
number
const
swiperEnabled
:
ComputedRef
<
boolean
>
=
computed
(
()
=>
swiperContexts
.
value
.
length
>
state
.
displayMultipleItems
)
const
circularEnabled
:
ComputedRef
<
boolean
>
=
computed
(
const
circularEnabled
:
ComputedRef
<
boolean
>
=
computed
(
()
=>
()
=>
props
.
circular
&&
swiperEnabled
.
value
props
.
circular
&&
swiperContexts
.
value
.
length
>
state
.
displayMultipleItems
)
)
function
checkCircularLayout
(
index
:
number
)
{
function
checkCircularLayout
(
index
:
number
)
{
if
(
!
invalid
)
{
if
(
!
invalid
)
{
...
@@ -276,7 +294,11 @@ function useLayout(
...
@@ -276,7 +294,11 @@ function useLayout(
updateViewport
(
l
)
updateViewport
(
l
)
animationFrame
=
requestAnimationFrame
(
animateFrameFuncProto
)
animationFrame
=
requestAnimationFrame
(
animateFrameFuncProto
)
}
}
function
animateViewport
(
current
:
number
,
source
:
string
,
n
:
number
)
{
function
animateViewport
(
current
:
number
,
source
:
CurrentChangeSource
,
n
:
number
)
{
cancelViewportAnimation
()
cancelViewportAnimation
()
const
duration
=
state
.
duration
const
duration
=
state
.
duration
const
length
=
swiperContexts
.
value
.
length
const
length
=
swiperContexts
.
value
.
length
...
@@ -310,6 +332,8 @@ function useLayout(
...
@@ -310,6 +332,8 @@ function useLayout(
position
+=
length
position
+=
length
}
}
}
}
}
else
if
(
source
===
'
click
'
)
{
current
=
current
+
state
.
displayMultipleItems
-
1
<
length
?
current
:
0
}
}
animating
=
{
animating
=
{
...
@@ -604,6 +628,8 @@ function useLayout(
...
@@ -604,6 +628,8 @@ function useLayout(
}
}
return
{
return
{
onSwiperDotClick
,
onSwiperDotClick
,
circularEnabled
,
swiperEnabled
,
}
}
}
}
...
@@ -688,7 +714,7 @@ export default /*#__PURE__*/ defineBuiltInComponent({
...
@@ -688,7 +714,7 @@ export default /*#__PURE__*/ defineBuiltInComponent({
}
}
provide
(
'
removeSwiperContext
'
,
removeSwiperContext
)
provide
(
'
removeSwiperContext
'
,
removeSwiperContext
)
const
{
onSwiperDotClick
}
=
useLayout
(
const
{
onSwiperDotClick
,
circularEnabled
,
swiperEnabled
}
=
useLayout
(
props
,
props
,
state
,
state
,
swiperContexts
,
swiperContexts
,
...
@@ -697,6 +723,19 @@ export default /*#__PURE__*/ defineBuiltInComponent({
...
@@ -697,6 +723,19 @@ export default /*#__PURE__*/ defineBuiltInComponent({
trigger
trigger
)
)
let
createNavigationTsx
:
()
=>
JSX
.
Element
|
null
=
()
=>
null
if
(
__PLATFORM__
===
'
h5
'
)
{
createNavigationTsx
=
useSwiperNavigation
(
rootRef
,
props
,
state
,
onSwiperDotClick
,
swiperContexts
,
circularEnabled
,
swiperEnabled
)
}
return
()
=>
{
return
()
=>
{
const
defaultSlots
=
slots
.
default
&&
slots
.
default
()
const
defaultSlots
=
slots
.
default
&&
slots
.
default
()
// TODO filter
// TODO filter
...
@@ -745,9 +784,164 @@ export default /*#__PURE__*/ defineBuiltInComponent({
...
@@ -745,9 +784,164 @@ export default /*#__PURE__*/ defineBuiltInComponent({
))
}
))
}
</
div
>
</
div
>
)
}
)
}
{
createNavigationTsx
()
}
</
div
>
</
div
>
</
uni
-
swiper
>
</
uni
-
swiper
>
)
)
}
}
},
},
})
})
type
NavigationHoverType
=
'
over
'
|
'
out
'
type
NavigationClickType
=
'
prev
'
|
'
next
'
const
useSwiperNavigation
=
/*#__PURE__*/
(
rootRef
:
Ref
<
HTMLElement
|
null
>
,
props
:
Props
,
state
:
State
,
onSwiperDotClick
:
ReturnType
<
typeof
useLayout
>
[
'
onSwiperDotClick
'
],
swiperContext
:
Ref
<
SwiperContext
[]
>
,
circularEnabled
:
ComputedRef
<
boolean
>
,
swiperEnabled
:
ComputedRef
<
boolean
>
)
=>
{
let
isNavigationAuto
=
false
let
prevDisabled
=
false
let
nextDisabled
=
false
let
hideNavigation
=
ref
(
false
)
watchEffect
(()
=>
{
isNavigationAuto
=
props
.
navigation
===
'
auto
'
hideNavigation
.
value
=
props
.
navigation
!==
true
||
isNavigationAuto
swiperAddMouseEvent
()
})
watchEffect
(()
=>
{
const
swiperItemLength
=
swiperContext
.
value
.
length
const
notCircular
=
!
circularEnabled
.
value
prevDisabled
=
state
.
current
===
0
&&
notCircular
nextDisabled
=
(
state
.
current
===
swiperItemLength
-
1
&&
notCircular
)
||
(
notCircular
&&
state
.
current
+
state
.
displayMultipleItems
>=
swiperItemLength
)
if
(
!
swiperEnabled
.
value
)
{
prevDisabled
=
true
nextDisabled
=
true
isNavigationAuto
&&
(
hideNavigation
.
value
=
true
)
}
})
function
navigationHover
(
event
:
MouseEvent
,
type
:
NavigationHoverType
)
{
const
target
=
event
.
currentTarget
if
(
!
target
)
return
;(
target
as
HTMLDivElement
).
style
.
backgroundColor
=
type
===
'
over
'
?
props
.
navigationActiveColor
:
''
}
const
navigationAttr
=
{
onMouseover
:
(
event
:
MouseEvent
)
=>
navigationHover
(
event
,
'
over
'
),
onMouseout
:
(
event
:
MouseEvent
)
=>
navigationHover
(
event
,
'
out
'
),
}
function
navigationClick
(
type
:
NavigationClickType
)
{
const
swiperItemLength
=
swiperContext
.
value
.
length
let
_current
=
state
.
current
switch
(
type
)
{
case
'
prev
'
:
_current
--
if
(
_current
<
0
&&
circularEnabled
.
value
)
{
_current
=
swiperItemLength
-
1
}
break
case
'
next
'
:
_current
++
if
(
_current
>=
swiperItemLength
&&
circularEnabled
.
value
)
{
_current
=
0
}
break
}
onSwiperDotClick
(
_current
)
}
const
createNavigationSVG
=
()
=>
createSvgIconVNode
(
ICON_PATH_BACK
,
props
.
navigationColor
,
26
)
const
_mouseMove
=
(
e
:
MouseEvent
)
=>
{
const
{
clientX
,
clientY
}
=
e
const
{
left
,
right
,
top
,
bottom
,
width
,
height
}
=
rootRef
.
value
!
.
getBoundingClientRect
()
if
(
props
.
vertical
)
{
hideNavigation
.
value
=
!
(
clientY
-
top
<
height
/
3
||
bottom
-
clientY
<
height
/
3
)
}
else
{
hideNavigation
.
value
=
!
(
clientX
-
left
<
width
/
3
||
right
-
clientX
<
width
/
3
)
}
}
const
_mouseOut
=
()
=>
{
hideNavigation
.
value
=
true
}
function
swiperAddMouseEvent
()
{
if
(
rootRef
.
value
)
{
rootRef
.
value
.
removeEventListener
(
'
mousemove
'
,
_mouseMove
)
rootRef
.
value
.
removeEventListener
(
'
mouseout
'
,
_mouseOut
)
if
(
isNavigationAuto
)
{
rootRef
.
value
.
addEventListener
(
'
mousemove
'
,
_mouseMove
)
rootRef
.
value
.
addEventListener
(
'
mouseout
'
,
_mouseOut
)
}
}
}
onMounted
(
swiperAddMouseEvent
)
function
createNavigationTsx
()
{
const
navigationClass
=
{
'
uni-swiper-navigation-hide
'
:
hideNavigation
.
value
,
'
uni-swiper-navigation-vertical
'
:
props
.
vertical
,
}
if
(
props
.
navigation
)
{
return
(
<>
<
div
class
=
"uni-swiper-navigation uni-swiper-navigation-prev"
// @ts-expect-error
class
=
{
extend
(
{
'
uni-swiper-navigation-disabled
'
:
prevDisabled
,
},
navigationClass
)
}
onClick
=
{
()
=>
navigationClick
(
'
prev
'
)
}
{
...
navigationAttr
}
>
{
createNavigationSVG
()
}
</
div
>
<
div
class
=
"uni-swiper-navigation uni-swiper-navigation-next"
// @ts-expect-error
class
=
{
extend
(
{
'
uni-swiper-navigation-disabled
'
:
nextDisabled
,
},
navigationClass
)
}
onClick
=
{
()
=>
navigationClick
(
'
next
'
)
}
{
...
navigationAttr
}
>
{
createNavigationSVG
()
}
</
div
>
</>
)
}
return
null
}
return
createNavigationTsx
}
packages/uni-components/style/swiper.css
浏览文件 @
21457d96
...
@@ -83,3 +83,70 @@ uni-swiper[hidden] {
...
@@ -83,3 +83,70 @@ uni-swiper[hidden] {
.uni-swiper-dot-active
{
.uni-swiper-dot-active
{
background-color
:
#000000
;
background-color
:
#000000
;
}
}
.uni-swiper-navigation
{
width
:
26px
;
height
:
26px
;
cursor
:
pointer
;
position
:
absolute
;
top
:
50%
;
margin-top
:
-13px
;
display
:
flex
;
align-items
:
center
;
transition
:
all
0.2s
;
border-radius
:
50%
;
opacity
:
1
;
}
.uni-swiper-navigation-disabled
{
opacity
:
0.35
;
cursor
:
auto
;
pointer-events
:
none
;
}
.uni-swiper-navigation-hide
{
opacity
:
0
;
cursor
:
auto
;
pointer-events
:
none
;
}
.uni-swiper-navigation-prev
{
left
:
10px
;
}
.uni-swiper-navigation-prev
svg
{
margin-left
:
-1px
;
left
:
10px
;
}
.uni-swiper-navigation-prev.uni-swiper-navigation-vertical
{
top
:
18px
;
left
:
50%
;
margin-left
:
-13px
;
}
.uni-swiper-navigation-prev.uni-swiper-navigation-vertical
svg
{
transform
:
rotate
(
90deg
);
margin-left
:
auto
;
margin-top
:
-2px
;
}
.uni-swiper-navigation-next
{
right
:
10px
;
}
.uni-swiper-navigation-next
svg
{
transform
:
rotate
(
180deg
);
}
.uni-swiper-navigation-next.uni-swiper-navigation-vertical
{
top
:
auto
;
bottom
:
5px
;
left
:
50%
;
margin-left
:
-13px
;
}
.uni-swiper-navigation-next.uni-swiper-navigation-vertical
svg
{
margin-top
:
2px
;
transform
:
rotate
(
270deg
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录