Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
fyge_for_tb
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王剑峰
fyge_for_tb
Commits
b74d8660
Commit
b74d8660
authored
Jun 24, 2022
by
邱旭
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
合并2.0.70一点东西
parent
36e2ca2a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
814 additions
and
28 deletions
+814
-28
FpsPanel.ts
src/2d/FpsPanel.ts
+102
-0
Container.ts
src/2d/display/Container.ts
+37
-8
Event.ts
src/2d/events/Event.ts
+12
-18
ScrollView.ts
src/2d/ui/ScrollView.ts
+661
-0
index.ts
src/index.ts
+2
-2
No files found.
src/2d/FpsPanel.ts
0 → 100644
View file @
b74d8660
import
{
createCanvas
}
from
"./utils"
;
import
{
Sprite
}
from
"./display"
;
import
{
Texture
}
from
"./texture"
;
export
class
FpsPanel
extends
Sprite
{
private
context
:
CanvasRenderingContext2D
;
private
bgColor
:
string
=
'#002002'
;
private
textColor
:
string
=
'#0ff0ff'
;
private
PR
:
number
=
3
;
private
WIDTH
=
80
*
this
.
PR
;
private
HEIGHT
=
48
*
this
.
PR
;
private
TEXT_X
=
3
*
this
.
PR
;
private
TEXT_Y
=
2
*
this
.
PR
;
private
GRAPH_X
=
3
*
this
.
PR
;
private
GRAPH_Y
=
15
*
this
.
PR
;
private
GRAPH_WIDTH
=
74
*
this
.
PR
;
private
GRAPH_HEIGHT
=
30
*
this
.
PR
;
private
GRAPH_SIZE
=
74
;
private
maxValue
=
120
;
private
min
=
Infinity
;
private
max
=
0
;
private
items
=
[];
/**
* 帧率面板
* 后续可以加入每次drawCall,总绘制对象等等
*/
constructor
()
{
super
()
//离屏canvas
var
canvas
=
createCanvas
();
canvas
.
width
=
this
.
WIDTH
;
canvas
.
height
=
this
.
HEIGHT
;
this
.
texture
=
Texture
.
fromCanvas
(
canvas
)
this
.
context
=
canvas
.
getContext
(
"2d"
);
this
.
context
.
font
=
'bold '
+
(
9
*
this
.
PR
)
+
'px Helvetica,Arial,sans-serif'
;
this
.
context
.
textBaseline
=
'top'
;
this
.
updateText
(
"FPS"
);
}
private
lastTime
:
number
=
Date
.
now
();
private
frames
:
number
=
0
;
reset
()
{
this
.
lastTime
=
Date
.
now
();
this
.
min
=
Infinity
;
this
.
max
=
0
;
this
.
items
.
length
=
0
;
this
.
frames
=
0
;
}
update
()
{
this
.
frames
++
;
var
time
=
Date
.
now
();
//每秒跑一次
if
(
time
>=
this
.
lastTime
+
1000
)
{
var
value
=
(
this
.
frames
*
1000
)
/
(
time
-
this
.
lastTime
);
this
.
updatePanel
(
value
)
this
.
lastTime
=
time
;
this
.
frames
=
0
;
}
super
.
update
();
}
private
updatePanel
(
value
:
number
)
{
const
{
items
,
GRAPH_SIZE
,
context
,
GRAPH_X
,
textColor
,
GRAPH_Y
,
PR
,
GRAPH_HEIGHT
,
bgColor
,
maxValue
}
=
this
items
.
push
(
value
);
while
(
items
.
length
>
GRAPH_SIZE
)
{
items
.
shift
();
}
this
.
min
=
Math
.
min
(
this
.
min
,
value
);
this
.
max
=
Math
.
max
(
this
.
max
,
value
);
this
.
updateText
(
Math
.
round
(
value
)
+
' FPS ('
+
Math
.
round
(
this
.
min
)
+
'-'
+
Math
.
round
(
this
.
max
)
+
')'
);
for
(
var
i
=
0
;
i
<
items
.
length
;
i
++
)
{
var
startPos
=
GRAPH_X
+
(
i
+
GRAPH_SIZE
-
items
.
length
)
*
PR
;
context
.
fillStyle
=
textColor
;
context
.
globalAlpha
=
1
;
context
.
fillRect
(
startPos
,
GRAPH_Y
,
PR
,
GRAPH_HEIGHT
);
context
.
fillStyle
=
bgColor
;
context
.
globalAlpha
=
0.9
;
context
.
fillRect
(
startPos
,
GRAPH_Y
,
PR
,
Math
.
round
((
1
-
(
items
[
i
]
/
maxValue
))
*
GRAPH_HEIGHT
));
}
this
.
texture
.
update
();
}
private
updateText
(
text
:
string
)
{
const
{
context
,
bgColor
,
textColor
,
WIDTH
,
HEIGHT
,
TEXT_X
,
TEXT_Y
,
GRAPH_X
,
GRAPH_Y
,
GRAPH_WIDTH
,
GRAPH_HEIGHT
}
=
this
context
.
fillStyle
=
bgColor
;
context
.
globalAlpha
=
1
;
context
.
fillRect
(
0
,
0
,
WIDTH
,
HEIGHT
);
context
.
fillStyle
=
textColor
;
context
.
fillText
(
text
,
TEXT_X
,
TEXT_Y
);
context
.
fillRect
(
GRAPH_X
,
GRAPH_Y
,
GRAPH_WIDTH
,
GRAPH_HEIGHT
);
context
.
fillStyle
=
bgColor
;
context
.
globalAlpha
=
0.9
;
context
.
fillRect
(
GRAPH_X
,
GRAPH_Y
,
GRAPH_WIDTH
,
GRAPH_HEIGHT
);
}
}
src/2d/display/Container.ts
View file @
b74d8660
...
...
@@ -55,7 +55,7 @@ export default class Container extends DisplayObject {
}
/**
* 批量添加child
* @param children
* @param children
*/
addChildren
<
T
extends
DisplayObject
>
(...
children
:
T
[]):
T
[]
{
children
.
forEach
((
child
:
T
)
=>
{
this
.
addChild
(
child
);
})
...
...
@@ -167,7 +167,7 @@ export default class Container extends DisplayObject {
/**
* 设置child的层级索引
* @param {DisplayObject} child
* @param {DisplayObject} child
* @param {number} index
*/
setChildIndex
(
child
:
DisplayObject
,
index
:
number
)
{
...
...
@@ -176,7 +176,7 @@ export default class Container extends DisplayObject {
/**
* 根据索引获取子级对象
* @param {number} index
* @param {number} index
* @return {DisplayObject}
*/
getChildAt
(
index
:
number
):
DisplayObject
{
...
...
@@ -188,9 +188,9 @@ export default class Container extends DisplayObject {
/**
* 通过名字获取子级
* @param name
* @param isOnlyOne
* @param isRecursive
* @param name
* @param isOnlyOne
* @param isRecursive
*/
public
getChildByName
(
name
:
string
|
RegExp
,
isOnlyOne
:
boolean
=
true
,
isRecursive
:
boolean
=
false
):
any
{
if
(
!
name
)
return
null
;
...
...
@@ -216,7 +216,7 @@ export default class Container extends DisplayObject {
/**
* 移除child
* @param {DisplayObject} child
* @return {DisplayObject}
* @return {DisplayObject}
*/
removeChild
(
child
:
DisplayObject
):
DisplayObject
{
...
...
@@ -231,7 +231,7 @@ export default class Container extends DisplayObject {
/**
* 在index索引处移除子级对象
* @param {number} index
* @param {number} index
* @return {DisplayObject} 移除的子级对象
*/
removeChildAt
(
index
:
number
):
DisplayObject
{
...
...
@@ -671,6 +671,35 @@ export default class Container extends DisplayObject {
}
}
}
/**
* 操作子级的所有方法,需要维护
*/
public
static
_childrenOperationMethods
:
string
[]
=
[
//添加子级的方法
"addChild"
,
"addChildAt"
,
"addChildren"
,
//移除子级的方法
"removeChild"
,
"removeChildAt"
,
"removeChildren"
,
"removeAllChildren"
,
"removeChildrenAt"
,
"spliceChildren"
,
//获取子级的方法
"getChildAt"
,
"getChildByName"
,
"getChildrenByName"
,
//获取子级索引的方法
"getChildIndex"
,
//改变子级索引的方法
"setChildIndex"
,
"swapChildren"
]
}
Container
.
prototype
.
containerUpdateTransform
=
Container
.
prototype
.
updateTransform
;
function
judgeMaskEnable
(
mask
):
boolean
{
if
(
!
mask
)
return
false
;
//Shape遮罩,或者Sprite遮罩
if
(
mask
.
texture
)
{
mask
.
updateShape
&&
mask
.
updateShape
();
//更新一下
if
(
!
mask
.
texture
.
valid
)
return
false
;
}
//Graphics遮罩,其实这个判断也包括了Sprite的纹理为空的情况
else
if
(
!
mask
.
graphicsData
||
!
mask
.
graphicsData
.
length
)
{
return
false
;
}
return
true
;
}
src/2d/events/Event.ts
View file @
b74d8660
...
...
@@ -19,7 +19,7 @@ export class Event extends HashObject {
public
static
RESIZE
:
string
=
"onResize"
;
/**
* Scroll
Page
组件滑动到开始位置事件
* Scroll组件滑动到开始位置事件
* @property SCROLL_TO_HEAD
* @static
* @since 1.1.0
...
...
@@ -27,7 +27,7 @@ export class Event extends HashObject {
*/
public
static
SCROLL_TO_HEAD
:
string
=
"onScrollToHead"
;
/**
* Scroll
Page
组件停止滑动事件
* Scroll组件停止滑动事件
* @property SCROLL_STOP
* @static
* @since 1.1.0
...
...
@@ -35,7 +35,7 @@ export class Event extends HashObject {
*/
public
static
SCROLL_STOP
:
string
=
"onScrollStop"
;
/**
* Scroll
Page
组件开始滑动事件
* Scroll组件开始滑动事件
* @property SCROLL_START
* @static
* @since 1.1.0
...
...
@@ -43,13 +43,17 @@ export class Event extends HashObject {
*/
public
static
SCROLL_START
:
string
=
"onScrollStart"
;
/**
* Scroll
Page
组件滑动到结束位置事件
* @property
ON_
SCROLL_TO_END
* Scroll组件滑动到结束位置事件
* @property SCROLL_TO_END
* @static
* @since 1.1.0
* @type {string}
*/
public
static
SCROLL_TO_END
:
string
=
"onScrollToEnd"
;
/**
* Scroll组件滚动时触发
*/
public
static
SCROLLING
:
string
=
"onScrolling"
;
/**
* 舞台初始化完成后会触发的事件
* @property INIT_STAGE
...
...
@@ -71,7 +75,7 @@ export class Event extends HashObject {
/**
* 显示对象从舞台移出事件
* @Event
* @property REMOVE
_TO
_STAGE
* @property REMOVE
D_FROM
_STAGE
* @type {string}
* @static
* @public
...
...
@@ -89,7 +93,7 @@ export class Event extends HashObject {
*/
public
static
ENTER_FRAME
:
string
=
"onEnterFrame"
;
/**
*
Movie
Clip 播放完成事件
*
Animation
Clip 播放完成事件
* @Event
* @property END_FRAME
* @type {string}
...
...
@@ -98,16 +102,6 @@ export class Event extends HashObject {
* @since 1.0.0
*/
public
static
END_FRAME
:
string
=
"onEndFrame"
;
/**
* MovieClip 帧标签事件
* @Event
* @property CALL_FRAME
* @type {string}
* @static
* @public
* @since 1.0.0
*/
public
static
CALL_FRAME
:
string
=
"onCallFrame"
;
/**
* 完成事件
* @Event
...
...
@@ -234,7 +228,7 @@ export class Event extends HashObject {
}
/**
* 重
围事件到初始状态方便重复利用
* 重
置事件
* @method reset
* @param {string} type
* @param target
...
...
src/2d/ui/ScrollView.ts
0 → 100644
View file @
b74d8660
import
{
Ease
}
from
"../../tween"
;
import
{
Container
}
from
"../display"
;
import
{
Event
,
MouseEvent
}
from
"../events"
;
import
{
Graphics
}
from
"../graphics"
;
/**
* 滚动视图
*/
export
class
ScrollView
extends
Container
{
protected
_scrollWidth
:
number
;
/**
* 滚动宽度
* 设置0表示不让滚动
*/
get
scrollWidth
()
{
return
this
.
_scrollWidth
}
set
scrollWidth
(
v
:
number
)
{
if
(
this
.
_scrollWidth
==
v
)
return
;
this
.
_scrollWidth
=
v
;
//改变
this
.
checkPosition
(
this
.
bounceTime
)
}
protected
_scrollHeight
:
number
;
/**
* 滚动高度
* 设置0表示不让滚动
*/
get
scrollHeight
()
{
return
this
.
_scrollHeight
}
set
scrollHeight
(
v
:
number
)
{
if
(
this
.
_scrollHeight
==
v
)
return
;
this
.
_scrollHeight
=
v
;
//改变
this
.
checkPosition
(
this
.
bounceTime
)
}
/**
* 最大滚动坐标x,为负
*/
private
get
maxScrollX
():
number
{
//不能滚动,就是0
if
(
!
this
.
scrollWidth
)
return
0
;
//
return
Math
.
min
(
this
.
viewWidth
-
this
.
scrollWidth
,
0
);
};
/**
* 最大滚动坐标y,为负
*/
private
get
maxScrollY
():
number
{
//不能滚动,就是0
if
(
!
this
.
scrollHeight
)
return
0
;
return
Math
.
min
(
this
.
viewHeight
-
this
.
scrollHeight
,
0
);
};
//容器
protected
_content
:
Container
;
/**
* 滚动内容的节点容器
* 注意滚动内容都往这上面加
*/
get
view
()
{
return
this
.
_content
;
}
/**
* 可见区域的宽
* @property viewWidth
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected
viewWidth
:
number
=
0
;
/**
* 可见区域的高
* @property viewHeight
* @type {number}
* @protected
* @since 1.0.0
* @default 0
*/
protected
viewHeight
:
number
=
0
;
/**
* 遮罩对象
* @property maskObj
* @since 1.0.0
* @private
* @type {Graphics}
*/
private
maskObj
:
Graphics
;
private
downX
:
number
private
downY
:
number
private
distX
:
number
;
private
distY
:
number
;
private
startX
:
number
private
startY
:
number
private
destX
:
number
private
destY
:
number
private
isRunning
:
boolean
;
private
startTime
:
number
;
private
destTime
:
number
;
private
duration
:
number
;
private
easeFn
:
(
t
:
number
)
=>
number
;
private
static
weight
=
[
1
,
1.33
,
1.66
,
2
,
2.33
];
private
velocitys
:
[
number
,
number
][]
=
[];
private
lastTouchTime
:
number
/**
* 手指拖动超过边界时是否允许回弹。默认true
*/
public
isBounce
:
boolean
=
true
/**
* 回弹时间,视图内容在不合理的位置时恢复的时间,比如超过边界时
*/
public
bounceTime
:
number
=
300
;
/**
* 手指抬起后是否存在惯性。默认true
*/
public
hasMomentum
:
boolean
=
true
;
/**
* 惯性的阻尼
* 默认0.002
*/
public
damping
:
number
=
0.002
/**
* 0无交互状态
* 1点击状态
* 2移动状态
*/
private
mouseStatus
:
0
|
1
|
2
=
0
;
/**
* 注意滚动内容在view里加
* @method ScrollPage
* @param {number} vW 可视区域宽
* @param {number} vH 可视区域高
* @param {number} sW 最大横向滚动距离
* @param {number} sH 最大纵向滚动距离
* @param {boolean} isFullScreen 是否全屏
* @example
* var scroll=new ScrollView(750,1000,0,2000);
* stage.addChild(scroll);
* //加滚动内容
* scroll.view.addChild(new Sprite());
*/
constructor
(
vW
:
number
,
vH
:
number
,
sW
:
number
,
sH
:
number
,
isFullScreen
?:
boolean
)
{
super
();
let
s
:
ScrollView
=
this
;
s
.
_instanceType
=
"ScrollView"
;
//视图容器,必须用super.addChildAt,其他都被重写了
s
.
_content
=
super
.
addChildAt
(
new
Container
(),
0
);
s
.
maskObj
=
super
.
addChildAt
(
new
Graphics
(),
0
);
s
.
maskObj
.
alpha
=
0
;
//有传过才赋值
if
(
typeof
sW
==
"number"
)
s
.
_scrollWidth
=
sW
;
if
(
typeof
sH
==
"number"
)
s
.
_scrollHeight
=
sH
;
//设置第一次
s
.
setViewRect
(
vW
,
vH
,
isFullScreen
);
//添加到舞台,需要注意local坐标替换成stage坐标
s
.
addEventListener
(
Event
.
ADDED_TO_STAGE
,
function
(
e
:
Event
)
{
s
.
stage
.
addEventListener
(
MouseEvent
.
MOUSE_MOVE
,
s
.
onMouseEvent
,
s
);
s
.
stage
.
addEventListener
(
MouseEvent
.
MOUSE_UP
,
s
.
onMouseEvent
,
s
);
});
s
.
addEventListener
(
Event
.
REMOVED_FROM_STAGE
,
function
(
e
:
Event
)
{
s
.
stage
.
removeEventListener
(
MouseEvent
.
MOUSE_MOVE
,
s
.
onMouseEvent
,
s
);
s
.
stage
.
removeEventListener
(
MouseEvent
.
MOUSE_UP
,
s
.
onMouseEvent
,
s
);
});
s
.
addEventListener
(
MouseEvent
.
MOUSE_DOWN
,
s
.
onMouseEvent
,
s
,
false
);
// s.addEventListener(MouseEvent.MOUSE_MOVE, s.onMouseEvent, s);
// s.addEventListener(MouseEvent.MOUSE_UP, s.onMouseEvent, s);
// s.addEventListener(MouseEvent.MOUSE_OUT, s.onMouseEvent, s);
s
.
addEventListener
(
Event
.
ENTER_FRAME
,
s
.
onEnterFrame
,
s
)
}
/**
* 设置可见区域,可见区域的坐标始终在本地坐标中0,0点位置
* @method setViewRect
* @param {number}w 设置可见区域的宽
* @param {number}h 设置可见区域的高
* @param {boolean} isVertical 方向
* @public
* @since 1.1.1
*/
public
setViewRect
(
w
:
number
,
h
:
number
,
isFull
?:
boolean
):
void
{
let
s
=
this
;
//不全屏才设置mask
if
(
!
isFull
)
{
//加遮罩
s
.
_content
.
mask
=
s
.
maskObj
;
//为了能接收鼠标事件设置_isUsedToMask
s
.
maskObj
.
_isUsedToMask
=
false
;
//绘制
s
.
maskObj
.
clear
()
.
beginFill
(
0
)
.
drawRect
(
0
,
0
,
w
,
h
)
.
endFill
();
}
//移除遮罩
else
{
s
.
_content
.
mask
=
null
;
}
//视窗尺寸
s
.
viewWidth
=
w
;
s
.
viewHeight
=
h
;
//改变
this
.
checkPosition
(
s
.
bounceTime
)
}
private
onMouseEvent
(
e
:
MouseEvent
):
void
{
let
s
=
this
;
//点的时候
if
(
e
.
type
==
MouseEvent
.
MOUSE_DOWN
)
{
s
.
isRunning
=
false
;
//阻止冒泡
e
.
stopPropagation
()
//标记一下状态
s
.
mouseStatus
=
1
;
s
.
lastTouchTime
=
Date
.
now
();
//记录点击的位置
s
.
downX
=
e
.
stageX
;
s
.
downY
=
e
.
stageY
;
s
.
distX
=
0
;
s
.
distY
=
0
;
}
else
if
(
e
.
type
==
MouseEvent
.
MOUSE_MOVE
)
{
//不是down过来的
if
(
s
.
mouseStatus
<
1
)
return
;
//计算间隔
let
deltaX
=
e
.
stageX
-
s
.
downX
,
deltaY
=
e
.
stageY
-
s
.
downY
,
timestamp
=
Date
.
now
();
s
.
downX
=
e
.
stageX
;
s
.
downY
=
e
.
stageY
;
s
.
distX
+=
deltaX
;
s
.
distY
+=
deltaY
;
let
absDistX
=
Math
.
abs
(
s
.
distX
);
let
absDistY
=
Math
.
abs
(
s
.
distY
);
//上一步是开始的,超出10才滑动
if
(
s
.
mouseStatus
==
1
&&
absDistX
<
10
&&
absDistY
<
10
)
{
s
.
lastTouchTime
=
timestamp
;
return
}
//这个先不加
// if (s.isLocked) {
// if (absDistX > absDistY + s.lockDis) {
// deltaY = 0;
// } else if (absDistY >= absDistX + s.lockDis) {
// deltaX = 0;
// }
// }
let
oriX
=
s
.
_content
.
x
,
oriY
=
s
.
_content
.
y
;
deltaX
=
s
.
scrollWidth
?
deltaX
:
0
;
deltaY
=
s
.
scrollHeight
?
deltaY
:
0
;
//计算速度
let
deltaT
=
timestamp
-
s
.
lastTouchTime
,
sx
=
0
,
sy
=
0
;
let
newX
=
oriX
+
deltaX
;
let
newY
=
oriY
+
deltaY
;
if
(
newX
>
0
||
newX
<
s
.
maxScrollX
)
{
newX
=
s
.
isBounce
?
oriX
+
deltaX
/
3
:
newX
>
0
?
0
:
s
.
maxScrollX
;
}
else
{
sx
=
deltaX
/
deltaT
}
if
(
newY
>
0
||
newY
<
s
.
maxScrollY
)
{
newY
=
s
.
isBounce
?
oriY
+
deltaY
/
3
:
newY
>
0
?
0
:
s
.
maxScrollY
;
}
else
{
sy
=
deltaY
/
deltaT
}
//记录速度
s
.
pushVelocitys
(
sx
,
sy
)
s
.
lastTouchTime
=
timestamp
;
s
.
_translate
(
newX
,
newY
);
//事件处理
if
(
s
.
mouseStatus
==
1
)
{
s
.
dispatchEvent
(
Event
.
SCROLL_START
,
{
x
:
-
newX
,
y
:
-
newY
,
deltaX
:
oriX
-
newX
,
deltaY
:
oriY
-
newY
});
}
s
.
mouseStatus
=
2
;
}
else
{
//超出边界了
if
(
s
.
checkPosition
(
s
.
bounceTime
))
{
s
.
mouseStatus
=
0
;
return
;
}
//状态不是move过来的,重置状态后return
if
(
s
.
mouseStatus
!=
2
)
{
s
.
mouseStatus
=
0
;
return
;
}
s
.
mouseStatus
=
0
;
let
newX
:
number
=
s
.
_content
.
x
,
newY
:
number
=
s
.
_content
.
y
,
time
:
number
=
0
;
//有缓冲
if
(
s
.
hasMomentum
&&
s
.
velocitys
.
length
)
{
//计算速度
let
sum
=
{
x
:
0
,
y
:
0
},
totalW
=
0
;
for
(
let
i
=
0
;
i
<
s
.
velocitys
.
length
;
i
++
)
{
let
v
=
s
.
velocitys
[
i
];
let
w
=
ScrollView
.
weight
[
i
];
sum
.
x
+=
v
[
0
]
*
w
;
sum
.
y
+=
v
[
1
]
*
w
;
totalW
+=
w
;
}
s
.
velocitys
.
length
=
0
;
let
sx
=
sum
.
x
/
totalW
,
sy
=
sum
.
y
/
totalW
;
let
momentumX
=
(
s
.
scrollWidth
&&
Math
.
abs
(
sx
)
>
0.02
)
?
toMomentum
(
newX
,
sx
,
s
.
maxScrollX
,
s
.
damping
)
:
{
destination
:
newX
,
duration
:
0
};
let
momentumY
=
(
s
.
scrollHeight
&&
Math
.
abs
(
sy
)
>
0.02
)
?
toMomentum
(
newY
,
sy
,
s
.
maxScrollY
,
s
.
damping
)
:
{
destination
:
newY
,
duration
:
0
};
newX
=
momentumX
.
destination
;
newY
=
momentumY
.
destination
;
time
=
Math
.
max
(
momentumX
.
duration
,
momentumY
.
duration
);
}
if
(
newX
!=
s
.
_content
.
x
||
newY
!=
s
.
_content
.
y
)
{
s
.
_scrollTo
(
newX
,
newY
,
time
);
return
;
}
s
.
dispatchEvent
(
Event
.
SCROLL_STOP
,
{
x
:
-
s
.
_content
.
x
,
y
:
-
s
.
_content
.
y
,
deltaX
:
0
,
deltaY
:
0
});
}
}
private
onEnterFrame
(
e
:
Event
)
{
let
s
=
this
;
let
now
=
Date
.
now
();
//用户点击交互时需要加
if
(
s
.
mouseStatus
&&
s
.
lastTouchTime
&&
now
-
s
.
lastTouchTime
>
100
&&
now
-
s
.
lastTouchTime
<
300
)
{
s
.
pushVelocitys
(
0
,
0
);
}
if
(
!
s
.
isRunning
)
return
;
//时间到了
if
(
now
>=
s
.
destTime
)
{
s
.
isRunning
=
false
;
const
{
x
,
y
}
=
s
.
_content
;
//移动到最终位置
s
.
_translate
(
s
.
destX
,
s
.
destY
);
//检查是否合法,
if
(
!
s
.
checkPosition
(
s
.
bounceTime
))
{
let
data
=
{
x
:
-
s
.
destX
,
y
:
-
s
.
destY
,
deltaX
:
x
-
s
.
destX
,
deltaY
:
y
-
s
.
destX
,
};
s
.
dispatchEvent
(
Event
.
SCROLL_STOP
,
data
);
if
(
s
.
destX
==
0
&&
s
.
destY
==
0
)
{
s
.
dispatchEvent
(
Event
.
SCROLL_TO_HEAD
,
data
);
}
if
(
s
.
destX
==
s
.
maxScrollX
&&
s
.
destY
==
s
.
maxScrollY
)
{
s
.
dispatchEvent
(
Event
.
SCROLL_TO_END
,
data
);
}
}
}
else
{
now
=
(
now
-
s
.
startTime
)
/
s
.
duration
;
var
easing
=
s
.
easeFn
(
now
);
s
.
_translate
(
(
s
.
destX
-
s
.
startX
)
*
easing
+
s
.
startX
,
(
s
.
destY
-
s
.
startY
)
*
easing
+
s
.
startY
);
}
}
private
pushVelocitys
(
vx
:
number
,
vy
:
number
)
{
this
.
velocitys
.
push
([
vx
,
vy
]);
if
(
this
.
velocitys
.
length
>
ScrollView
.
weight
.
length
)
this
.
velocitys
.
shift
();
}
/**
* 滚到指定的坐标位置
* @param {number} x 往左横向滚动距离,0到最大横向滚动距离
* @param {number} y 往上纵向滚动距离,0到最大纵向滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
public
scrollTo
(
x
:
number
,
y
:
number
,
time
:
number
=
0
,
easeFn
?:
(
t
:
number
)
=>
number
):
void
{
//xy都是相对左上角正向的,所以真正_content的坐标应该取负
//判断范围
const
[
nx
,
ny
]
=
this
.
_modifyXY
(
-
x
,
-
y
);
//真实滚动
this
.
_scrollTo
(
nx
,
ny
,
time
,
easeFn
);
}
/**
* 从当前位置继续滚动
* @param {number} x 往左滚动距离
* @param {number} y 往上滚动距离
* @param {number} time 滚动需要的时间 默认为0 即没有缓动直接到达指定位置,毫秒计
* @param {Function} easeFn 缓动函数,不传默认用Ease.circOut,从快到慢
* @public
*/
public
scrollBy
(
x
:
number
,
y
:
number
,
time
:
number
=
0
,
easeFn
?:
(
t
:
number
)
=>
number
)
{
let
s
=
this
;
//最终的位置
x
=
s
.
_content
.
x
-
x
;
y
=
s
.
_content
.
y
-
y
;
//判断范围
const
[
nx
,
ny
]
=
this
.
_modifyXY
(
x
,
y
);
s
.
_scrollTo
(
nx
,
ny
,
time
,
easeFn
);
}
/**
* 真实的滚动,xy一般都是负数
* @param x
* @param y
* @param time
* @param easeFn 缓动函数,不传默认用Ease.circOut
* @returns
*/
private
_scrollTo
(
x
:
number
,
y
:
number
,
time
:
number
=
0
,
easeFn
?:
(
t
:
number
)
=>
number
)
{
let
s
=
this
;
//判断下
if
(
isNaN
(
x
)
||
isNaN
(
y
))
return
;
if
(
!
time
)
{
s
.
isRunning
=
false
;
s
.
_translate
(
x
,
y
);
}
else
{
s
.
startX
=
s
.
_content
.
x
;
s
.
startY
=
s
.
_content
.
y
;
s
.
startTime
=
Date
.
now
();
s
.
destTime
=
s
.
startTime
+
time
;
s
.
destX
=
x
;
s
.
destY
=
y
;
s
.
duration
=
time
;
s
.
easeFn
=
easeFn
||
Ease
.
quadOut
;
s
.
isRunning
=
true
;
}
}
/**
* _content位置的改变都用这个方法
* @param x
* @param y
*/
private
_translate
(
x
:
number
,
y
:
number
)
{
let
s
=
this
;
let
{
x
:
oriX
,
y
:
oriY
}
=
s
.
_content
;
s
.
_content
.
x
=
x
;
s
.
_content
.
y
=
y
;
//事件,位置变了
if
(
oriX
!=
x
||
oriY
!=
y
)
{
s
.
dispatchEvent
(
Event
.
SCROLLING
,
{
x
:
-
x
,
y
:
-
y
,
deltaX
:
oriX
-
x
,
deltaY
:
oriY
-
y
});
}
}
/**
* 检查当前的位置是否合理,不合理会返回true,且滚动到对应位置
* @param time
* @returns
*/
protected
checkPosition
(
time
:
number
=
0
):
boolean
{
//原先坐标
const
{
x
,
y
}
=
this
.
_content
;
//矫正坐标
const
[
nx
,
ny
]
=
this
.
_modifyXY
(
x
,
y
);
// 完全一致,就不处理
if
(
x
==
nx
&&
y
==
ny
)
return
false
;
//滚动
this
.
_scrollTo
(
nx
,
ny
,
time
);
return
true
}
/**
* 矫正坐标
* @param x
* @param y
* @returns
*/
private
_modifyXY
(
x
:
number
,
y
:
number
)
{
let
{
scrollWidth
,
maxScrollX
,
scrollHeight
,
maxScrollY
}
=
this
;
if
(
!
scrollWidth
||
x
>
0
)
{
x
=
0
;
}
else
if
(
x
<
maxScrollX
)
{
x
=
maxScrollX
;
}
if
(
!
scrollHeight
||
y
>
0
)
{
y
=
0
;
}
else
if
(
y
<
maxScrollY
)
{
y
=
maxScrollY
;
}
return
[
x
,
y
];
}
public
destroy
():
void
{
let
s
=
this
;
//由于操作子级方法被重写了,销毁时移除不了,所以手动操作,用removeChildAt,其他都被重写了
super
.
removeChildAt
(
0
)
.
destroy
();
super
.
removeChildAt
(
0
)
.
destroy
();
s
.
maskObj
=
null
;
s
.
_content
=
null
;
s
.
easeFn
=
null
;
super
.
destroy
();
}
};
//将添加与移除的操作统统重写到_content中,待测试,需要维护,TODO。对于list直接不允许使用下面这些方法
Container
.
_childrenOperationMethods
.
forEach
((
v
)
=>
{
Object
.
defineProperty
(
ScrollView
.
prototype
,
v
,
{
value
:
function
(...
arg
)
{
console
.
warn
(
"Maybe you want to operate children in its view rather then in it when it is a ScrollView!"
);
return
Container
.
prototype
[
v
].
call
(
this
,
...
arg
)
//先不重写了,不方便扩展,还容易出问题,只加提示吧
// return this._content[v](...arg);
},
writable
:
true
,
enumerable
:
true
,
})
})
/**
*
* @param current 当前位置
* @param speed 速度。move最后位置到松开的位置/滑动到松开的时间
* @param lowerMargin
* @param deceleration
* @returns
*/
function
toMomentum
(
current
:
number
,
speed
:
number
,
lowerMargin
:
number
,
deceleration
:
number
=
0.0006
)
{
//衰减到0的时间
let
duration
=
Math
.
abs
(
speed
)
/
deceleration
;
let
destination
=
current
+
duration
*
(
speed
/
2
)
// console.log(current, speed)
if
(
destination
<
lowerMargin
)
{
destination
=
lowerMargin
;
duration
=
Math
.
abs
((
destination
-
current
)
/
(
speed
/
2
));
}
else
if
(
destination
>
0
)
{
destination
=
0
;
duration
=
Math
.
abs
(
current
/
(
speed
/
2
));
}
return
{
destination
,
duration
};
};
function
toMomentum1
(
current
:
number
,
speed
:
number
,
lowerMargin
:
number
,
deceleration
:
number
=
0.0006
)
{
let
destination
=
current
+
(
speed
*
speed
)
/
(
2
*
deceleration
)
*
(
speed
<
0
?
-
1
:
1
);
let
duration
=
Math
.
abs
(
speed
)
/
deceleration
;
// console.log(current, speed)
if
(
destination
<
lowerMargin
)
{
destination
=
lowerMargin
;
duration
=
Math
.
abs
((
destination
-
current
)
/
speed
);
}
else
if
(
destination
>
0
)
{
destination
=
0
;
duration
=
Math
.
abs
(
current
/
speed
);
}
return
{
destination
,
duration
};
};
function
toMomentum2
(
curPos
:
number
,
pixelsPerMS
:
number
,
maxPos
:
number
,
damping
:
number
):
{
destination
:
number
;
duration
:
number
}
{
let
absPixelsPerMS
:
number
=
Math
.
abs
(
pixelsPerMS
);
let
extraFricition
:
number
=
0.95
;
let
duration
:
number
=
0
;
let
friction
:
number
=
0.998
;
let
minVelocity
:
number
=
0.02
;
let
posTo
:
number
=
curPos
+
pixelsPerMS
*
500
;
if
(
posTo
<
maxPos
)
{
posTo
=
maxPos
;
duration
=
Math
.
abs
((
posTo
-
curPos
)
/
pixelsPerMS
);
}
else
if
(
posTo
>
0
)
{
posTo
=
0
;
duration
=
Math
.
abs
(
curPos
/
pixelsPerMS
);
}
else
{
duration
=
-
Math
.
log
(
minVelocity
/
absPixelsPerMS
)
*
500
;
}
let
result
=
{
destination
:
posTo
,
duration
};
return
result
;
}
export
interface
IScrollData
{
/**
* 横向滚动位置,通常为正
*/
x
:
number
,
/**
* 纵向滚动位置,通常为正
*/
y
:
number
,
/**
* 滚动横向距离,为正表示向左滚动
*/
deltaX
?:
number
,
/**
* 滚动纵向距离,为正表示向上滚动
*/
deltaY
?:
number
}
export
interface
ScrollEvent
extends
Event
{
data
:
IScrollData
}
\ No newline at end of file
src/index.ts
View file @
b74d8660
...
...
@@ -35,5 +35,5 @@ export * from "./3d";
//spine
export
*
from
"./spine"
;
// export * from "./Stats";
\ No newline at end of file
//fps面板,后续可以加入每次drawCall,总绘制对象等等
export
*
from
"./2d/FpsPanel"
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment