1.需求
目前很多游戏的主场景都要求能实现滚动功能和多点触摸时缩放主场景的功能
2.设计思路
ccui.scrollView能满足除了多点触摸以外的其他功能需求,所以考虑在scrollview的基础上增加多点触摸的缩放功能
难点:因为单点触摸的优先级高于多点触摸 所以在scrollView中,无法获取到多个触摸点信息
解决方案:
设置一个优先级高于scrollView的事件监听,判断当前是单点触摸,还是多点触摸。如果是多点触摸,则进行缩放,如果是单点,则进行移动
代码:
var CityLayer = cc.Layer.extend({
scroll : null, //滚动层
back : null, //滚动层上的内容(背景图)
touchDistance : 0, //触摸点之间的距离
initScale : 0.7, //初始缩放
nowScale : 0.7, //当前缩放比例
oldInnerSize : null, //当前滚动层滚动尺寸
ctor: function(){
//加载UI
var city = ccs.uiReader.widgetFromJsonFile(res.ui.city);
this.addChild(city,1);
//找到scrollView
this.scroll = ccui.helper.seekWidgetByName(city, "scrollView");//层容器
this.oldInnerSize = this.scroll.getInnerContainerSize();
this.back = this.scroll.getChildByName("back");
//新增监听,并使监听的优先级高于scrollView 用于判断当前是单点还是多点
var touch = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan : this.checkTouches.bind(this)
});
cc.eventManager.addListener(touch, -1);
//多点触摸监听
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ALL_AT_ONCE,
onTouchesBegan: this._onTouchBegan.bind(this),
onTouchesMoved: this._onTouchMoved.bind(this),
onTouchesEnded: this._onTouchEnded.bind(this),
onTouchesCancelled: this._onTouchCancelled.bind(this)
}, this);
},
checkTouches: function(touches, event){
if(touches.getID() > 0){
this.scroll.setTouchEnabled(false);//多点触摸下,关闭滚动层的响应
}
return false;
},
_onTouchBegan: function(touches, event){
this.touchDistance = 0;
return true;
},
_onTouchMoved: function(touches, event){
if(touches.length >= 2){
var point1 = touches[0].getLocation(),point2 = touches[1].getLocation();
var _dis = cc.pDistance(point1,point2);
if(!this.touchDistance){
this.touchDistance = _dis;
}else {
var _scale = _dis / this.touchDistance * this.nowScale;//根据两个点的移动距离,获取缩放尺寸
this.touchDistance = _dis;
this.changeScrollContainerSize(_scale);
}
}
return true;
},
_onTouchEnded: function(touches, event){
this.scroll.setTouchEnabled(true);//缩放结束,恢复滚动层的touch事件
return true;
},
_onTouchCancelled: function(touches, event){
this.scroll.setTouchEnabled(true);//缩放结束,恢复滚动层的touch事件
return true;
},
changeScrollContainerSize: function(scale){
if(scale<0.5 || scale>1.0) return; //设置最大和最小缩放比例
var size = this.oldInnerSize;
this.back.setPosition(cc.p(size.width*scale/2,size.height*scale/2));//重新计算背景的位置
this.back.setScale(scale);
var scroll = this.scroll;
var inner = scroll.getInnerContainer();
var pos = inner.getPosition();
var newPos = cc.p(pos.x*scale/this.nowScale + (scale - this.nowScale)*pos.x,pos.y*scale/this.nowScale + (scale - this.nowScale)*pos.y);
var newInner = cc.size(size.width*scale,size.height*scale);
scroll.setInnerContainerSize(newInner);//重新设置滚动区域
//防止越界
var contentSize = scroll.getLayoutSize();
if (newPos.y <= 0)
newPos.y = Math.max(newPos.y, contentSize.height - newInner.height);
if (newPos.x <= 0)
newPos.x = Math.max(newPos.x, contentSize.width - newInner.width);
inner.setPosition(newPos);//重新设置内容层位置
this.nowScale = scale;
}
});
最后:
小弟不是大神,所以不希望去修改底层代码来实现,这样会带来很多额外的工作。所以在不修改引擎的基础上实现这个功能
各位有什么意见的话可以留言给我~