lua 自定义控件及动画控制(1)

来源:互联网 发布:windows连不上aws 编辑:程序博客网 时间:2024/06/01 23:56

1 lua控件基类

_class = {}local UIBase = class("UIBase",cc.Node)function UIBase:ctor()      -- 触摸监听事件      local listener = cc.EventListenerTouchOneByOne:create()      listener:registerScriptHandler(function ( touch,event )          return self:onPanelTouchBegan(touch,event)      end,cc.Handler.EVENT_TOUCH_BEGAN)      listener:registerScriptHandler(function ( touch,event )          return self:onPanelTouchMoved(touch,event)      end,cc.Handler.EVENT_TOUCH_MOVED)      listener:registerScriptHandler(function ( touch,event )          return self:onPanelTouchEnded(touch,event)      end,cc.Handler.EVENT_TOUCH_ENDED)      self.listener = listener        local eventDispatch = self:getEventDispatcher()      eventDispatch:addEventListenerWithSceneGraphPriority(listener,self) -- self:响应事件的对象     -- script handler    local function onNodeEvent(event)        if "enter" == event then            self:onEnter()        elseif "exit" == event then            self:onExit()        end    end    self:registerScriptHandler(onNodeEvent)endfunction UIBase.isTouchInside(node,touch)local touchLoc = touch:getLocation()touchLoc = node:getParent():convertToNodeSpace(touchLoc)if not cc.rectContainsPoint(node:getBoundingBox(), touchLoc) then    return falseendreturn trueendfunction UIBase:onEnter()endfunction UIBase:onExit()endfunction UIBase:onPanelTouchBegan( touch,event )      -- body  end  function UIBase:onPanelTouchMoved( touch,event )      -- body  end  function UIBase:onPanelTouchEnded( touch,event )      -- body  end _class.UIBase = UIBase

2 各种自定义滑动选择控件

2.1 类型1

效果


采用的曲线方程

lua源码 参考(http://blog.csdn.net/ccy0815ccy/article/details/43924895)

local UIRotateMenu1 = class("UIRotateMenu1",_class.UIBase)UIRotateMenu1.AniDuration = 0.5 -- 运动延时UIRotateMenu1.Factror = 2 -- 控制曲线形态UIRotateMenu1.ItemScrollFactor = 1/5 -- 滑过1/5宽度对应滑动过一个itemUIRotateMenu1.IndexScrollFactor = 1/3 -- 滑动超过1/3自动转至下个Indexfunction UIRotateMenu1:ctor()_class.UIBase.ctor(self)self._itemT = {}self._index = 0 -- 中心位置Item indexself._lastindex = 0    local cs = cc.Director:getInstance():getWinSize()    self:setContentSize(cs)    -- self:setContentSize(cc.size(cs.width*2/3,cs.height*2/3))endfunction UIRotateMenu1:title() return "Moke And TianTian"endfunction UIRotateMenu1:addMenuItem(item)local cs = self:getContentSize()item:setPosition(cc.p(cs.width/2,cs.height/2))self:addChild(item)table.insert(self._itemT,item)self:reset()self:updatePosWithAni()endfunction UIRotateMenu1:reset()self._index = 0self._lastindex = 0end-- 矫正中心Indexfunction UIRotateMenu1:rectify( deltaX )local isforward = nilif deltaX thenif deltaX > 0 then isforward = trueelseisforward = falseendendlocal idx = self:_getIndex()if idx < 0 thenidx = idx + #self._itemTelseif idx > (#self._itemT - 1) thenidx = idx - #self._itemTendif isforward == true thenidx = math.floor(idx + self.IndexScrollFactor)elseif isforward == false thenidx = math.floor(idx + 2*self.IndexScrollFactor)endself:_setIndex(idx)endfunction UIRotateMenu1:updatePos()for k,v in pairs(self._itemT) dov:setPosition(self:_getPos(k-1))v:setScale(self:_getScale(k-1))v:setRotation3D(cc.vec3(0,self:_getRotation(k-1),0))v:setLocalZOrder(self:_getZorder(k-1))endendfunction UIRotateMenu1:updatePosWithAni()for k,v in pairs(self._itemT) dov:stopAllActions()endfor k,v in pairs(self._itemT) dolocal newpos = self:_getPos(k-1)v:moveTo({time = self.AniDuration, x = newpos.x, y = newpos.y})v:scaleTo({time = self.AniDuration, scale = self:_getScale(k-1)})v:rotateTo({time = self.AniDuration, rotation = cc.vec3(0,self:_getRotation(k-1),0)})v:setLocalZOrder(self:_getZorder(k-1))endlocal delayTimeAct = cc.DelayTime:create(self.AniDuration)local sequence = cc.Sequence:create(delayTimeAct,cc.CallFunc:create(handler(self,self.callFunc)))self:runAction(sequence)endfunction UIRotateMenu1:_getPos(idx)local cs = self:getContentSize()local deltaX = self:curveFunc(self:transIdxToCurveFuncVar(idx),cs.width/2)return cc.p(cs.width/2 + deltaX,cs.height/2)endfunction UIRotateMenu1:_getZorder(idx)return -math.abs(idx-self:_getIndex())endfunction UIRotateMenu1:_getScale(idx)return 1- math.abs(self:curveFunc(self:transIdxToCurveFuncVar(idx),1))endfunction UIRotateMenu1:_getRotation(idx)return self:curveFunc(self:transIdxToCurveFuncVar(idx),60)endfunction UIRotateMenu1:_getIndex()return self._indexendfunction UIRotateMenu1:_setIndex( curTmpIdx )self._index = curTmpIdxendfunction UIRotateMenu1:callFunc()self:rectify()local curSp = self._itemT[self:_getIndex() + 1]if curSp thenself.label:setString(curSp:getName())endendfunction UIRotateMenu1:onPanelTouchBegan( touch,event )      -- cclog("UIRotateMenu1:onPanelTouchBegan")    if not self.isTouchInside(self,touch) then    return false    end    for k,v in pairs(self._itemT) do    v:stopAllActions()    end    return trueend function UIRotateMenu1:onPanelTouchMoved( touch,event )local deltaX = touch:getDelta().xlocal curTmpIdx = self:transMoveLenToVar(deltaX)self:_setIndex(curTmpIdx)self:updatePos()endfunction UIRotateMenu1:onPanelTouchEnded( touch,event )local deltaX = touch:getLocation().x - touch:getStartLocation().xself:rectify(deltaX)self:updatePosWithAni()end-- 将移动长度转为核心变量function UIRotateMenu1:transMoveLenToVar(moveLen)local cs = self:getContentSize()return self._index - moveLen/(cs.width * self.ItemScrollFactor)end-- 将当前Idx转为曲线方程自变量function UIRotateMenu1:transIdxToCurveFuncVar(idx)return idx - self:_getIndex() endfunction UIRotateMenu1:curveFunc(x,width) -- x:deltaIdxreturn width * x/(math.abs(x)+self.Factror)endfunction UIRotateMenu1:onEnter()cclog("UIRotateMenu1:onEnter")-- title    local label = cc.Label:createWithTTF(self.title(), "fonts/arial.ttf", 32)    self:addChild(label)    label:setAnchorPoint(cc.p(0.5, 0.5))    label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 50) )    -- index label    label = cc.Label:createWithTTF("", "fonts/arial.ttf", 22)    label:setColor(cc.c3b(255,0,0))    self:addChild(label)    label:setAnchorPoint(cc.p(0.5, 0.5))    label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 80) )    self.label = label    local ball = cc.Sprite:create("Images/moke1.jpg")    ball:setName("moke1")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke2.jpg")    ball:setName("moke2")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke3.jpg")    ball:setName("moke3")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke4.jpg")    ball:setName("moke4")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke5.jpg")    ball:setName("moke5")    self:addMenuItem(ball)    -- ball = cc.Sprite:create("Images/moke6.jpg")    -- self:addMenuItem(ball)endfunction UIRotateMenu1:onExit()endfunction UIRotateMenu1Main()cclog("UIRotateMenu1Main")local scene = cc.Scene:create()local rotateMenu = UIRotateMenu1:create()scene:addChild(rotateMenu)scene:addChild(CreateBackMenuItem())return sceneend

2.2 类型2

效果


函数方程



Lua源码(参:http://blog.csdn.net/ccy0815ccy/article/details/41519767)
local UIRotateMenu2 = class("UIRotateMenu2",_class.UIBase)UIRotateMenu2.AniDuration = 0.5 -- 运动延时UIRotateMenu2.Factror = 2 -- 控制曲线形态UIRotateMenu2.ItemScrollFactor = 1/5 -- 滑过1/5宽度对应滑动过一个itemUIRotateMenu2.IndexScrollFactor = 1/3 -- 滑动超过1/3自动转至下个Indexfunction UIRotateMenu2:ctor()_class.UIBase.ctor(self)self._itemT = {}self._index = 0 -- 中心位置Item indexself._unitAngle = 0 -- 两个item间相隔的离心角(单位离心角)    local cs = cc.Director:getInstance():getWinSize()    self:setContentSize(cs)    -- self:setContentSize(cc.size(cs.width*2/3,cs.height*2/3))    self.majorSemiAxis = cs.width/4 -- 长半轴    self.minorSemiAxis = cs.height/4 -- 短半轴endfunction UIRotateMenu2:title() return "Moke And TianTian"endfunction UIRotateMenu2:addMenuItem(item)local cs = self:getContentSize()item:setPosition(cc.p(cs.width/2,cs.height/2))self:addChild(item)table.insert(self._itemT,item)self:reset()self:updatePosWithAni()endfunction UIRotateMenu2:reset()self._index = 0self._unitAngle = 2 * math.pi / #self._itemTendfunction UIRotateMenu2:rectify( deltaX )local isforward = nilif deltaX thenif deltaX > 0 then isforward = trueelseisforward = falseendendlocal idx = self:_getIndex()if idx < 0 thenidx = idx + #self._itemTelseif idx > (#self._itemT - 1) thenidx = idx - #self._itemTendif isforward == true thenidx = math.floor(idx + self.IndexScrollFactor)elseif isforward == false thenidx = math.floor(idx + 2*self.IndexScrollFactor)endself:_setIndex(idx)endfunction UIRotateMenu2:updatePos()for k,v in pairs(self._itemT) dov:setPosition(self:_getPos(k-1))v:setScale(self:_getScale(k-1))v:setOpacity(self:_getOpacity(k-1))-- v:setRotation3D(cc.vec3(0,self:_getRotation(k-1),0))v:setLocalZOrder(self:_getZorder(k-1))endendfunction UIRotateMenu2:updatePosWithAni()for k,v in pairs(self._itemT) dov:stopAllActions()endfor k,v in pairs(self._itemT) dolocal newpos = self:_getPos(k-1)v:moveTo({time = self.AniDuration, x = newpos.x, y = newpos.y})v:scaleTo({time = self.AniDuration, scale = self:_getScale(k-1)})v:fadeTo({time = self.AniDuration, opacity = self:_getOpacity(k-1)})-- v:rotateTo({time = self.AniDuration, rotation = cc.vec3(0,self:_getRotation(k-1),0)})v:setLocalZOrder(self:_getZorder(k-1))endlocal delayTimeAct = cc.DelayTime:create(self.AniDuration)local sequence = cc.Sequence:create(delayTimeAct,cc.CallFunc:create(handler(self,self.callFunc)))self:runAction(sequence)endfunction UIRotateMenu2:_getPos(idx)local cs = self:getContentSize()local idxAngle = self:transIdxToCurveFuncVar(idx)local posx = self:curveFuncSin(idxAngle,cs.width/2,self.majorSemiAxis)local posy = self:curveFuncCos(idxAngle,cs.height/2,-self.minorSemiAxis)return cc.p(posx,posy)endfunction UIRotateMenu2:_getZorder(idx)local cs = self:getContentSize()local idxAngle = self:transIdxToCurveFuncVar(idx)return self:curveFuncCos(idxAngle,cs.height/2,self.minorSemiAxis)end-- scale: 0.5~1function UIRotateMenu2:_getScale(idx)local idxAngle = self:transIdxToCurveFuncVar(idx)return self:curveFuncCos(idxAngle,0.75,0.25)end-- opcacity: 129~255function UIRotateMenu2:_getOpacity(idx)local idxAngle = self:transIdxToCurveFuncVar(idx)return self:curveFuncCos(idxAngle,192,63)endfunction UIRotateMenu2:_getRotation(idx)endfunction UIRotateMenu2:_getIndex()return self._indexendfunction UIRotateMenu2:_setIndex( curTmpIdx )self._index = curTmpIdxendfunction UIRotateMenu2:callFunc()self:rectify()local curSp = self._itemT[self:_getIndex() + 1]if curSp thenself.label:setString(curSp:getName())endendfunction UIRotateMenu2:onPanelTouchBegan( touch,event )      -- cclog("UIRotateMenu2:onPanelTouchBegan")    if not self.isTouchInside(self,touch) then    return false    end    for k,v in pairs(self._itemT) do    v:stopAllActions()    end    return trueend function UIRotateMenu2:onPanelTouchMoved( touch,event )local deltaX = touch:getDelta().xlocal curTmpIdx = self:transMoveLenToVar(deltaX)self:_setIndex(curTmpIdx)self:updatePos()endfunction UIRotateMenu2:onPanelTouchEnded( touch,event )local deltaX = touch:getLocation().x - touch:getStartLocation().xself:rectify(deltaX)self:updatePosWithAni()end-- 将移动长度转为核心变量function UIRotateMenu2:transMoveLenToVar(moveLen)local cs = self:getContentSize()return self._index - moveLen/(cs.width * self.ItemScrollFactor)end-- 将当前Idx转为曲线方程自变量function UIRotateMenu2:transIdxToCurveFuncVar(idx)return (idx - self._index) * self._unitAngleendfunction UIRotateMenu2:curveFuncSin(x,a,b) -- x:curAnglereturn a + b * math.sin(x)endfunction UIRotateMenu2:curveFuncCos(x,a,b)return a + b * math.cos(x)endfunction UIRotateMenu2:onEnter()cclog("UIRotateMenu2:onEnter")-- title    local label = cc.Label:createWithTTF(self.title(), "fonts/arial.ttf", 32)    self:addChild(label)    label:setAnchorPoint(cc.p(0.5, 0.5))    label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 50) )    -- index label    label = cc.Label:createWithTTF("", "fonts/arial.ttf", 22)    label:setColor(cc.c3b(255,0,0))    self:addChild(label)    label:setAnchorPoint(cc.p(0.5, 0.5))    label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 80) )    self.label = label    local ball = cc.Sprite:create("Images/moke1.jpg")    ball:setName("moke1")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke2.jpg")    ball:setName("moke2")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke3.jpg")    ball:setName("moke3")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke4.jpg")    ball:setName("moke4")    self:addMenuItem(ball)    ball = cc.Sprite:create("Images/moke5.jpg")    ball:setName("moke5")    self:addMenuItem(ball)    -- ball = cc.Sprite:create("Images/moke6.jpg")    -- self:addMenuItem(ball)endfunction UIRotateMenu2:onExit()endfunction UIRotateMenu2Main()cclog("UIRotateMenu2Main")local scene = cc.Scene:create()local rotateMenu = UIRotateMenu2:create()scene:addChild(rotateMenu)scene:addChild(CreateBackMenuItem())return sceneend
可以加入Cocos自带的各种Action实现更多的效果,如下:

修改代码
function UIRotateMenu2:updatePosWithAni()for k,v in pairs(self._itemT) dov:stopAllActions()endfor k,v in pairs(self._itemT) dolocal newpos = self:_getPos(k-1)-- v:moveTo({time = self.AniDuration, x = newpos.x, y = newpos.y})local action = cc.MoveTo:create(self.AniDuration, cc.p(newpos.x, newpos.y))local move_ease_out = cc.EaseBounceOut:create(action)v:runAction(move_ease_out)v:scaleTo({time = self.AniDuration, scale = self:_getScale(k-1)})v:fadeTo({time = self.AniDuration, opacity = self:_getOpacity(k-1)})-- v:rotateTo({time = self.AniDuration, rotation = cc.vec3(0,self:_getRotation(k-1),0)})v:setLocalZOrder(self:_getZorder(k-1))endlocal delayTimeAct = cc.DelayTime:create(self.AniDuration)local sequence = cc.Sequence:create(delayTimeAct,cc.CallFunc:create(handler(self,self.callFunc)))self:runAction(sequence)end

上述两种类型控件原理如下:
1)在滑动时计算处于中间位置的Index;
2)确定采用何种曲线方程计算item的位置、尺度、旋转角度等属性;
3)基于item的index与中心位置的index,计算曲线函数自变量参数,从而进一步计算节点各属性。
至于其他过程,如中心index的矫正,一般无需修改。







原创粉丝点击