展会信息港展会大全

cocos2dx 实现华丽丽的滚动层.
来源:互联网   发布日期:2015-09-27 15:11:31   浏览:4415次  

导读:1 -- 2 -- 滑动惯性. 3 -- 4 Control.SlideInertia = Control.SlideInertia or class(Control.SlideInertia, function() 5 return cc.Node:create(); 6 end ); 7 8 function Control.SlideInertia:init() 9 self.schId = 0; 10 end 11 12 function Control.S...

1 --

2 --滑动惯性.

3 --

4 Control.SlideInertia = Control.SlideInertia or class("Control.SlideInertia", function()

5return cc.Node:create();

6end );

7

8 function Control.SlideInertia:init()

9self.schId = 0;

10 end

11

12 function Control.SlideInertia:destroy()

13self.schId = Utils:unSchedule(self.schId);

14 end

15

16 function Control.SlideInertia:setMark(x, y)

17self.time = os.time();

18self.mark = cc.p(x, y);

19self.schId = Utils:unSchedule(self.schId);

20 end

21

22 function Control.SlideInertia:run(x, y, frameCallFunc, endCallFunc)

23frameCallFunc = frameCallFunc or function() cclog("default frameCallFunc") end;

24endCallFunc = endCallFunc or function() cclog("default endCallFunc") end;

25

26local curTime = os.time();

27local diffTime = math.max(curTime - self.time, 1);

28local stepX = (x - self.mark.x) / diffTime;

29local stepY = (y - self.mark.y) / diffTime;

30local function call()

31frameCallFunc(stepX, stepY);

32stepX = stepX * 0.8;

33stepY = stepY * 0.8;

34if math.abs(stepX) < 1 and math.abs(stepY) < 1 then

35endCallFunc();

36self.schId = Utils:unSchedule(self.schId);

37end

38end

39if math.abs(stepX) > 0 or math.abs(stepY) > 0 then

40self.schId = Utils:unSchedule(self.schId);

41self.schId = Utils:runSchedule(call, 0.01);

42end

43 end

44

45

46 --

47 --滚动层.

48 --

49 Control.ScrollView = Control.ScrollView or class("Control.ScrollView", function()

50return cc.Node:create();

51end );

52

53 --[[

54 params = {

55["count"]= 0,

56["cellWidth"]= 0,

57["cellHeight"]= 0,

58["triggerLen"]= 0,

59["scaleXY"]= 0,

60["maxOffsetY"]= 0,

61["newCallFunc"]= nil,=>newCallFunc(i)

62["selCallFunc"]= nil,=>selCallFunc(cell)

63["enterCallFunc"]= nil,=>enterCallFunc(cell)

64["leaveCallFunc"]= nil,=>leaveCallFunc(cell)

65 }

66 ]]

67

68 function Control.ScrollView:init(params)

69local count = params["count"];

70local cellWidth = params["cellWidth"];

71local cellHeight = params["cellHeight"];

72local triggerLen = params["triggerLen"];

73local scaleXY = params["scaleXY"];

74local maxOffsetY = params["maxOffsetY"] or 0;

75local newCallFunc = params["newCallFunc"];

76local selCallFunc = params["selCallFunc"] or function(cell) cclog("sel cell: %s", cell); end;

77local enterCallFunc = params["enterCallFunc"] or function(cell) cclog("enter cell: %s", cell); end;

78local leaveCallFunc = params["leaveCallFunc"] or function(cell) cclog("leave cell: %s", cell); end;

79local selCell = nil;

80local curCell = nil;

81local triggerScale = triggerLen / cellWidth;

82local downPosX;

83local downPosY;

84local cellScale = 1;

85local elements = {};

86local nodePosX = triggerLen * 0.5 + cellWidth * 0.5;

87local isTouch = false;

88local isLoadEnd = false;

89local skipFrame = math.floor(count / 50) + 1;

90local skipCount = 0;

91local viewSize = cc.Director:getInstance():getVisibleSize();

92

93local function in2Value(value, minValue, maxValue)

94return value >= minValue and value <= maxValue;

95end

96

97--移动所有节点.

98local function moveCells(offsetX)

99nodePosX = nodePosX + offsetX;

100for i = 1, count do

101local cell = elements[i];

102if math.abs(nodePosX + i * cellWidth) < viewSize.width + cellWidth / 2 then

103cell:setVisible(true);

104--移动.

105(function()

106local curPosX = nodePosX + (i - 1) * cellWidth;

107local movetoX = curPosX;

108local movetoY = 0;

109local maxX = triggerLen / 2;

110local minX = maxX - cellWidth;

111if curPosX <= maxX and curPosX >= minX then

112if not cell.isEnter then

113leaveCallFunc(selCell);

114selCell.isEnter = false;

115selCell = cell;

116selCell.isEnter = true;

117enterCallFunc(cell);

118end

119movetoX = curPosX + (curPosX - maxX) * (triggerScale - 1);

120local centerOffsetY = (maxX - cellWidth / 2);

121local offsetWidth = (maxX - minX) / 2;

122movetoY = (1 - math.abs(curPosX - centerOffsetY) / offsetWidth) * maxOffsetY;

123else

124movetoX = curPosX + (curPosX < minX and -cellWidth * (triggerScale - 1) or 0);

125end

126cell:setPositionX(movetoX);

127cell:setPositionY(movetoY);

128end)();

129--缩放.

130(function()

131local distance = math.abs(cell:getPositionX());

132local scale = 0;

133local maxDistance = triggerLen * 0.5;

134if distance <= maxDistance then

135scale = (1 - distance / maxDistance) * (scaleXY - cellScale);

136end

137cell:setScale(cellScale + scale);

138end)();

139else

140cell:setVisible(false);

141end

142end

143end

144

145--调整位置.

146local function adjustPosition()

147local function call()

148local cell = curCell and curCell or selCell;

149local pointX = cell:getPositionX();

150local step = -pointX * 0.1;

151if math.abs(step) < 0.1 then

152curCell = nil;

153selCallFunc(cell);

154self.schSlideId = Utils:unSchedule(self.schSlideId);

155end

156moveCells(step);

157end

158self.schSlideId = Utils:unSchedule(self.schSlideId);

159self.schSlideId = Utils:runSchedule(call, 0.01);

160end

161

162local function isTouchRect(touchPoint)

163local worldPoint = self:convertToWorldSpace(cc.p(0, 0));

164return in2Value(touchPoint.y, worldPoint.y, worldPoint.y + cellHeight);

165end

166

167local function onTouchUp(touch)

168local function frameCallFunc(stepX, stepY)

169moveCells(stepX);

170end

171local function endCallFunc()

172adjustPosition();

173end

174local touchPoint = touch:getLocation();

175self.slide:run(touchPoint.x, touchPoint.y, frameCallFunc, endCallFunc);

176end

177

178local function onTouchBegan(touch, event)

179skipCount = 0;

180local touchPoint = touch:getLocation();

181local result = isTouchRect(touchPoint);

182curCell = nil;

183downPosX = touchPoint.x;

184downPosY = touchPoint.y;

185if result then

186self.slide:setMark(downPosX, downPosY);

187self.schSlideId = Utils:unSchedule(self.schSlideId);

188end

189return result;

190end

191

192local function onTouchMoved(touch, event)

193if skipCount % skipFrame == 0 then

194local touchPoint = touch:getLocation();

195

196--调整拖动灵敏度.

197if math.abs(downPosX - touchPoint.x) > 5 then

198isTouch = false;

199end

200

201self.slide:setMark(downPosX, downPosY);

202moveCells(touchPoint.x - downPosX);

203downPosX = touchPoint.x;

204downPosY = touchPoint.y;

205end

206skipCount = skipCount + 1;

207end

208

209local function onTouchEnded(touch, event)

210onTouchUp(touch);

211end

212

213local function onTouchCancelled(touch, event)

214onTouchUp(touch);

215end

216

217local function setCurCell(cell)

218if isTouch == true then

219curCell = cell;

220adjustPosition();

221end

222end

223

224local function loadEnd()

225isLoadEnd = true;

226

227self.schLoadId = Utils:unSchedule(self.schLoadId);

228

229--touch 响应层.

230local touchLayer = cc.Layer:create();

231local listener = cc.EventListenerTouchOneByOne:create();

232listener:registerScriptHandler( onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN );

233listener:registerScriptHandler( onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED );

234listener:registerScriptHandler( onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED );

235listener:registerScriptHandler( onTouchCancelled, cc.Handler.EVENT_TOUCH_CANCELLED );

236touchLayer:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, touchLayer);

237self:addChild(touchLayer);

238

239--touch吞噬层.

240local listener = cc.EventListenerTouchOneByOne:create();

241listener:registerScriptHandler(

242function(touch, event)

243return isTouchRect(touch:getLocation());

244end, cc.Handler.EVENT_TOUCH_BEGAN );

245listener:setSwallowTouches(true);

246self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, self);

247

248adjustPosition();

249end

250

251self.schSlideId = 0;

252self.schLoadId = 0;

253self.slide = Utils:createCocos2dObject(Control.SlideInertia);

254self:addChild(self.slide);

255self:setAnchorPoint(cc.p(0.5, 0.0));

256

257--异步加载.

258local num = 0;

259self.schLoadId = Utils:runSchedule(function()

260local cell = newCallFunc(num + 1);

261self:addChild(cell);

262cell:setAnchorPoint(cc.p(0.5, 0.0));

263cell:setPosition(nodePosX + num * cellWidth, 0.0);

264cell.isEnter = false;

265cell:setTouchEnabled(true);

266cell.onTouchBegan = function() if isLoadEnd then isTouch = true; end end;

267cell.onTouchEnded = function() setCurCell(cell); end;

268Utils:registerButtonEvent(cell);

269table.insert(elements, cell);

270cellScale = cell:getScale();

271selCell = selCell and selCell or cell;

272

273num = num + 1;

274if num == count then

275loadEnd();

276end

277end, 0.016);

278 end

279

280 function Control.ScrollView:destroy()

281self.schSlideId = Utils:unSchedule(self.schSlideId);

282self.schLoadId = Utils:unSchedule(self.schLoadId);

283 end

复制代码

该控件实质是一个cc.Node.

内部没有使用cc.ScrollView.

因为引擎自带的控件相当不好扩充. 最主要的是, 我喜欢造轮子.

该控件内部有一个 滑动对象, 该对象用于控制惯性.

该控件通过

newCallFunc 创造子节点.

SelCallFunc 节点最大化时回调.

enterCallFunc 节点开始变大时回调.

leaveCallFunc 节点恢复原状时回调.

移动子节点时, 需要对子节点逐个遍历移动.

这里占用了很大的性能开销.

不过, 这是不可能的.

在超出范围的子节点将被忽略, 并且隐藏.

并且内部使用了跳帧技巧.

根据节点数量变化跳帧数.

300个骨骼动画拖动时, 最低可在30帧以上, 平均45帧左右.

赞助本站

人工智能实验室
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港