Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-app
提交
6e8dfd97
U
uni-app
项目概览
DCloud
/
uni-app
3 个月 前同步成功
通知
725
Star
38705
Fork
3642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
7
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
7
Issue
7
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6e8dfd97
编写于
5月 11, 2021
作者:
D
DCloud_LXH
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: movable-area、movable-view
上级
ad51f136
变更
9
展开全部
隐藏空白更改
内联
并排
Showing
9 changed file
with
2625 addition
and
2358 deletion
+2625
-2358
packages/uni-components/src/components/index.ts
packages/uni-components/src/components/index.ts
+3
-3
packages/uni-components/src/components/movable-area/index.tsx
...ages/uni-components/src/components/movable-area/index.tsx
+280
-0
packages/uni-components/src/components/movable-area/index.vue
...ages/uni-components/src/components/movable-area/index.vue
+0
-171
packages/uni-components/src/components/movable-view/index.tsx
...ages/uni-components/src/components/movable-view/index.tsx
+766
-0
packages/uni-components/src/components/movable-view/index.vue
...ages/uni-components/src/components/movable-view/index.vue
+0
-638
packages/uni-components/src/helpers/useTouchtrack.ts
packages/uni-components/src/helpers/useTouchtrack.ts
+3
-3
packages/uni-h5/dist/uni-h5.cjs.js
packages/uni-h5/dist/uni-h5.cjs.js
+617
-717
packages/uni-h5/dist/uni-h5.es.js
packages/uni-h5/dist/uni-h5.es.js
+955
-826
packages/uni-h5/src/view/components/web-view/index.tsx
packages/uni-h5/src/view/components/web-view/index.tsx
+1
-0
未找到文件。
packages/uni-components/src/components/index.ts
浏览文件 @
6e8dfd97
...
@@ -9,8 +9,8 @@ import Icon from './icon/index'
...
@@ -9,8 +9,8 @@ import Icon from './icon/index'
import
Image
from
'
./image/index
'
import
Image
from
'
./image/index
'
import
Input
from
'
./input/index
'
import
Input
from
'
./input/index
'
import
Label
from
'
./label/index
'
import
Label
from
'
./label/index
'
// import MovableArea from './movable-area/index.vue
'
import
MovableArea
from
'
./movable-area/index
'
import
MovableView
from
'
./movable-view/index
.vue
'
import
MovableView
from
'
./movable-view/index
'
import
Navigator
from
'
./navigator/index.vue
'
import
Navigator
from
'
./navigator/index.vue
'
// import PickerView from './picker-view/index.vue'
// import PickerView from './picker-view/index.vue'
// import PickerViewColumn from './picker-view-column/index.vue'
// import PickerViewColumn from './picker-view-column/index.vue'
...
@@ -39,7 +39,7 @@ export {
...
@@ -39,7 +39,7 @@ export {
Image
,
Image
,
Input
,
Input
,
Label
,
Label
,
//
MovableArea,
MovableArea
,
MovableView
,
MovableView
,
Navigator
,
Navigator
,
// PickerView,
// PickerView,
...
...
packages/uni-components/src/components/movable-area/index.tsx
0 → 100644
浏览文件 @
6e8dfd97
import
{
ref
,
defineComponent
,
ExtractPropTypes
,
reactive
,
Ref
,
onMounted
,
VNode
,
markRaw
,
provide
,
}
from
'
vue
'
import
{
useAttrs
,
withWebEvent
}
from
'
@dcloudio/uni-components
'
import
{
initScrollBounce
,
disableScrollBounce
}
from
'
../../helpers/scroll
'
import
ResizeSensor
from
'
../resize-sensor/index
'
const
props
=
{
scaleArea
:
{
type
:
Boolean
,
default
:
false
,
},
}
type
Props
=
ExtractPropTypes
<
typeof
props
>
export
interface
MovableViewContext
{
rootRef
:
Ref
<
HTMLElement
|
null
>
setParent
:
Function
_endScale
:
Function
_setScale
:
Function
}
export
type
AddMovableViewContext
=
(
context
:
MovableViewContext
)
=>
void
export
type
RemoveMovableViewContext
=
(
context
:
MovableViewContext
)
=>
void
export
default
/*#__PURE__*/
defineComponent
({
inheritAttrs
:
false
,
name
:
'
MovableArea
'
,
props
,
setup
(
props
,
{
slots
})
{
const
rootRef
=
ref
(
null
)
const
_isMounted
=
ref
(
false
)
let
{
setContexts
,
events
:
movableAreaEvents
}
=
useMovableAreaState
(
props
,
rootRef
)
const
{
$listeners
,
$attrs
,
$excludeAttrs
}
=
useAttrs
()
const
_listeners
=
$listeners
.
value
let
events
=
[
'
onTouchstart
'
,
'
onTouchmove
'
,
'
onTouchend
'
]
events
.
forEach
((
event
)
=>
{
let
existing
=
(
_listeners
as
any
)[
event
]
let
ours
=
movableAreaEvents
[
`_
${
event
}
`
as
'
_onTouchstart
'
|
'
_onTouchmove
'
|
'
_onTouchend
'
]
;(
_listeners
as
any
)[
event
]
=
existing
?
[].
concat
(
existing
,
ours
as
any
)
:
ours
})
onMounted
(()
=>
{
movableAreaEvents
.
_resize
()
initScrollBounce
()
_isMounted
.
value
=
true
})
let
movableViewItems
:
VNode
[]
=
[]
const
originMovableViewContexts
:
MovableViewContext
[]
=
[]
function
updateMovableViewContexts
()
{
const
contexts
:
MovableViewContext
[]
=
[]
for
(
let
index
=
0
;
index
<
movableViewItems
.
length
;
index
++
)
{
const
movableViewItem
=
movableViewItems
[
index
]
const
movableViewContext
=
originMovableViewContexts
.
find
(
(
context
)
=>
movableViewItem
.
el
===
context
.
rootRef
.
value
)
if
(
movableViewContext
)
{
contexts
.
push
(
markRaw
(
movableViewContext
))
}
}
setContexts
(
contexts
)
}
const
addMovableViewContext
:
AddMovableViewContext
=
(
movableViewContext
)
=>
{
originMovableViewContexts
.
push
(
movableViewContext
)
updateMovableViewContexts
()
}
const
removeMovableViewContext
:
RemoveMovableViewContext
=
(
movableViewContext
)
=>
{
const
index
=
originMovableViewContexts
.
indexOf
(
movableViewContext
)
if
(
index
>=
0
)
{
originMovableViewContexts
.
splice
(
index
,
1
)
updateMovableViewContexts
()
}
}
provide
(
'
_isMounted
'
,
_isMounted
)
provide
(
'
movableAreaRootRef
'
,
rootRef
)
provide
(
'
addMovableViewContext
'
,
addMovableViewContext
)
provide
(
'
removeMovableViewContext
'
,
removeMovableViewContext
)
return
()
=>
{
const
defaultSlots
=
slots
.
default
&&
slots
.
default
()
movableViewItems
=
defaultSlots
||
[]
return
(
<
uni
-
movable
-
area
ref
=
{
rootRef
}
{
...
$attrs
.
value
}
{
...
$excludeAttrs
.
value
}
{
...
_listeners
}
>
{
/* @ts-ignore */
}
<
ResizeSensor
onReize
=
{
movableAreaEvents
.
_resize
}
></
ResizeSensor
>
{
movableViewItems
}
</
uni
-
movable
-
area
>
)
}
},
})
type
GapV
=
{
x
:
number
|
null
y
:
number
|
null
}
function
calc
(
e
:
GapV
)
{
return
Math
.
sqrt
(
e
.
x
!
*
e
.
x
!
+
e
.
y
!
*
e
.
y
!
)
}
function
useMovableAreaState
(
props
:
Props
,
rootRef
:
Ref
<
HTMLElement
|
null
>
)
{
const
width
=
ref
(
0
)
const
height
=
ref
(
0
)
const
gapV
:
GapV
=
reactive
({
x
:
null
,
y
:
null
,
})
const
pinchStartLen
=
ref
<
number
|
null
>
(
null
)
let
_scaleMovableView
:
MovableViewContext
|
null
=
null
let
movableViewContexts
:
MovableViewContext
[]
=
[]
function
_updateScale
(
e
:
number
)
{
if
(
e
&&
e
!==
1
)
{
if
(
props
.
scaleArea
)
{
movableViewContexts
.
forEach
(
function
(
item
)
{
item
.
_setScale
(
e
)
})
}
else
{
if
(
_scaleMovableView
)
{
_scaleMovableView
.
_setScale
(
e
)
}
}
}
}
function
_find
(
target
:
TouchEvent
[
'
target
'
],
items
=
movableViewContexts
)
{
let
root
=
rootRef
.
value
function
get
(
node
:
EventTarget
|
HTMLElement
|
null
):
MovableViewContext
|
null
{
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
const
item
=
items
[
i
]
if
(
node
===
item
.
rootRef
.
value
)
{
return
item
}
}
if
(
node
===
root
||
node
===
document
.
body
||
node
===
document
)
{
return
null
}
return
get
((
node
as
HTMLElement
).
parentNode
)
}
return
get
(
target
)
}
const
_onTouchstart
=
withWebEvent
((
t
:
TouchEvent
)
=>
{
disableScrollBounce
({
disable
:
true
,
})
let
i
=
t
.
touches
if
(
i
)
{
if
(
i
.
length
>
1
)
{
let
r
=
{
x
:
i
[
1
].
pageX
-
i
[
0
].
pageX
,
y
:
i
[
1
].
pageY
-
i
[
0
].
pageY
,
}
pinchStartLen
.
value
=
calc
(
r
)
gapV
.
x
=
r
.
x
gapV
.
y
=
r
.
y
if
(
!
props
.
scaleArea
)
{
let
touch0
=
_find
(
i
[
0
].
target
)
let
touch1
=
_find
(
i
[
1
].
target
)
_scaleMovableView
=
touch0
&&
touch0
===
touch1
?
touch0
:
null
}
}
}
})
const
_onTouchmove
=
withWebEvent
((
t
:
TouchEvent
)
=>
{
let
n
=
t
.
touches
if
(
n
)
{
if
(
n
.
length
>
1
)
{
t
.
preventDefault
()
let
i
=
{
x
:
n
[
1
].
pageX
-
n
[
0
].
pageX
,
y
:
n
[
1
].
pageY
-
n
[
0
].
pageY
,
}
if
(
gapV
.
x
!==
null
&&
pinchStartLen
.
value
&&
pinchStartLen
.
value
>
0
)
{
let
r
=
calc
(
i
)
/
pinchStartLen
.
value
_updateScale
(
r
)
}
gapV
.
x
=
i
.
x
gapV
.
y
=
i
.
y
}
}
})
const
_onTouchend
=
withWebEvent
((
e
:
TouchEvent
)
=>
{
disableScrollBounce
({
disable
:
false
,
})
let
t
=
e
.
touches
if
(
!
(
t
&&
t
.
length
))
{
if
(
e
.
changedTouches
)
{
gapV
.
x
=
0
gapV
.
y
=
0
pinchStartLen
.
value
=
null
if
(
props
.
scaleArea
)
{
movableViewContexts
.
forEach
(
function
(
item
)
{
item
.
_endScale
()
})
}
else
{
if
(
_scaleMovableView
)
{
_scaleMovableView
.
_endScale
()
}
}
}
}
})
function
_resize
()
{
_getWH
()
movableViewContexts
.
forEach
(
function
(
item
,
index
)
{
item
.
setParent
()
})
}
function
_getWH
()
{
let
style
=
window
.
getComputedStyle
(
rootRef
.
value
!
)
let
rect
=
rootRef
.
value
!
.
getBoundingClientRect
()
width
.
value
=
rect
.
width
-
[
'
Left
'
,
'
Right
'
].
reduce
(
function
(
all
,
item
)
{
const
LEFT
=
(
'
border
'
+
item
+
'
Width
'
)
as
keyof
CSSStyleDeclaration
const
RIGHT
=
(
'
padding
'
+
item
)
as
keyof
CSSStyleDeclaration
return
(
all
+
parseFloat
((
style
[
LEFT
]
as
unknown
)
as
string
)
+
parseFloat
((
style
[
RIGHT
]
as
unknown
)
as
string
)
)
},
0
)
height
.
value
=
rect
.
height
-
[
'
Top
'
,
'
Bottom
'
].
reduce
(
function
(
all
,
item
)
{
const
TOP
=
(
'
border
'
+
item
+
'
Width
'
)
as
keyof
CSSStyleDeclaration
const
BOTTOM
=
(
'
padding
'
+
item
)
as
keyof
CSSStyleDeclaration
return
(
all
+
parseFloat
((
style
[
TOP
]
as
unknown
)
as
string
)
+
parseFloat
((
style
[
BOTTOM
]
as
unknown
)
as
string
)
)
},
0
)
}
provide
(
'
movableAreaWidth
'
,
width
)
provide
(
'
movableAreaHeight
'
,
height
)
return
{
setContexts
(
contexts
:
MovableViewContext
[])
{
movableViewContexts
=
contexts
},
events
:
{
_onTouchstart
,
_onTouchmove
,
_onTouchend
,
_resize
,
},
}
}
packages/uni-components/src/components/movable-area/index.vue
已删除
100644 → 0
浏览文件 @
ad51f136
<
script
>
import
{
disableScrollBounce
}
from
'
../../helpers/disable-scroll-bounce
'
import
{
deepClone
}
from
'
uni-shared
'
function
calc
(
e
)
{
return
Math
.
sqrt
(
e
.
x
*
e
.
x
+
e
.
y
*
e
.
y
)
}
export
default
{
name
:
'
MovableArea
'
,
props
:
{
scaleArea
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
width
:
0
,
height
:
0
,
items
:
[]
}
},
created
:
function
()
{
this
.
gapV
=
{
x
:
null
,
y
:
null
}
this
.
pinchStartLen
=
null
},
mounted
:
function
()
{
this
.
_resize
()
},
methods
:
{
_resize
()
{
this
.
_getWH
()
this
.
items
.
forEach
(
function
(
item
,
index
)
{
item
.
componentInstance
.
setParent
()
})
},
_find
(
target
,
items
=
this
.
items
)
{
var
root
=
this
.
$el
function
get
(
node
)
{
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
const
item
=
items
[
i
]
if
(
node
===
item
.
componentInstance
.
$el
)
{
return
item
}
}
if
(
node
===
root
||
node
===
document
.
body
||
node
===
document
)
{
return
null
}
return
get
(
node
.
parentNode
)
}
return
get
(
target
)
},
_touchstart
(
t
)
{
disableScrollBounce
({
disable
:
true
})
var
i
=
t
.
touches
if
(
i
)
{
if
(
i
.
length
>
1
)
{
var
r
=
{
x
:
i
[
1
].
pageX
-
i
[
0
].
pageX
,
y
:
i
[
1
].
pageY
-
i
[
0
].
pageY
}
this
.
pinchStartLen
=
calc
(
r
)
this
.
gapV
=
r
if
(
!
this
.
scaleArea
)
{
var
touch0
=
this
.
_find
(
i
[
0
].
target
)
var
touch1
=
this
.
_find
(
i
[
1
].
target
)
this
.
_scaleMovableView
=
touch0
&&
touch0
===
touch1
?
touch0
:
null
}
}
}
},
_touchmove
(
t
)
{
var
n
=
t
.
touches
if
(
n
)
{
if
(
n
.
length
>
1
)
{
t
.
preventDefault
()
var
i
=
{
x
:
n
[
1
].
pageX
-
n
[
0
].
pageX
,
y
:
n
[
1
].
pageY
-
n
[
0
].
pageY
}
if
(
this
.
gapV
.
x
!==
null
&&
this
.
pinchStartLen
>
0
)
{
var
r
=
calc
(
i
)
/
this
.
pinchStartLen
this
.
_updateScale
(
r
)
}
this
.
gapV
=
i
}
}
},
_touchend
(
e
)
{
disableScrollBounce
({
disable
:
false
})
var
t
=
e
.
touches
if
(
!
(
t
&&
t
.
length
))
{
if
(
e
.
changedTouches
)
{
this
.
gapV
.
x
=
0
this
.
gapV
.
y
=
0
this
.
pinchStartLen
=
null
if
(
this
.
scaleArea
)
{
this
.
items
.
forEach
(
function
(
item
)
{
item
.
componentInstance
.
_endScale
()
})
}
else
{
if
(
this
.
_scaleMovableView
)
{
this
.
_scaleMovableView
.
componentInstance
.
_endScale
()
}
}
}
}
},
_updateScale
(
e
)
{
if
(
e
&&
e
!==
1
)
{
if
(
this
.
scaleArea
)
{
this
.
items
.
forEach
(
function
(
item
)
{
item
.
componentInstance
.
_setScale
(
e
)
})
}
else
{
if
(
this
.
_scaleMovableView
)
{
this
.
_scaleMovableView
.
componentInstance
.
_setScale
(
e
)
}
}
}
},
_getWH
()
{
var
style
=
window
.
getComputedStyle
(
this
.
$el
)
var
rect
=
this
.
$el
.
getBoundingClientRect
()
this
.
width
=
rect
.
width
-
[
'
Left
'
,
'
Right
'
].
reduce
(
function
(
all
,
item
)
{
return
all
+
parseFloat
(
style
[
'
border
'
+
item
+
'
Width
'
])
+
parseFloat
(
style
[
'
padding
'
+
item
])
},
0
)
this
.
height
=
rect
.
height
-
[
'
Top
'
,
'
Bottom
'
].
reduce
(
function
(
all
,
item
)
{
return
all
+
parseFloat
(
style
[
'
border
'
+
item
+
'
Width
'
])
+
parseFloat
(
style
[
'
padding
'
+
item
])
},
0
)
}
},
render
(
createElement
)
{
var
items
=
[]
const
$slots
=
this
.
$slots
.
default
&&
deepClone
(
this
.
$slots
.
default
,
createElement
)
if
(
$slots
)
{
$slots
.
forEach
(
vnode
=>
{
if
(
vnode
.
componentOptions
&&
vnode
.
componentOptions
.
tag
===
'
v-uni-movable-view
'
)
{
items
.
push
(
vnode
)
}
})
}
this
.
items
=
items
var
$listeners
=
Object
.
assign
({},
this
.
$listeners
)
var
events
=
[
'
touchstart
'
,
'
touchmove
'
,
'
touchend
'
]
events
.
forEach
(
event
=>
{
var
existing
=
$listeners
[
event
]
var
ours
=
this
[
`_
${
event
}
`
]
$listeners
[
event
]
=
existing
?
[].
concat
(
existing
,
ours
)
:
ours
})
return
createElement
(
'
uni-movable-area
'
,
{
on
:
$listeners
},
[
createElement
(
'
v-uni-resize-sensor
'
,
{
on
:
{
resize
:
this
.
_resize
}
}),
$slots
])
}
}
</
script
>
\ No newline at end of file
packages/uni-components/src/components/movable-view/index.tsx
0 → 100644
浏览文件 @
6e8dfd97
import
{
ref
,
defineComponent
,
ExtractPropTypes
,
Ref
,
onMounted
,
inject
,
computed
,
watch
,
onUnmounted
,
}
from
'
vue
'
import
{
initScrollBounce
,
disableScrollBounce
}
from
'
../../helpers/scroll
'
import
{
useTouchtrack
,
TouchtrackEvent
}
from
'
../../helpers/useTouchtrack
'
import
ResizeSensor
from
'
../resize-sensor/index
'
import
{
useCustomEvent
,
CustomEventTrigger
,
EmitEvent
,
}
from
'
../../helpers/useEvent
'
import
type
{
MovableViewContext
,
AddMovableViewContext
,
RemoveMovableViewContext
,
}
from
'
../movable-area/index
'
import
{
Decline
,
Friction
,
STD
}
from
'
./utils
'
const
props
=
{
direction
:
{
type
:
String
,
default
:
'
none
'
,
},
inertia
:
{
type
:
[
Boolean
,
String
],
default
:
false
,
},
outOfBounds
:
{
type
:
[
Boolean
,
String
],
default
:
false
,
},
x
:
{
type
:
[
Number
,
String
],
default
:
0
,
},
y
:
{
type
:
[
Number
,
String
],
default
:
0
,
},
damping
:
{
type
:
[
Number
,
String
],
default
:
20
,
},
friction
:
{
type
:
[
Number
,
String
],
default
:
2
,
},
disabled
:
{
type
:
[
Boolean
,
String
],
default
:
false
,
},
scale
:
{
type
:
[
Boolean
,
String
],
default
:
false
,
},
scaleMin
:
{
type
:
[
Number
,
String
],
default
:
0.5
,
},
scaleMax
:
{
type
:
[
Number
,
String
],
default
:
10
,
},
scaleValue
:
{
type
:
[
Number
,
String
],
default
:
1
,
},
animation
:
{
type
:
[
Boolean
,
String
],
default
:
true
,
},
}
type
Props
=
ExtractPropTypes
<
typeof
props
>
type
RootRef
=
Ref
<
HTMLElement
|
null
>
export
default
/*#__PURE__*/
defineComponent
({
name
:
'
MovableView
'
,
props
,
emits
:
[
'
change
'
,
'
scale
'
],
setup
(
props
,
{
slots
,
emit
})
{
const
rootRef
:
RootRef
=
ref
(
null
)
const
trigger
=
useCustomEvent
<
EmitEvent
<
typeof
emit
>>
(
rootRef
,
emit
)
const
{
setParent
}
=
useMovableViewState
(
props
,
trigger
,
rootRef
)
return
()
=>
{
return
(
<
uni
-
movable
-
view
ref
=
{
rootRef
}
>
{
/* @ts-ignore */
}
<
ResizeSensor
onResize
=
{
setParent
}
></
ResizeSensor
>
{
slots
.
default
&&
slots
.
default
()
}
</
uni
-
movable
-
view
>
)
}
},
})
let
requesting
=
false
function
_requestAnimationFrame
(
e
:
Function
)
{
if
(
!
requesting
)
{
requesting
=
true
requestAnimationFrame
(
function
()
{
e
()
requesting
=
false
})
}
}
function
p
(
t
:
HTMLElement
,
n
:
HTMLElement
):
number
{
if
(
t
===
n
)
{
return
0
}
let
i
=
t
.
offsetLeft
return
t
.
offsetParent
?
(
i
+=
p
(
t
.
offsetParent
as
HTMLElement
,
n
))
:
0
}
function
f
(
t
:
HTMLElement
,
n
:
HTMLElement
):
number
{
if
(
t
===
n
)
{
return
0
}
let
i
=
t
.
offsetTop
return
t
.
offsetParent
?
(
i
+=
f
(
t
.
offsetParent
as
HTMLElement
,
n
))
:
0
}
function
v
(
a
:
number
,
b
:
number
)
{
return
+
((
1000
*
a
-
1000
*
b
)
/
1000
).
toFixed
(
1
)
}
function
g
(
e
:
Friction
|
STD
,
t
:
Function
,
n
:
Function
)
{
type
R
=
{
id
:
number
cancelled
:
boolean
}
let
i
=
function
(
e
:
R
)
{
if
(
e
&&
e
.
id
)
{
cancelAnimationFrame
(
e
.
id
)
}
if
(
e
)
{
e
.
cancelled
=
true
}
}
let
r
:
R
=
{
id
:
0
,
cancelled
:
false
,
}
function
fn
(
n
:
R
,
i
:
Friction
|
STD
,
r
:
Function
,
o
:
Function
)
{
if
(
!
n
||
!
n
.
cancelled
)
{
r
(
i
)
let
a
=
e
.
done
()
if
(
!
a
)
{
if
(
!
n
.
cancelled
)
{
n
.
id
=
requestAnimationFrame
(
fn
.
bind
(
null
,
n
,
i
,
r
,
o
))
}
}
if
(
a
&&
o
)
{
o
(
i
)
}
}
}
fn
(
r
,
e
,
t
,
n
)
return
{
cancel
:
i
.
bind
(
null
,
r
),
model
:
e
,
}
}
function
_getPx
(
val
:
Props
[
'
x
'
]
|
Props
[
'
y
'
])
{
if
(
/
\d
+
[
ur
]
px$/i
.
test
(
val
as
string
))
{
return
uni
.
upx2px
(
parseFloat
(
val
as
string
))
}
return
Number
(
val
)
||
0
}
type
ReturnType_g
=
ReturnType
<
typeof
g
>
|
null
type
ScaleOffset
=
{
x
:
number
y
:
number
}
type
MoveDirection
=
'
htouchmove
'
|
'
vtouchmove
'
function
useMovableViewState
(
props
:
Props
,
trigger
:
CustomEventTrigger
,
rootRef
:
RootRef
)
{
const
movableAreaWidth
:
Ref
<
number
>
=
inject
(
'
movableAreaWidth
'
,
ref
(
0
))
const
movableAreaHeight
:
Ref
<
number
>
=
inject
(
'
movableAreaHeight
'
,
ref
(
0
))
const
_isMounted
:
Ref
<
boolean
>
=
inject
(
'
_isMounted
'
,
ref
(
false
))
const
movableAreaRootRef
:
RootRef
=
inject
(
'
movableAreaRootRef
'
)
!
const
addMovableViewContext
:
AddMovableViewContext
=
inject
(
'
addMovableViewContext
'
,
()
=>
{}
)
const
removeMovableViewContext
:
RemoveMovableViewContext
=
inject
(
'
removeMovableViewContext
'
,
()
=>
{}
)
const
xSync
=
ref
(
_getPx
(
props
.
x
))
const
ySync
=
ref
(
_getPx
(
props
.
y
))
const
scaleValueSync
=
ref
(
Number
(
props
.
scaleValue
)
||
1
)
const
width
=
ref
(
0
)
const
height
=
ref
(
0
)
const
minX
=
ref
(
0
)
const
minY
=
ref
(
0
)
const
maxX
=
ref
(
0
)
const
maxY
=
ref
(
0
)
let
_SFA
:
ReturnType_g
=
null
let
_FA
:
ReturnType_g
=
null
const
_offset
:
ScaleOffset
=
{
x
:
0
,
y
:
0
,
}
const
_scaleOffset
:
ScaleOffset
=
{
x
:
0
,
y
:
0
,
}
let
_scale
=
1
let
_oldScale
=
1
let
_translateX
=
0
let
_translateY
=
0
let
_isScaling
=
false
let
_isTouching
=
false
let
__baseX
:
number
let
__baseY
:
number
let
_checkCanMove
:
boolean
|
null
=
null
let
_firstMoveDirection
:
MoveDirection
|
null
=
null
const
_declineX
=
new
Decline
()
const
_declineY
=
new
Decline
()
const
__touchInfo
=
{
historyX
:
[
0
,
0
],
historyY
:
[
0
,
0
],
historyT
:
[
0
,
0
],
}
const
dampingNumber
=
computed
(()
=>
{
let
val
=
Number
(
props
.
damping
)
return
isNaN
(
val
)
?
20
:
val
})
const
frictionNumber
=
computed
(()
=>
{
let
val
=
Number
(
props
.
friction
)
return
isNaN
(
val
)
||
val
<=
0
?
2
:
val
})
const
scaleMinNumber
=
computed
(()
=>
{
let
val
=
Number
(
props
.
scaleMin
)
return
isNaN
(
val
)
?
0.5
:
val
})
const
scaleMaxNumber
=
computed
(()
=>
{
let
val
=
Number
(
props
.
scaleMax
)
return
isNaN
(
val
)
?
10
:
val
})
const
xMove
=
computed
(
()
=>
props
.
direction
===
'
all
'
||
props
.
direction
===
'
horizontal
'
)
const
yMove
=
computed
(
()
=>
props
.
direction
===
'
all
'
||
props
.
direction
===
'
vertical
'
)
const
_STD
=
new
STD
(
1
,
(
9
*
Math
.
pow
(
dampingNumber
.
value
,
2
))
/
40
,
dampingNumber
.
value
)
const
_friction
=
new
Friction
(
1
,
frictionNumber
.
value
)
watch
(
()
=>
props
.
x
,
(
val
)
=>
{
xSync
.
value
=
_getPx
(
val
)
}
)
watch
(
()
=>
props
.
y
,
(
val
)
=>
{
ySync
.
value
=
_getPx
(
val
)
}
)
watch
(
xSync
,
(
val
)
=>
{
_setX
(
val
)
})
watch
(
ySync
,
(
val
)
=>
{
_setY
(
val
)
})
watch
(
()
=>
props
.
scaleValue
,
(
val
)
=>
{
scaleValueSync
.
value
=
Number
(
val
)
||
0
}
)
watch
(
scaleValueSync
,
(
val
)
=>
{
_setScaleValue
(
val
)
})
watch
(
scaleMinNumber
,
()
=>
{
_setScaleMinOrMax
()
})
watch
(
scaleMaxNumber
,
()
=>
{
_setScaleMinOrMax
()
})
function
_setX
(
val
:
number
)
{
if
(
xMove
.
value
)
{
if
(
val
+
_scaleOffset
.
x
===
_translateX
)
{
return
_translateX
}
else
{
if
(
_SFA
)
{
_SFA
.
cancel
()
}
_animationTo
(
val
+
_scaleOffset
.
x
,
ySync
.
value
+
_scaleOffset
.
y
,
_scale
)
}
}
return
val
}
function
_setY
(
val
:
number
)
{
if
(
yMove
.
value
)
{
if
(
val
+
_scaleOffset
.
y
===
_translateY
)
{
return
_translateY
}
else
{
if
(
_SFA
)
{
_SFA
.
cancel
()
}
_animationTo
(
xSync
.
value
+
_scaleOffset
.
x
,
val
+
_scaleOffset
.
y
,
_scale
)
}
}
return
val
}
function
_setScaleMinOrMax
()
{
if
(
!
props
.
scale
)
{
return
false
}
_updateScale
(
_scale
,
true
)
_updateOldScale
(
_scale
)
}
function
_setScaleValue
(
scale
:
number
)
{
if
(
!
props
.
scale
)
{
return
false
}
scale
=
_adjustScale
(
scale
)
_updateScale
(
scale
,
true
)
_updateOldScale
(
scale
)
return
scale
}
function
__handleTouchStart
()
{
if
(
!
_isScaling
)
{
if
(
!
props
.
disabled
)
{
disableScrollBounce
({
disable
:
true
,
})
if
(
_FA
)
{
_FA
.
cancel
()
}
if
(
_SFA
)
{
_SFA
.
cancel
()
}
__touchInfo
.
historyX
=
[
0
,
0
]
__touchInfo
.
historyY
=
[
0
,
0
]
__touchInfo
.
historyT
=
[
0
,
0
]
if
(
xMove
.
value
)
{
__baseX
=
_translateX
}
if
(
yMove
.
value
)
{
__baseY
=
_translateY
}
rootRef
.
value
!
.
style
.
willChange
=
'
transform
'
_checkCanMove
=
null
_firstMoveDirection
=
null
_isTouching
=
true
}
}
}
function
__handleTouchMove
(
event
:
TouchtrackEvent
)
{
if
(
!
_isScaling
&&
!
props
.
disabled
&&
_isTouching
)
{
let
x
=
_translateX
let
y
=
_translateY
if
(
_firstMoveDirection
===
null
)
{
_firstMoveDirection
=
Math
.
abs
(
event
.
detail
.
dx
/
event
.
detail
.
dy
)
>
1
?
'
htouchmove
'
:
'
vtouchmove
'
}
if
(
xMove
.
value
)
{
x
=
event
.
detail
.
dx
+
__baseX
__touchInfo
.
historyX
.
shift
()
__touchInfo
.
historyX
.
push
(
x
)
if
(
!
yMove
.
value
&&
_checkCanMove
===
null
)
{
_checkCanMove
=
Math
.
abs
(
event
.
detail
.
dx
/
event
.
detail
.
dy
)
<
1
}
}
if
(
yMove
.
value
)
{
y
=
event
.
detail
.
dy
+
__baseY
__touchInfo
.
historyY
.
shift
()
__touchInfo
.
historyY
.
push
(
y
)
if
(
!
xMove
.
value
&&
_checkCanMove
===
null
)
{
_checkCanMove
=
Math
.
abs
(
event
.
detail
.
dy
/
event
.
detail
.
dx
)
<
1
}
}
__touchInfo
.
historyT
.
shift
()
__touchInfo
.
historyT
.
push
(
event
.
detail
.
timeStamp
)
if
(
!
_checkCanMove
)
{
event
.
preventDefault
()
let
source
=
'
touch
'
if
(
x
<
minX
.
value
)
{
if
(
props
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
x
=
minX
.
value
-
_declineX
.
x
(
minX
.
value
-
x
)
}
else
{
x
=
minX
.
value
}
}
else
if
(
x
>
maxX
.
value
)
{
if
(
props
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
x
=
maxX
.
value
+
_declineX
.
x
(
x
-
maxX
.
value
)
}
else
{
x
=
maxX
.
value
}
}
if
(
y
<
minY
.
value
)
{
if
(
props
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
y
=
minY
.
value
-
_declineY
.
x
(
minY
.
value
-
y
)
}
else
{
y
=
minY
.
value
}
}
else
{
if
(
y
>
maxY
.
value
)
{
if
(
props
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
y
=
maxY
.
value
+
_declineY
.
x
(
y
-
maxY
.
value
)
}
else
{
y
=
maxY
.
value
}
}
}
_requestAnimationFrame
(
function
()
{
_setTransform
(
x
,
y
,
_scale
,
source
)
})
}
}
}
function
__handleTouchEnd
()
{
if
(
!
_isScaling
&&
!
props
.
disabled
&&
_isTouching
)
{
disableScrollBounce
({
disable
:
false
,
})
rootRef
.
value
!
.
style
.
willChange
=
'
auto
'
_isTouching
=
false
if
(
!
_checkCanMove
&&
!
_revise
(
'
out-of-bounds
'
)
&&
props
.
inertia
)
{
const
xv
=
(
1000
*
(
__touchInfo
.
historyX
[
1
]
-
__touchInfo
.
historyX
[
0
]))
/
(
__touchInfo
.
historyT
[
1
]
-
__touchInfo
.
historyT
[
0
])
const
yv
=
(
1000
*
(
__touchInfo
.
historyY
[
1
]
-
__touchInfo
.
historyY
[
0
]))
/
(
__touchInfo
.
historyT
[
1
]
-
__touchInfo
.
historyT
[
0
])
_friction
.
setV
(
xv
,
yv
)
_friction
.
setS
(
_translateX
,
_translateY
)
const
x0
=
_friction
.
delta
().
x
const
y0
=
_friction
.
delta
().
y
let
x
=
x0
+
_translateX
let
y
=
y0
+
_translateY
if
(
x
<
minX
.
value
)
{
x
=
minX
.
value
y
=
_translateY
+
((
minX
.
value
-
_translateX
)
*
y0
)
/
x0
}
else
{
if
(
x
>
maxX
.
value
)
{
x
=
maxX
.
value
y
=
_translateY
+
((
maxX
.
value
-
_translateX
)
*
y0
)
/
x0
}
}
if
(
y
<
minY
.
value
)
{
y
=
minY
.
value
x
=
_translateX
+
((
minY
.
value
-
_translateY
)
*
x0
)
/
y0
}
else
{
if
(
y
>
maxY
.
value
)
{
y
=
maxY
.
value
x
=
_translateX
+
((
maxY
.
value
-
_translateY
)
*
x0
)
/
y0
}
}
_friction
.
setEnd
(
x
,
y
)
_FA
=
g
(
_friction
,
function
()
{
let
t
=
_friction
.
s
()
let
x
=
t
.
x
let
y
=
t
.
y
_setTransform
(
x
,
y
,
_scale
,
'
friction
'
)
},
function
()
{
_FA
!
.
cancel
()
}
)
}
}
}
function
_getLimitXY
(
x
:
number
,
y
:
number
)
{
let
outOfBounds
=
false
if
(
x
>
maxX
.
value
)
{
x
=
maxX
.
value
outOfBounds
=
true
}
else
{
if
(
x
<
minX
.
value
)
{
x
=
minX
.
value
outOfBounds
=
true
}
}
if
(
y
>
maxY
.
value
)
{
y
=
maxY
.
value
outOfBounds
=
true
}
else
{
if
(
y
<
minY
.
value
)
{
y
=
minY
.
value
outOfBounds
=
true
}
}
return
{
x
,
y
,
outOfBounds
,
}
}
function
_updateOffset
()
{
_offset
.
x
=
p
(
rootRef
.
value
!
,
movableAreaRootRef
.
value
!
)
_offset
.
y
=
f
(
rootRef
.
value
!
,
movableAreaRootRef
.
value
!
)
}
function
_updateWH
(
scale
:
number
)
{
scale
=
scale
||
_scale
scale
=
_adjustScale
(
scale
)
let
rect
=
rootRef
.
value
!
.
getBoundingClientRect
()
height
.
value
=
rect
.
height
/
_scale
width
.
value
=
rect
.
width
/
_scale
let
_height
=
height
.
value
*
scale
let
_width
=
width
.
value
*
scale
_scaleOffset
.
x
=
(
_width
-
width
.
value
)
/
2
_scaleOffset
.
y
=
(
_height
-
height
.
value
)
/
2
}
function
_updateBoundary
()
{
let
x
=
0
-
_offset
.
x
+
_scaleOffset
.
x
let
_width
=
movableAreaWidth
.
value
-
width
.
value
-
_offset
.
x
-
_scaleOffset
.
x
minX
.
value
=
Math
.
min
(
x
,
_width
)
maxX
.
value
=
Math
.
max
(
x
,
_width
)
let
y
=
0
-
_offset
.
y
+
_scaleOffset
.
y
let
_height
=
movableAreaHeight
.
value
-
height
.
value
-
_offset
.
y
-
_scaleOffset
.
y
minY
.
value
=
Math
.
min
(
y
,
_height
)
maxY
.
value
=
Math
.
max
(
y
,
_height
)
}
function
_beginScale
()
{
_isScaling
=
true
}
function
_updateScale
(
scale
:
number
,
animat
?:
boolean
)
{
if
(
props
.
scale
)
{
scale
=
_adjustScale
(
scale
)
_updateWH
(
scale
)
_updateBoundary
()
const
limitXY
=
_getLimitXY
(
_translateX
,
_translateY
)
const
x
=
limitXY
.
x
const
y
=
limitXY
.
y
if
(
animat
)
{
_animationTo
(
x
,
y
,
scale
,
''
,
true
,
true
)
}
else
{
_requestAnimationFrame
(
function
()
{
_setTransform
(
x
,
y
,
scale
,
''
,
true
,
true
)
})
}
}
}
function
_updateOldScale
(
scale
:
number
)
{
_oldScale
=
scale
}
function
_adjustScale
(
scale
:
number
)
{
scale
=
Math
.
max
(
0.5
,
scaleMinNumber
.
value
,
scale
)
scale
=
Math
.
min
(
10
,
scaleMaxNumber
.
value
,
scale
)
return
scale
}
function
_animationTo
(
x
:
number
,
y
:
number
,
scale
:
number
,
source
?:
number
|
string
,
r
?:
boolean
,
o
?:
boolean
)
{
if
(
_FA
)
{
_FA
.
cancel
()
}
if
(
_SFA
)
{
_SFA
.
cancel
()
}
if
(
!
xMove
.
value
)
{
x
=
_translateX
}
if
(
!
yMove
.
value
)
{
y
=
_translateY
}
if
(
!
props
.
scale
)
{
scale
=
_scale
}
let
limitXY
=
_getLimitXY
(
x
,
y
)
x
=
limitXY
.
x
y
=
limitXY
.
y
if
(
!
props
.
animation
)
{
_setTransform
(
x
,
y
,
scale
,
source
,
r
,
o
)
return
}
_STD
.
_springX
.
_solution
=
null
_STD
.
_springY
.
_solution
=
null
_STD
.
_springScale
.
_solution
=
null
_STD
.
_springX
.
_endPosition
=
_translateX
_STD
.
_springY
.
_endPosition
=
_translateY
_STD
.
_springScale
.
_endPosition
=
_scale
_STD
.
setEnd
(
x
,
y
,
scale
,
1
)
_SFA
=
g
(
_STD
,
function
()
{
let
data
=
_STD
.
x
()
let
x
=
data
.
x
let
y
=
data
.
y
let
scale
=
data
.
scale
_setTransform
(
x
,
y
,
scale
,
source
,
r
,
o
)
},
function
()
{
_SFA
!
.
cancel
()
}
)
}
function
_revise
(
source
:
number
|
string
)
{
let
limitXY
=
_getLimitXY
(
_translateX
,
_translateY
)
let
x
=
limitXY
.
x
let
y
=
limitXY
.
y
let
outOfBounds
=
limitXY
.
outOfBounds
if
(
outOfBounds
)
{
_animationTo
(
x
,
y
,
_scale
,
source
)
}
return
outOfBounds
}
function
_setTransform
(
x
:
number
,
y
:
number
,
scale
:
number
,
source
:
string
|
number
=
''
,
r
?:
boolean
,
o
?:
boolean
)
{
if
(
!
(
x
!==
null
&&
x
.
toString
()
!==
'
NaN
'
&&
typeof
x
===
'
number
'
))
{
x
=
_translateX
||
0
}
if
(
!
(
y
!==
null
&&
y
.
toString
()
!==
'
NaN
'
&&
typeof
y
===
'
number
'
))
{
y
=
_translateY
||
0
}
x
=
Number
(
x
.
toFixed
(
1
))
y
=
Number
(
y
.
toFixed
(
1
))
scale
=
Number
(
scale
.
toFixed
(
1
))
if
(
!
(
_translateX
===
x
&&
_translateY
===
y
))
{
if
(
!
r
)
{
trigger
(
'
change
'
,
{}
as
Event
,
{
x
:
v
(
x
,
_scaleOffset
.
x
),
y
:
v
(
y
,
_scaleOffset
.
y
),
source
:
source
,
})
}
}
if
(
!
props
.
scale
)
{
scale
=
_scale
}
scale
=
_adjustScale
(
scale
)
scale
=
+
scale
.
toFixed
(
3
)
if
(
o
&&
scale
!==
_scale
)
{
trigger
(
'
scale
'
,
{}
as
Event
,
{
x
:
x
,
y
:
y
,
scale
:
scale
,
})
}
let
transform
=
'
translateX(
'
+
x
+
'
px) translateY(
'
+
y
+
'
px) translateZ(0px) scale(
'
+
scale
+
'
)
'
rootRef
.
value
!
.
style
.
transform
=
transform
rootRef
.
value
!
.
style
.
webkitTransform
=
transform
_translateX
=
x
_translateY
=
y
_scale
=
scale
}
function
setParent
()
{
if
(
!
_isMounted
.
value
)
{
return
}
if
(
_FA
)
{
_FA
.
cancel
()
}
if
(
_SFA
)
{
_SFA
.
cancel
()
}
let
scale
=
props
.
scale
?
scaleValueSync
.
value
:
1
_updateOffset
()
_updateWH
(
scale
)
_updateBoundary
()
_translateX
=
xSync
.
value
+
_scaleOffset
.
x
_translateY
=
ySync
.
value
+
_scaleOffset
.
y
let
limitXY
=
_getLimitXY
(
_translateX
,
_translateY
)
let
x
=
limitXY
.
x
let
y
=
limitXY
.
y
_setTransform
(
x
,
y
,
scale
,
''
,
true
)
_updateOldScale
(
scale
)
}
function
_endScale
()
{
_isScaling
=
false
_updateOldScale
(
_scale
)
}
function
_setScale
(
scale
:
number
)
{
if
(
scale
)
{
scale
=
_oldScale
*
scale
_beginScale
()
_updateScale
(
scale
)
}
}
onMounted
(()
=>
{
useTouchtrack
(
rootRef
.
value
!
,
(
event
)
=>
{
switch
(
event
.
detail
.
state
)
{
case
'
start
'
:
__handleTouchStart
()
break
case
'
move
'
:
__handleTouchMove
(
event
)
break
case
'
end
'
:
__handleTouchEnd
()
}
})
setParent
()
_friction
.
reconfigure
(
1
,
frictionNumber
.
value
)
_STD
.
reconfigure
(
1
,
(
9
*
Math
.
pow
(
dampingNumber
.
value
,
2
))
/
40
,
dampingNumber
.
value
)
rootRef
.
value
!
.
style
.
transformOrigin
=
'
center
'
initScrollBounce
()
const
context
:
MovableViewContext
=
{
rootRef
,
setParent
,
_endScale
,
_setScale
,
}
addMovableViewContext
(
context
)
onUnmounted
(()
=>
{
removeMovableViewContext
(
context
)
})
})
return
{
setParent
,
}
}
packages/uni-components/src/components/movable-view/index.vue
已删除
100644 → 0
浏览文件 @
ad51f136
<
template
>
<uni-movable-view
v-bind=
"$attrs"
>
<v-uni-resize-sensor
@
resize=
"setParent"
/>
<slot
/>
</uni-movable-view>
</
template
>
<
script
>
import
touchtrack
from
'
../../mixins/touchtrack
'
import
{
Decline
,
Friction
,
STD
}
from
'
./utils
'
import
{
disableScrollBounce
}
from
'
../../helpers/disable-scroll-bounce
'
var
requesting
=
false
function
_requestAnimationFrame
(
e
)
{
if
(
!
requesting
)
{
requesting
=
true
requestAnimationFrame
(
function
()
{
e
()
requesting
=
false
})
}
}
function
p
(
t
,
n
)
{
if
(
t
===
n
)
{
return
0
}
var
i
=
t
.
offsetLeft
return
t
.
offsetParent
?
(
i
+=
p
(
t
.
offsetParent
,
n
))
:
0
}
function
f
(
t
,
n
)
{
if
(
t
===
n
)
{
return
0
}
var
i
=
t
.
offsetTop
return
t
.
offsetParent
?
(
i
+=
f
(
t
.
offsetParent
,
n
))
:
0
}
function
v
(
a
,
b
)
{
return
+
((
1000
*
a
-
1000
*
b
)
/
1000
).
toFixed
(
1
)
}
function
g
(
e
,
t
,
n
)
{
var
i
=
function
(
e
)
{
if
(
e
&&
e
.
id
)
{
cancelAnimationFrame
(
e
.
id
)
}
if
(
e
)
{
e
.
cancelled
=
true
}
}
var
r
=
{
id
:
0
,
cancelled
:
false
}
function
fn
(
n
,
i
,
r
,
o
)
{
if
(
!
n
||
!
n
.
cancelled
)
{
r
(
i
)
var
a
=
e
.
done
()
if
(
!
a
)
{
if
(
!
n
.
cancelled
)
{
(
n
.
id
=
requestAnimationFrame
(
fn
.
bind
(
null
,
n
,
i
,
r
,
o
)))
}
}
if
(
a
&&
o
)
{
o
(
i
)
}
}
}
fn
(
r
,
e
,
t
,
n
)
return
{
cancel
:
i
.
bind
(
null
,
r
),
model
:
e
}
}
export
default
{
name
:
'
MovableView
'
,
mixins
:
[
touchtrack
],
props
:
{
direction
:
{
type
:
String
,
default
:
'
none
'
},
inertia
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
outOfBounds
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
x
:
{
type
:
[
Number
,
String
],
default
:
0
},
y
:
{
type
:
[
Number
,
String
],
default
:
0
},
damping
:
{
type
:
[
Number
,
String
],
default
:
20
},
friction
:
{
type
:
[
Number
,
String
],
default
:
2
},
disabled
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
scale
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
scaleMin
:
{
type
:
[
Number
,
String
],
default
:
0.5
},
scaleMax
:
{
type
:
[
Number
,
String
],
default
:
10
},
scaleValue
:
{
type
:
[
Number
,
String
],
default
:
1
},
animation
:
{
type
:
[
Boolean
,
String
],
default
:
true
}
},
data
()
{
return
{
xSync
:
this
.
_getPx
(
this
.
x
),
ySync
:
this
.
_getPx
(
this
.
y
),
scaleValueSync
:
Number
(
this
.
scaleValue
)
||
1
,
width
:
0
,
height
:
0
,
minX
:
0
,
minY
:
0
,
maxX
:
0
,
maxY
:
0
}
},
computed
:
{
dampingNumber
()
{
var
val
=
Number
(
this
.
damping
)
return
isNaN
(
val
)
?
20
:
val
},
frictionNumber
()
{
var
val
=
Number
(
this
.
friction
)
return
isNaN
(
val
)
||
val
<=
0
?
2
:
val
},
scaleMinNumber
()
{
var
val
=
Number
(
this
.
scaleMin
)
return
isNaN
(
val
)
?
0.5
:
val
},
scaleMaxNumber
()
{
var
val
=
Number
(
this
.
scaleMax
)
return
isNaN
(
val
)
?
10
:
val
},
xMove
()
{
return
this
.
direction
===
'
all
'
||
this
.
direction
===
'
horizontal
'
},
yMove
()
{
return
this
.
direction
===
'
all
'
||
this
.
direction
===
'
vertical
'
}
},
watch
:
{
x
(
val
)
{
this
.
xSync
=
this
.
_getPx
(
val
)
},
xSync
(
val
)
{
this
.
_setX
(
val
)
},
y
(
val
)
{
this
.
ySync
=
this
.
_getPx
(
val
)
},
ySync
(
val
)
{
this
.
_setY
(
val
)
},
scaleValue
(
val
)
{
this
.
scaleValueSync
=
Number
(
val
)
||
0
},
scaleValueSync
(
val
)
{
this
.
_setScaleValue
(
val
)
},
scaleMinNumber
()
{
this
.
_setScaleMinOrMax
()
},
scaleMaxNumber
()
{
this
.
_setScaleMinOrMax
()
}
},
created
:
function
()
{
this
.
_offset
=
{
x
:
0
,
y
:
0
}
this
.
_scaleOffset
=
{
x
:
0
,
y
:
0
}
this
.
_translateX
=
0
this
.
_translateY
=
0
this
.
_scale
=
1
this
.
_oldScale
=
1
this
.
_STD
=
new
STD
(
1
,
9
*
Math
.
pow
(
this
.
dampingNumber
,
2
)
/
40
,
this
.
dampingNumber
)
this
.
_friction
=
new
Friction
(
1
,
this
.
frictionNumber
)
this
.
_declineX
=
new
Decline
()
this
.
_declineY
=
new
Decline
()
this
.
__touchInfo
=
{
historyX
:
[
0
,
0
],
historyY
:
[
0
,
0
],
historyT
:
[
0
,
0
]
}
},
mounted
:
function
()
{
this
.
touchtrack
(
this
.
$el
,
'
_onTrack
'
)
this
.
setParent
()
this
.
_friction
.
reconfigure
(
1
,
this
.
frictionNumber
)
this
.
_STD
.
reconfigure
(
1
,
9
*
Math
.
pow
(
this
.
dampingNumber
,
2
)
/
40
,
this
.
dampingNumber
)
this
.
$el
.
style
.
transformOrigin
=
'
center
'
},
methods
:
{
_getPx
(
val
)
{
if
(
/
\d
+
[
ur
]
px$/i
.
test
(
val
))
{
return
uni
.
upx2px
(
parseFloat
(
val
))
}
return
Number
(
val
)
||
0
},
_setX
:
function
(
val
)
{
if
(
this
.
xMove
)
{
if
(
val
+
this
.
_scaleOffset
.
x
===
this
.
_translateX
)
{
return
this
.
_translateX
}
else
{
if
(
this
.
_SFA
)
{
this
.
_SFA
.
cancel
()
}
this
.
_animationTo
(
val
+
this
.
_scaleOffset
.
x
,
this
.
ySync
+
this
.
_scaleOffset
.
y
,
this
.
_scale
)
}
}
return
val
},
_setY
:
function
(
val
)
{
if
(
this
.
yMove
)
{
if
(
val
+
this
.
_scaleOffset
.
y
===
this
.
_translateY
)
{
return
this
.
_translateY
}
else
{
if
(
this
.
_SFA
)
{
this
.
_SFA
.
cancel
()
}
this
.
_animationTo
(
this
.
xSync
+
this
.
_scaleOffset
.
x
,
val
+
this
.
_scaleOffset
.
y
,
this
.
_scale
)
}
}
return
val
},
_setScaleMinOrMax
:
function
()
{
if
(
!
this
.
scale
)
{
return
false
}
this
.
_updateScale
(
this
.
_scale
,
true
)
this
.
_updateOldScale
(
this
.
_scale
)
},
_setScaleValue
:
function
(
scale
)
{
if
(
!
this
.
scale
)
{
return
false
}
scale
=
this
.
_adjustScale
(
scale
)
this
.
_updateScale
(
scale
,
true
)
this
.
_updateOldScale
(
scale
)
return
scale
},
__handleTouchStart
:
function
()
{
if
(
!
this
.
_isScaling
)
{
if
(
!
this
.
disabled
)
{
disableScrollBounce
({
disable
:
true
})
if
(
this
.
_FA
)
{
this
.
_FA
.
cancel
()
}
if
(
this
.
_SFA
)
{
this
.
_SFA
.
cancel
()
}
this
.
__touchInfo
.
historyX
=
[
0
,
0
]
this
.
__touchInfo
.
historyY
=
[
0
,
0
]
this
.
__touchInfo
.
historyT
=
[
0
,
0
]
if
(
this
.
xMove
)
{
this
.
__baseX
=
this
.
_translateX
}
if
(
this
.
yMove
)
{
this
.
__baseY
=
this
.
_translateY
}
this
.
$el
.
style
.
willChange
=
'
transform
'
this
.
_checkCanMove
=
null
this
.
_firstMoveDirection
=
null
this
.
_isTouching
=
true
}
}
},
__handleTouchMove
:
function
(
event
)
{
var
self
=
this
if
(
!
this
.
_isScaling
&&
!
this
.
disabled
&&
this
.
_isTouching
)
{
let
x
=
this
.
_translateX
let
y
=
this
.
_translateY
if
(
this
.
_firstMoveDirection
===
null
)
{
this
.
_firstMoveDirection
=
Math
.
abs
(
event
.
detail
.
dx
/
event
.
detail
.
dy
)
>
1
?
'
htouchmove
'
:
'
vtouchmove
'
}
if
(
this
.
xMove
)
{
x
=
event
.
detail
.
dx
+
this
.
__baseX
this
.
__touchInfo
.
historyX
.
shift
()
this
.
__touchInfo
.
historyX
.
push
(
x
)
if
(
!
this
.
yMove
&&
this
.
_checkCanMove
===
null
)
{
this
.
_checkCanMove
=
Math
.
abs
(
event
.
detail
.
dx
/
event
.
detail
.
dy
)
<
1
}
}
if
(
this
.
yMove
)
{
y
=
event
.
detail
.
dy
+
this
.
__baseY
this
.
__touchInfo
.
historyY
.
shift
()
this
.
__touchInfo
.
historyY
.
push
(
y
)
if
(
!
this
.
xMove
&&
this
.
_checkCanMove
===
null
)
{
this
.
_checkCanMove
=
Math
.
abs
(
event
.
detail
.
dy
/
event
.
detail
.
dx
)
<
1
}
}
this
.
__touchInfo
.
historyT
.
shift
()
this
.
__touchInfo
.
historyT
.
push
(
event
.
detail
.
timeStamp
)
if
(
!
this
.
_checkCanMove
)
{
event
.
preventDefault
()
let
source
=
'
touch
'
if
(
x
<
this
.
minX
)
{
if
(
this
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
x
=
this
.
minX
-
this
.
_declineX
.
x
(
this
.
minX
-
x
)
}
else
{
x
=
this
.
minX
}
}
else
if
(
x
>
this
.
maxX
)
{
if
(
this
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
x
=
this
.
maxX
+
this
.
_declineX
.
x
(
x
-
this
.
maxX
)
}
else
{
x
=
this
.
maxX
}
}
if
(
y
<
this
.
minY
)
{
if
(
this
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
y
=
this
.
minY
-
this
.
_declineY
.
x
(
this
.
minY
-
y
)
}
else
{
y
=
this
.
minY
}
}
else
{
if
(
y
>
this
.
maxY
)
{
if
(
this
.
outOfBounds
)
{
source
=
'
touch-out-of-bounds
'
y
=
this
.
maxY
+
this
.
_declineY
.
x
(
y
-
this
.
maxY
)
}
else
{
y
=
this
.
maxY
}
}
}
_requestAnimationFrame
(
function
()
{
self
.
_setTransform
(
x
,
y
,
self
.
_scale
,
source
)
})
}
}
},
__handleTouchEnd
:
function
()
{
var
self
=
this
if
(
!
this
.
_isScaling
&&
!
this
.
disabled
&&
this
.
_isTouching
)
{
disableScrollBounce
({
disable
:
false
})
this
.
$el
.
style
.
willChange
=
'
auto
'
this
.
_isTouching
=
false
if
(
!
this
.
_checkCanMove
&&
!
this
.
_revise
(
'
out-of-bounds
'
)
&&
this
.
inertia
)
{
const
xv
=
1000
*
(
this
.
__touchInfo
.
historyX
[
1
]
-
this
.
__touchInfo
.
historyX
[
0
])
/
(
this
.
__touchInfo
.
historyT
[
1
]
-
this
.
__touchInfo
.
historyT
[
0
])
const
yv
=
1000
*
(
this
.
__touchInfo
.
historyY
[
1
]
-
this
.
__touchInfo
.
historyY
[
0
])
/
(
this
.
__touchInfo
.
historyT
[
1
]
-
this
.
__touchInfo
.
historyT
[
0
])
this
.
_friction
.
setV
(
xv
,
yv
)
this
.
_friction
.
setS
(
this
.
_translateX
,
this
.
_translateY
)
const
x0
=
this
.
_friction
.
delta
().
x
const
y0
=
this
.
_friction
.
delta
().
y
let
x
=
x0
+
this
.
_translateX
let
y
=
y0
+
this
.
_translateY
if
(
x
<
this
.
minX
)
{
x
=
this
.
minX
y
=
this
.
_translateY
+
(
this
.
minX
-
this
.
_translateX
)
*
y0
/
x0
}
else
{
if
(
x
>
this
.
maxX
)
{
x
=
this
.
maxX
y
=
this
.
_translateY
+
(
this
.
maxX
-
this
.
_translateX
)
*
y0
/
x0
}
}
if
(
y
<
this
.
minY
)
{
y
=
this
.
minY
x
=
this
.
_translateX
+
(
this
.
minY
-
this
.
_translateY
)
*
x0
/
y0
}
else
{
if
(
y
>
this
.
maxY
)
{
y
=
this
.
maxY
x
=
this
.
_translateX
+
(
this
.
maxY
-
this
.
_translateY
)
*
x0
/
y0
}
}
this
.
_friction
.
setEnd
(
x
,
y
)
this
.
_FA
=
g
(
this
.
_friction
,
function
()
{
var
t
=
self
.
_friction
.
s
()
var
x
=
t
.
x
var
y
=
t
.
y
self
.
_setTransform
(
x
,
y
,
self
.
_scale
,
'
friction
'
)
},
function
()
{
self
.
_FA
.
cancel
()
})
}
}
},
_onTrack
:
function
(
event
)
{
switch
(
event
.
detail
.
state
)
{
case
'
start
'
:
this
.
__handleTouchStart
()
break
case
'
move
'
:
this
.
__handleTouchMove
(
event
)
break
case
'
end
'
:
this
.
__handleTouchEnd
()
}
},
_getLimitXY
:
function
(
x
,
y
)
{
var
outOfBounds
=
false
if
(
x
>
this
.
maxX
)
{
x
=
this
.
maxX
outOfBounds
=
true
}
else
{
if
(
x
<
this
.
minX
)
{
x
=
this
.
minX
outOfBounds
=
true
}
}
if
(
y
>
this
.
maxY
)
{
y
=
this
.
maxY
outOfBounds
=
true
}
else
{
if
(
y
<
this
.
minY
)
{
y
=
this
.
minY
outOfBounds
=
true
}
}
return
{
x
,
y
,
outOfBounds
}
},
setParent
:
function
()
{
if
(
!
this
.
$parent
.
_isMounted
)
{
return
}
if
(
this
.
_FA
)
{
this
.
_FA
.
cancel
()
}
if
(
this
.
_SFA
)
{
this
.
_SFA
.
cancel
()
}
var
scale
=
this
.
scale
?
this
.
scaleValueSync
:
1
this
.
_updateOffset
()
this
.
_updateWH
(
scale
)
this
.
_updateBoundary
()
this
.
_translateX
=
this
.
xSync
+
this
.
_scaleOffset
.
x
this
.
_translateY
=
this
.
ySync
+
this
.
_scaleOffset
.
y
var
limitXY
=
this
.
_getLimitXY
(
this
.
_translateX
,
this
.
_translateY
)
var
x
=
limitXY
.
x
var
y
=
limitXY
.
y
this
.
_setTransform
(
x
,
y
,
scale
,
''
,
true
)
this
.
_updateOldScale
(
scale
)
},
_updateOffset
:
function
()
{
this
.
_offset
.
x
=
p
(
this
.
$el
,
this
.
$parent
.
$el
)
this
.
_offset
.
y
=
f
(
this
.
$el
,
this
.
$parent
.
$el
)
},
_updateWH
:
function
(
scale
)
{
scale
=
scale
||
this
.
_scale
scale
=
this
.
_adjustScale
(
scale
)
var
rect
=
this
.
$el
.
getBoundingClientRect
()
this
.
height
=
rect
.
height
/
this
.
_scale
this
.
width
=
rect
.
width
/
this
.
_scale
var
height
=
this
.
height
*
scale
var
width
=
this
.
width
*
scale
this
.
_scaleOffset
.
x
=
(
width
-
this
.
width
)
/
2
this
.
_scaleOffset
.
y
=
(
height
-
this
.
height
)
/
2
},
_updateBoundary
:
function
()
{
var
x
=
0
-
this
.
_offset
.
x
+
this
.
_scaleOffset
.
x
var
width
=
this
.
$parent
.
width
-
this
.
width
-
this
.
_offset
.
x
-
this
.
_scaleOffset
.
x
this
.
minX
=
Math
.
min
(
x
,
width
)
this
.
maxX
=
Math
.
max
(
x
,
width
)
var
y
=
0
-
this
.
_offset
.
y
+
this
.
_scaleOffset
.
y
var
height
=
this
.
$parent
.
height
-
this
.
height
-
this
.
_offset
.
y
-
this
.
_scaleOffset
.
y
this
.
minY
=
Math
.
min
(
y
,
height
)
this
.
maxY
=
Math
.
max
(
y
,
height
)
},
_beginScale
:
function
()
{
this
.
_isScaling
=
true
},
_endScale
:
function
()
{
this
.
_isScaling
=
false
this
.
_updateOldScale
(
this
.
_scale
)
},
_setScale
:
function
(
scale
)
{
if
(
this
.
scale
)
{
scale
=
this
.
_adjustScale
(
scale
)
scale
=
this
.
_oldScale
*
scale
this
.
_beginScale
()
this
.
_updateScale
(
scale
)
}
},
_updateScale
:
function
(
scale
,
animat
)
{
var
self
=
this
if
(
this
.
scale
)
{
scale
=
this
.
_adjustScale
(
scale
)
this
.
_updateWH
(
scale
)
this
.
_updateBoundary
()
const
limitXY
=
this
.
_getLimitXY
(
this
.
_translateX
,
this
.
_translateY
)
const
x
=
limitXY
.
x
const
y
=
limitXY
.
y
if
(
animat
)
{
this
.
_animationTo
(
x
,
y
,
scale
,
''
,
true
,
true
)
}
else
{
_requestAnimationFrame
(
function
()
{
self
.
_setTransform
(
x
,
y
,
scale
,
''
,
true
,
true
)
})
}
}
},
_updateOldScale
:
function
(
scale
)
{
this
.
_oldScale
=
scale
},
_adjustScale
:
function
(
scale
)
{
scale
=
Math
.
max
(
0.5
,
this
.
scaleMinNumber
,
scale
)
scale
=
Math
.
min
(
10
,
this
.
scaleMaxNumber
,
scale
)
return
scale
},
_animationTo
:
function
(
x
,
y
,
scale
,
source
,
r
,
o
)
{
var
self
=
this
if
(
this
.
_FA
)
{
this
.
_FA
.
cancel
()
}
if
(
this
.
_SFA
)
{
this
.
_SFA
.
cancel
()
}
if
(
!
this
.
xMove
)
{
x
=
this
.
_translateX
}
if
(
!
this
.
yMove
)
{
y
=
this
.
_translateY
}
if
(
!
this
.
scale
)
{
scale
=
this
.
_scale
}
var
limitXY
=
this
.
_getLimitXY
(
x
,
y
)
x
=
limitXY
.
x
y
=
limitXY
.
y
if
(
!
this
.
animation
)
{
this
.
_setTransform
(
x
,
y
,
scale
,
source
,
r
,
o
)
return
}
this
.
_STD
.
_springX
.
_solution
=
null
this
.
_STD
.
_springY
.
_solution
=
null
this
.
_STD
.
_springScale
.
_solution
=
null
this
.
_STD
.
_springX
.
_endPosition
=
this
.
_translateX
this
.
_STD
.
_springY
.
_endPosition
=
this
.
_translateY
this
.
_STD
.
_springScale
.
_endPosition
=
this
.
_scale
this
.
_STD
.
setEnd
(
x
,
y
,
scale
,
1
)
this
.
_SFA
=
g
(
this
.
_STD
,
function
()
{
var
data
=
self
.
_STD
.
x
()
var
x
=
data
.
x
var
y
=
data
.
y
var
scale
=
data
.
scale
self
.
_setTransform
(
x
,
y
,
scale
,
source
,
r
,
o
)
},
function
()
{
self
.
_SFA
.
cancel
()
})
},
_revise
:
function
(
source
)
{
var
limitXY
=
this
.
_getLimitXY
(
this
.
_translateX
,
this
.
_translateY
)
var
x
=
limitXY
.
x
var
y
=
limitXY
.
y
var
outOfBounds
=
limitXY
.
outOfBounds
if
(
outOfBounds
)
{
this
.
_animationTo
(
x
,
y
,
this
.
_scale
,
source
)
}
return
outOfBounds
},
_setTransform
:
function
(
x
,
y
,
scale
,
source
=
''
,
r
,
o
)
{
if
(
!
(
x
!==
null
&&
x
.
toString
()
!==
'
NaN
'
&&
typeof
x
===
'
number
'
))
{
x
=
this
.
_translateX
||
0
}
if
(
!
(
y
!==
null
&&
y
.
toString
()
!==
'
NaN
'
&&
typeof
y
===
'
number
'
))
{
y
=
this
.
_translateY
||
0
}
x
=
Number
(
x
.
toFixed
(
1
))
y
=
Number
(
y
.
toFixed
(
1
))
scale
=
Number
(
scale
.
toFixed
(
1
))
if
(
!
(
this
.
_translateX
===
x
&&
this
.
_translateY
===
y
))
{
if
(
!
r
)
{
this
.
$trigger
(
'
change
'
,
{},
{
x
:
v
(
x
,
this
.
_scaleOffset
.
x
),
y
:
v
(
y
,
this
.
_scaleOffset
.
y
),
source
:
source
})
}
}
if
(
!
this
.
scale
)
{
scale
=
this
.
_scale
}
scale
=
this
.
_adjustScale
(
scale
)
scale
=
+
scale
.
toFixed
(
3
)
if
(
o
&&
scale
!==
this
.
_scale
)
{
this
.
$trigger
(
'
scale
'
,
{},
{
x
:
x
,
y
:
y
,
scale
:
scale
})
}
var
transform
=
'
translateX(
'
+
x
+
'
px) translateY(
'
+
y
+
'
px) translateZ(0px) scale(
'
+
scale
+
'
)
'
this
.
$el
.
style
.
transform
=
transform
this
.
$el
.
style
.
webkitTransform
=
transform
this
.
_translateX
=
x
this
.
_translateY
=
y
this
.
_scale
=
scale
}
}
}
</
script
>
\ No newline at end of file
packages/uni-components/src/helpers/useTouchtrack.ts
浏览文件 @
6e8dfd97
...
@@ -26,10 +26,10 @@ const addListenerToElement = function (
...
@@ -26,10 +26,10 @@ const addListenerToElement = function (
}
}
)
)
}
}
type
State
=
'
start
'
|
'
move
'
|
'
end
'
|
'
cancel
'
type
TouchOrMouseEvent
=
TouchEvent
|
MouseEvent
type
TouchOrMouseEvent
=
TouchEvent
|
MouseEvent
type
Detail
=
{
type
Detail
=
{
state
:
any
state
:
State
x0
:
number
x0
:
number
y0
:
number
y0
:
number
dx
:
number
dx
:
number
...
@@ -67,7 +67,7 @@ export function useTouchtrack(
...
@@ -67,7 +67,7 @@ export function useTouchtrack(
let
y1
=
0
let
y1
=
0
const
fn
=
function
(
const
fn
=
function
(
$event
:
TouchOrMouseEvent
,
$event
:
TouchOrMouseEvent
,
state
:
any
,
state
:
State
,
x
:
number
,
x
:
number
,
y
:
number
y
:
number
)
{
)
{
...
...
packages/uni-h5/dist/uni-h5.cjs.js
浏览文件 @
6e8dfd97
此差异已折叠。
点击以展开。
packages/uni-h5/dist/uni-h5.es.js
浏览文件 @
6e8dfd97
此差异已折叠。
点击以展开。
packages/uni-h5/src/view/components/web-view/index.tsx
浏览文件 @
6e8dfd97
...
@@ -52,6 +52,7 @@ export default /*#__PURE__*/ defineComponent({
...
@@ -52,6 +52,7 @@ export default /*#__PURE__*/ defineComponent({
{
...
$excludeAttrs
.
value
}
{
...
$excludeAttrs
.
value
}
ref
=
{
rootRef
}
ref
=
{
rootRef
}
>
>
{
/* @ts-ignore */
}
<
ResizeSensor
onResize
=
{
_resize
}
/>
<
ResizeSensor
onResize
=
{
_resize
}
/>
</
uni
-
web
-
view
>
</
uni
-
web
-
view
>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录