Asroads'Blog 君子不器
Cocos Creator ScrollBar(滑动按钮)增强组件
发布于: 2022-01-11 更新于: 2024-03-02 分类于: game 阅读次数: 

众所周知,Cocos Creator自带的cc.ScrollView组件中的ScrollBar组件是无法拖动实现进度的,于是乎论坛就有人自己研发了这个功能,进来需求里有这个功能,于是就用到了,这里对前辈们的功能加以修改和整合,实现自己的需求,下面细说一下。

首先我们看看实现后的效果

横向ScrollView列表:

001

纵向ScrollView列表:

002

项目结构

管理器节点结构

image-20220111125029474

image-20220111125209885

原理

  1. 实现借鉴了论坛两位大佬的思路结合,依赖 cc.Slider组件实现。
  2. 然后设置对应的进度
  3. 如果是列表滑动,添加滑动监听函数,实现同步进度。

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Created by jsroads on 2022/1/10 5:51 PM
* Note:滑动按钮增强
*/
const {ccclass, property, requireComponent, menu} = cc._decorator;
@ccclass
@requireComponent(cc.Slider)
@menu("组件库/ScrollBarEnhance")
export class ScrollBarEnhance extends cc.Component {
@property({
tooltip: "对应的(ScrollView)滑动列表",
type: cc.ScrollView
})
private scrollView: cc.ScrollView = null!;
//滑动事件改变事件
@property({
type: [cc.Component.EventHandler],
tooltip: CC_DEV && "滑动事件改变事件",
})
private renderEvent: cc.Component.EventHandler[] = [];

private vSlider: cc.Slider = null!;

private static creatEventHandler(target: cc.Node, component: string, handler: string) {
const e = new cc.Component.EventHandler();
e.target = target;
e.component = component;
e.handler = handler;
return e;
}

/**
* 外部修改进度
* @param p
*/
public refresh(p: number) {
let progress, slider = this.vSlider || this.node.getComponent(cc.Slider);
progress = Math.min(p, 1);
progress = Math.max(p, 0);
slider.progress = progress;
this.onSliderEvent(slider, "");
console.log("slider.progress----:" + JSON.stringify(slider.progress));
}

protected start() {
this.addScrollChildIndex();
}

/** 增加scroll子节点区间功能 */
private addScrollChildIndex() {
/** 禁用鼠标滚轮,滚轮在移动区间时ScrollEvent返回很怪异,没有SCROLL_ENDED事件回调 */
// this.node.off(cc.Node.EventType.MOUSE_WHEEL);
const scroll = this.scrollView;
this.vSlider = this.node.getComponent(cc.Slider);
let className = cc.js.getClassName(this);
/** Slider 事件监听 */
this.vSlider.slideEvents.push(ScrollBarEnhance.creatEventHandler(this.node, className, 'onSliderEvent'));
/** ScrollView 事件监听 */
scroll.scrollEvents.push(ScrollBarEnhance.creatEventHandler(this.node, className, 'onScrollEvent'));
/** 初始化进度 */
this.scrollMoveEvent();
}

/**
* 滚动列表事件回调
* @param scroll
* @param eventType
* @param customEventData
* @private
*/
private onScrollEvent(scroll: cc.ScrollView, eventType: cc.ScrollView.EventType, customEventData: string) {
switch (eventType) {
case cc.ScrollView.EventType.SCROLL_BEGAN:
break;
case cc.ScrollView.EventType.SCROLL_ENDED:
break;
case cc.ScrollView.EventType.SCROLLING:
this.scrollMoveEvent();
break;
}
}

//滑动列表--滚动条改变
private scrollMoveEvent() {
let vertical = this.scrollView.vertical, maxScrollOffset, getScrollOffset;
if (vertical) {
maxScrollOffset = this.scrollView.getMaxScrollOffset().y;
getScrollOffset = this.scrollView.getScrollOffset().y;
} else {
maxScrollOffset = this.scrollView.getMaxScrollOffset().x;
getScrollOffset = this.scrollView.getScrollOffset().x * (-1);
}
// console.log("maxScrollOffset", maxScrollOffset);
// console.log("getScrollOffset", getScrollOffset);
if (getScrollOffset / maxScrollOffset > 0 && getScrollOffset / maxScrollOffset < 1) {
this.vSlider.progress = getScrollOffset / maxScrollOffset;
} else if (getScrollOffset / maxScrollOffset <= 0) {
this.vSlider.progress = 0;
} else {
this.vSlider.progress = 1;
}
// console.log(this.vSlider.progress);
console.log("scrollMoveEvent", this.vSlider.progress);
if (this.renderEvent && this.renderEvent.length) {
cc.Component.EventHandler.emitEvents(this.renderEvent, this.vSlider.progress);
}
}

/**
* 滑动按钮 回调
* @param slider
* @param customEventData
* @private
*/
private onSliderEvent(slider, customEventData: string) {
// console.log("onSliderEvent", slider.progress);
let vertical = this.scrollView.vertical, maxScrollOffsetX = 0, maxScrollOffsetY = 0;
if (vertical) {
maxScrollOffsetX = this.scrollView.getScrollOffset().x;
maxScrollOffsetY = this.scrollView.getMaxScrollOffset().y * slider.progress;
} else {
maxScrollOffsetX = this.scrollView.getMaxScrollOffset().x * slider.progress;
maxScrollOffsetY = this.scrollView.getScrollOffset().y;
}
this.scrollView.scrollToOffset(cc.v2(maxScrollOffsetX, maxScrollOffsetY), 0.05);
}
}

注意: getScrollOffset = this.scrollView.getScrollOffset().x * (-1);

是否乘以-1 根据自己的scrollViewcontentanchorX 等因素决定,这里是从左到右 anchorX0 所以这样写。

源码地址 点击进入

参考

--- 本文结束 The End ---