引擎: cocos2d-js 3.0
这只是一个简单的,循环的版本,后期再给大家呈现实时滑动的版本。
为了方便对齐坐标,所以这个控件结合了cocos studio1.6的编辑器。
编辑器的编辑效果如下:
ClipPanel是一个大小为选择区域的裁剪Panel(设置裁剪)。
Image_BackGround是左右黑色渐变的背景,位于图片上层。
Image_0到Image_3是4个基本的移动对象。由于要实现切换的效果,最少需要用到的精灵个数为4个。所以为了最优的性能,我们用4个精灵来模拟。
Label_Tile是上方的标题
Btn_Right和Btn_Left是左右的按钮,用来切换
Btn_Panel是大小同精灵一样的Panel,用来点击选择进入哪一个场景。(切换到相应的地方后,总得要确定选择吧)
由于最初我们设计是循环的控件,因此默认正中间的是第一个对象,左边是列表的最后一个对象,向左边数第二个是倒数第二个对象,右边是第二个对象。如下图:
这里的Image_2在游戏中是看不见的,被裁剪了。
提问:也有朋友觉得这样做不觉得麻烦吗,我列表中有多少个就创建多少个,这样管理不更直接,更简单吗。
我答:如果说需要切换的列表有100个,甚至100个以上的对象怎么破?
接着,我们知道了编辑器的操作后,再来看实际的带代码:
var SwitchTable = cc.Layer.extend({
_curIndex:null,_list:null,_spriteList:null,_originPosition:null,_root:null,_objList:null,_isCanMove:true,// 设定操作间隔
ctor: function(json){
this._super();
this._curIndex = 0;
this._list = [];
this._originPosition = [];
this._root = ccs.uiReader.widgetFromJsonFile(json);
this.addChild(this._root);
for(var i = 0; i < 4; i++){
var sprite = ccui.helper.seekWidgetByName(this._root,"Image_"+i);
this._originPosition.push(sprite.getPosition());
this._list.push(sprite);
}
// ini button
var rightBtn = ccui.helper.seekWidgetByName(this._root,"Btn_Right");
rightBtn.addTouchEventListener(this._touchEvent,this);
var leftBtn = ccui.helper.seekWidgetByName(this._root,"Btn_Left");
leftBtn.addTouchEventListener(this._touchEvent,this);
var panelBtn = ccui.helper.seekWidgetByName(this._root,"Btn_Panel");
panelBtn.addTouchEventListener(this._clicked,this);
this._labTitle = ccui.helper.seekWidgetByName(this._root,"Label_Title");
},initWithObjList: function (objList) {
this._objList = objList;
// 清空目前的Sprite,切换其他ObjList
this._clear();
// 根据列表放置sprite
var length = objList.length;
for( var i = 0; i < 2; i++){ // 头两个
if(objList[i]){
this._list[i].loadTexture(objList[i].imgName);
}
}
var listLength = this._list.length;
for( var i = length - 1; i >= length - 2; i--){ // 尾两个
if(objList[i]){
this._list[listLength-1].loadTexture(objList[i].imgName);
listLength = listLength - 1;
}
}
// 个数处理,如果为1,2,3时
if(length == 1){
this._list[1].setVisible(false);
this._list[2].setVisible(false);
this._list[3].setVisible(false);
}else if( length == 2){
this._list[2].setVisible(false);
this._list[3].setVisible(false);
}else if( length == 3){
this._list[2].setVisible(false);
}
this._curIndex = 0;
this._labTitle.setString(this._objList[this._curIndex].titleName);
},_scroll: function(direction){
if(!this._isCanMove) return;
var length = this._objList.length;
if(length <= 1 ) return; // 不足长度是无法移动
if(direction == 0){
if(length == 2 && this._curIndex == 1) return;
if(length == 3 && this._curIndex == 1) return;
this._curIndex = (this._curIndex + 1) >= length ? 0 : this._curIndex + 1;
var index = this._curIndex + 1 >= this._objList.length ? 0 : this._curIndex + 1;
if(this._objList[index]){
this._list[2].loadTexture(this._objList[index].imgName);
}
this._moveToLeft();
}else{
if(length == 2 && this._curIndex == 0) return;
if(length == 3 && this._curIndex == 2) return;
this._curIndex = (this._curIndex - 1) < 0 ? length - 1 : this._curIndex - 1;
this._moveToRight();
}
this._isCanMove = false;
this.runAction(cc.sequence(cc.delayTime(0.3),cc.callFunc(function(){
this._isCanMove = true;
if(direction == 0){
}else{
var index = this._curIndex - 2 < 0 ? this._objList.length + (this._curIndex - 2) : this._curIndex - 2;
if(this._objList[index]){
this._list[2].loadTexture(this._objList[index].imgName);
}
}
},this)));
this._labTitle.setString(this._objList[this._curIndex].titleName);
},_moveToRight: function(){
var time = 0.3;
this._list[0].runAction(cc.spawn(cc.moveTo(time,this._originPosition[1]),cc.scaleTo(time,0.8)));
this._list[1].runAction(cc.moveBy(time,cc.p(this._list[2].getContentSize().width + 5,0)));
this._list[2].setPosition(this._originPosition[2]);
this._list[2].runAction(cc.moveTo(time,this._originPosition[3]));
this._list[3].runAction(cc.spawn(cc.moveTo(time,this._originPosition[0]),1)));
var tempSp = this._list[0];
this._list[0] = this._list[3];
this._list[3] = this._list[2];
this._list[2] = this._list[1];
this._list[1] = tempSp;
},_moveToLeft: function(){
var time = 0.3;
this._list[0].runAction(cc.spawn(cc.moveTo(time,this._originPosition[3]),0.8)));
this._list[3].runAction(cc.moveBy(time,cc.p(-this._list[2].getContentSize().width + 5,0)));
this._list[2].setPosition(cc.p(this._originPosition[1].x + this._list[2].getContentSize().width,this._originPosition[1].y));
this._list[2].runAction(cc.moveTo(time,this._originPosition[1]));
this._list[1].runAction(cc.spawn(cc.moveTo(time,1)));
var tempSp = this._list[0];
this._list[0] = this._list[1];
this._list[1] = this._list[2];
this._list[2] = this._list[3];
this._list[3] = tempSp;
},_clear: function(){
//this._list[2].setVisible(false);
this._curIndex = 0;
},_touchEvent: function (sender,type) {
switch (type) {
case ccui.Widget.TOUCH_ENDED:
var tag = sender.getTag();
this._scroll(tag);
break;
default:
break;
}
},_clicked: function (sender,type) {
/*if (type == ccui.Widget.TOUCH_ENDED) { window.open(....); }*/
}
});
(1)左右按钮通过tag的设置来区分
(2)由于1~3个个数的时候数量太少,无法支持循环,所有上方判断。
(3)SwitchTable名字是我随便取的^ ^
下周会把一个通用的、跟随手指滑动的控件给大家贴出来。