前言:
废话不多说,先看最终效果图
正文:
1、使用说明:
① 引入头文件 “NumberScroller.h"
② 用NumberScroller::create(int length,int FontSize) 函数来创建NumberScroller对象
③ 利用setNumber(int number)函数来设置计时器里面的值(这里只实现了向后滚动,即设置的值要大于等于当前值)
④ 利用getNumber获得当前计数器显示的值
⑤ 利用setTime(float time)函数来设置计时器滚动的速度,默认为1
2、实现思路:
① 根据输入的长度length确定计时器的长度(即多少位)
② 根据输入的FontSize确定字体大小
③ 创建length条并排放置的竖着的从01234567890(注意末尾有个零)
④ 根据设置的数字,不同的竖条移动相应的位置。
⑤ 利用遮罩层遮罩
3、源码解析:
对应思路①②
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | bool NumberScroller::init( int length, int FontSize){ if (!Node::init()) return false ; m_length=length; m_FontSize=FontSize; m_visibleNode=Node::create(); //排好length列数字 for ( int i=0;i<length;i++){ NumberColumn*column=NumberColumn::create(FontSize); m_columns.pushBack(column); column->setAnchorPoint(Point(0,0)); column->setposition(i*FontSize,0); column->setTime(m_time); m_visibleNode->addChild(column); } /*设置遮罩层*/ ClipPingNode*cliper=ClipPingNode::create(); DrawNode*drawNode=DrawNode::create(); Pointpoints[]={Point(getposition()),Point(getpositionX(),getpositionY()+m_FontSize), Point(getpositionX()+m_length*m_FontSize,Point(getpositionX()+m_length*m_FontSize,getpositionY())}; drawNode->drawpolygon(points,4,color4F(0,1),1)); cliper->setStencil(drawNode); cliper->addChild(m_visibleNode); this ->addChild(cliper); } |
先暂时不用看设置遮罩层部分,前面只是保存长度和字体大小到成员变量中,下面的一个for循环就是用来排好length列数字的。
其中这里出现了一个NumberColumn类,表示一列数字01234567890。
具体的初始化函数如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | bool NumberColumn::init( int FontSize){ if (!Node::init()) return false ; m_numbers=Node::create(); this ->addChild(m_numbers); m_FontSize=FontSize; this ->scheduleUpdate(); for ( int i=0;i<10;i++){ char str[2]; str[0]=i+ '0' ; str[1]= ' Label*temp=Label::create(str, "" ,FontSize); temp->setAnchorPoint(Point(0,0)); temp->setposition(Point(0,i*FontSize)); m_numbers->addChild(temp); } char str[2]; str[0]= '0' ; str[1]= ' Label*temp=Label::create(str,FontSize); temp->setAnchorPoint(Point(0,0)); temp->setposition(Point(0,10*FontSize)); m_numbers->addChild(temp); return true ; } NumberColumn的init函数里面,除了保存长度和字体大小和启动update外,接下来就是构造一个01234567890的竖列。 NumberScroller最重要的函数还是setNumber |
注意,我们这里把所有Label都放在一个Node里面,这样可使我们更方便的 *** 作.
最后,回到NumberScroller 初始化完的效果是这样子(无遮罩)的:
voID
int number){ if (number>m_cur_num){ m_cur_num=number; for ( int i=0;i<m_length;i++){ m_columns.at(m_length-i-1)->setNumber(number); number/=10; } } } | 1 2 3 4 5 |
可以看出都是间接地调用NumberColumn的setNumber方法
int number, bool direction){ m_target_num=number; int delta=m_target_num-m_cur_num; update_speed=(delta*m_FontSize/m_time); } | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
奇怪啦,NumberColumn也只是简单的把传来的number保存到m_target_num里面,还有计算滚动的速度 也没有实现滚动的动作啊。
奥秘在于NumberColumn启动的update函数
float d){ if (m_cur_num!=m_target_num){ //如果当前显示的数字不等于目标数字,即要开始滚动 float dis=update_speed*d; //每次调用update函数需要滚动的距离等于update_speed乘以d(update_speed在setNumber函数中已经算出) m_numbers->setpositionY(m_numbers->getpositionY()-dis); //每次使整条向下移动dis距离 update_moveSum+=dis; //update_moveSum用于保存现在到底移动了多少距离 if (update_moveSum>=m_FontSize){ //如果现在已经移动了一个字大小的距离 m_cur_num++; //当前数字+1 m_numbers->setpositionY(-m_cur_num*m_FontSize); //标准对齐 update_moveSum=0; //重置 } } } update函数便是实现滚动效果的核心,每一行都给了详细的注释。 所以对应每一条NumberColum,其对应的m_cur_num是不一样的。 |
因为我们这里要实现的是类似于时钟的滚动效果(秒针转1圈时,分针转1/60圈),应用到计时器,个位滚动10次,十位才会转一下,int
例如999这个数 ,第一条(百位)对应的m_cur_num应该是9,第二条(十位)对应的m_cur_num应该是99,第三条(个位)对应的m_cur_num应该是999。
由于setNumber时候计算了速度:
update_speed=(delta*m_FontSize/m_time); 间隔越大,速度越快,因此保证了每条NumberColumn均会在m_time时间内完成滚动。 | 1 2 3 4 5 6 7 8 9 10 |
voID
有了上面的介绍,再回过头来再看一次NumberScroller的setNumber函数,是不是恍然大悟呢:
int number){ if (number>m_cur_num){ m_cur_num=number; for ( int i=0;i<m_length;i++){ m_columns.at(m_length-i-1)->setNumber(number); number/=10; } } } | 1 2 3 4 5 6 7 8 9 10 11 12 13 |
完成效果后如下:
最后,添加遮罩层,只显示当前数字部分。
int length, int FontSize){ 。。。省略了一部分。。。 /*设置遮罩层*/ ClipPingNode*cliper=ClipPingNode::create(); DrawNode*drawNode=DrawNode::create(); Pointpoints[]={Point(getposition()), Point(getpositionX()+m_length*m_FontSize,getpositionY())}; drawNode->drawpolygon(points,1)); cliper->setStencil(drawNode); cliper->addChild(m_visibleNode); this ->addChild(cliper); } |
关于遮罩的基本知识,推荐《【Cocos2d-x 3.2】裁剪节点(ClippingNode)总结》
4、附上源码:滚动计数器NumberScroller
总结以上是内存溢出为你收集整理的Cocos2d-x 3.2编写常用UI组件(二)滚动计数器NumberScroller全部内容,希望文章能够帮你解决Cocos2d-x 3.2编写常用UI组件(二)滚动计数器NumberScroller所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)