mirror of
https://github.com/Leo501/CocosCreatorTutorial.git
synced 2026-09-11 03:54:43 +08:00
221 lines
7.0 KiB
TypeScript
221 lines
7.0 KiB
TypeScript
|
|
const {ccclass, property} = cc._decorator;
|
|
|
|
export enum EventType {
|
|
SCROLL_START,
|
|
SCROLL_ING,
|
|
SCROLL_END
|
|
}
|
|
|
|
@ccclass
|
|
export default class UIScrollSelect extends cc.Component {
|
|
|
|
public static EventType = EventType;
|
|
@property(cc.Node)
|
|
content :cc.Node = null;
|
|
@property({
|
|
type:cc.Integer,
|
|
tooltip:'单个控件之间的距离'
|
|
})
|
|
deltaX : number = 100 //x间隔距离
|
|
@property({
|
|
type:cc.Integer,
|
|
tooltip:'中心点的缩放比例'
|
|
})
|
|
centerScale : number = 1.0
|
|
@property({
|
|
type:cc.Integer,
|
|
tooltip:'边缘点的缩放比例'
|
|
})
|
|
minScale : number = 1.0
|
|
@property({
|
|
type:cc.Integer,
|
|
tooltip:'滚动时的速度'
|
|
})
|
|
scrollSpeed: number = 300;
|
|
@property({
|
|
type: cc.Component.EventHandler,
|
|
tooltip: "选择后的回调"
|
|
})
|
|
selectEvents:Array<cc.Component.EventHandler> = [];
|
|
|
|
private childs:Array<cc.Node> = [];
|
|
private isTouching : boolean = false;
|
|
private hasTouchMove : boolean = false;
|
|
private isTestX : boolean = false;
|
|
private _touchId: any = null;
|
|
private currentIndex:number = 0;
|
|
private _toMoveX:number = 1; //移动方向
|
|
private dx:number = 0;
|
|
private moveAim : number = 0;
|
|
|
|
onLoad(){
|
|
this.childs = [];
|
|
for(var i=0; i<this.content.children.length; i++){
|
|
this.childs[i] = this.content.children[i];
|
|
this.childs[i].x = this.deltaX*(i-1);
|
|
}
|
|
this.isTouching = false
|
|
this.hasTouchMove = false
|
|
this.isTestX = false;
|
|
this._touchId = null;
|
|
// this.currentIndex = 0;
|
|
this.scrollTo(0,false);
|
|
}
|
|
/** 滚动到指定节点
|
|
* @param anim 是否带移动动画
|
|
*/
|
|
scrollTo(idx:number,anim:boolean=true){
|
|
if(idx < 0 && idx >= this.childs.length){
|
|
return console.error(this.node.name+'->移动超出边界面')
|
|
}
|
|
this.currentIndex = idx;
|
|
this.moveAim = idx;
|
|
if(!anim){
|
|
for(var i=0; i<this.childs.length; i++){
|
|
this._checkChildX(this.childs[i],(i-idx) *this.deltaX)
|
|
}
|
|
} else {
|
|
this.isTestX = true
|
|
cc.Component.EventHandler.emitEvents(this.selectEvents, {target :this,
|
|
type :EventType.SCROLL_START,
|
|
index : this.currentIndex});
|
|
}
|
|
}
|
|
/** 向左滚一个点 */
|
|
scrollToLeft(){
|
|
this._toMoveX = 1
|
|
this.scrollTo((this.currentIndex-1+this.childs.length)%this.childs.length)
|
|
}
|
|
|
|
/** 向左滚一个点 */
|
|
scrollToRight(){
|
|
this._toMoveX = -1
|
|
this.scrollTo((this.currentIndex+1+this.childs.length)%this.childs.length)
|
|
}
|
|
|
|
_checkChildX(child,x){
|
|
if(x > this.childs.length/2 * this.deltaX){
|
|
x-=this.childs.length * this.deltaX
|
|
} else if(x < -this.childs.length/2 * this.deltaX){
|
|
x+=this.childs.length * this.deltaX
|
|
}
|
|
child.x = x;
|
|
let dx = Math.min(Math.abs(x),this.deltaX)
|
|
child.scale = (1-dx/this.deltaX)*(this.centerScale-this.minScale) + this.minScale
|
|
}
|
|
|
|
start(){
|
|
this.content.on(cc.Node.EventType.TOUCH_START,this._onTouch,this);
|
|
this.content.on(cc.Node.EventType.TOUCH_MOVE,this._onTouch,this);
|
|
this.content.on(cc.Node.EventType.TOUCH_END,this._onTouchEnd,this);
|
|
this.content.on(cc.Node.EventType.TOUCH_CANCEL,this._onTouchEnd,this);
|
|
}
|
|
_onTouch(event ){
|
|
if(this._touchId != null && event.touch != this._touchId){
|
|
return;
|
|
}
|
|
if(event.type == cc.Node.EventType.TOUCH_START){
|
|
this.isTouching = true;
|
|
this.hasTouchMove = false
|
|
this.isTestX = false;
|
|
this._touchId = event.touch;
|
|
this.dx = event.getStartLocation().x;
|
|
let evt = {
|
|
target :this,
|
|
type :EventType.SCROLL_START,
|
|
index : this.currentIndex
|
|
}
|
|
cc.Component.EventHandler.emitEvents(this.selectEvents, evt);
|
|
return;
|
|
}
|
|
this.hasTouchMove = true;
|
|
var dx = event.getLocation().x - this.dx
|
|
this._move(dx);
|
|
this.dx = event.getLocation().x
|
|
var evt = {
|
|
target :this,
|
|
type :EventType.SCROLL_ING,
|
|
dx:this.dx
|
|
}
|
|
cc.Component.EventHandler.emitEvents(this.selectEvents, evt);
|
|
}
|
|
_onTouchEnd(event){
|
|
if(this._touchId != null && event.touch != this._touchId){
|
|
return;
|
|
}
|
|
this.isTouching = false;
|
|
if(event.type == cc.Node.EventType.TOUCH_END || event.type == cc.Node.EventType.TOUCH_CANCEL){
|
|
this._touchId = null;
|
|
}
|
|
let lo = this.node.convertToNodeSpaceAR(event.getLocation())
|
|
if(!this.hasTouchMove){
|
|
|
|
let mx = Math.ceil((lo.x - this.deltaX / 2) / this.deltaX)
|
|
if(mx === 0){
|
|
var event1 = {
|
|
target :this,
|
|
type :EventType.SCROLL_END,
|
|
index : this.currentIndex
|
|
}
|
|
cc.Component.EventHandler.emitEvents(this.selectEvents, event1);
|
|
} else {
|
|
this.moveAim = (this.currentIndex+mx+this.childs.length)%this.childs.length
|
|
this._toMoveX = mx > 0 ? -1 : 1
|
|
this.isTestX = true;
|
|
}
|
|
return;
|
|
}
|
|
let max = this.deltaX;
|
|
let minidx = 0
|
|
for(let i=0; i<this.childs.length; i++){
|
|
if(Math.abs(this.childs[i].x)<=max){
|
|
max = Math.abs(this.childs[i].x)
|
|
minidx = i;
|
|
}
|
|
}
|
|
this.moveAim = minidx
|
|
this._toMoveX = this.childs[minidx].x >= 0 ? -1 : 1
|
|
this.isTestX = true;
|
|
}
|
|
_move(dt){
|
|
for(var i=0; i<this.childs.length; i++){
|
|
this._checkChildX(this.childs[i],this.childs[i].x+dt)
|
|
}
|
|
}
|
|
|
|
update(dt){
|
|
if(this.isTouching || !this.isTestX){
|
|
return;
|
|
}
|
|
var stepx = this._toMoveX * dt * this.scrollSpeed
|
|
let lx = this.childs[this.moveAim].x
|
|
for(var i=0; i<this.childs.length; i++){
|
|
this._checkChildX(this.childs[i],this.childs[i].x+stepx)
|
|
}
|
|
|
|
var x = this.childs[0].x;
|
|
var idx = Math.round(x/this.deltaX);
|
|
var tox = this.deltaX * idx;
|
|
let cx = this.childs[this.moveAim].x
|
|
if(lx * cx < 0 && Math.abs(cx) < this.deltaX){
|
|
this.isTestX = false;
|
|
for(let i=0; i<this.childs.length; i++){
|
|
if(Math.abs(this.childs[i].x)<=Math.abs(stepx)){
|
|
this.currentIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
for(var i=0; i<this.childs.length; i++){
|
|
this._checkChildX(this.childs[i],this.childs[i].x+tox-x)
|
|
}
|
|
var event = {
|
|
target :this,
|
|
type :EventType.SCROLL_END,
|
|
index : this.currentIndex
|
|
}
|
|
cc.Component.EventHandler.emitEvents(this.selectEvents, event);
|
|
}
|
|
}
|
|
}
|