2016年4月20日 星期三

0419 Cocos2dx 小技巧 ScrollView實現縮放效果

Cocos2dx 小技巧(十四)ScrollView實現縮放效果

http://blog.csdn.net/star530/article/details/25658725

前天有個網友問我一些關於scrollView的用法,由於在QQ上實在講不清,所以就利用晚上的時間寫這篇博客出來了。
本篇要實現的功能是用scrollView 拖動對象時,對象移動到某個固定範圍會有放大、縮小的效果。下面開始。


在進入正題前我先簡短的介紹下scrollView應該怎麼用吧(想必大家也都會用~~):
1、記得在頭文件裡包含 「../extensions/cocos-ext.h",順便聲明下作用域:USING_NS_CC_EXT;
2、在類的繼承裡 加上ScrollViewDelegate,如下:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. class HelloWorld : public cocos2d::Layer,public ScrollViewDelegate  
3、在類的聲明中,加上三個scrollView的委託函數,如下:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void scrollViewDidScroll(ScrollView* view);  
  2. void scrollViewDidZoom(ScrollView* view);  
  3. void scrollViewMoveOver(ScrollView* view);  
4、實在不想繼續說廢話了,直接看實例吧。

先看頭文件:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #ifndef __HELLOWORLD_SCENE_H__  
  2. #define __HELLOWORLD_SCENE_H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include "../extensions/cocos-ext.h"  
  6.   
  7. USING_NS_CC;  
  8. USING_NS_CC_EXT;  
  9.   
  10. class HelloWorld : public cocos2d::Layer,public ScrollViewDelegate  
  11. {  
  12. public:  
  13.     static cocos2d::Scene* createScene();//獲取歡迎畫面的Scene  
  14.     virtual bool init();    
  15.   
  16.     void menuCloseCallback(Ref* pSender);  
  17.       
  18.     CREATE_FUNC(HelloWorld);  
  19.   
  20.     //scroll 委託  
  21.     void scrollViewDidScroll(ScrollView* view);  
  22.     void scrollViewDidZoom(ScrollView* view);  
  23.     void scrollViewMoveOver(ScrollView* view);  
  24.   
  25. private:  
  26.     Vector<Sprite*> sp_vec;//聲明一個容器  
  27. };  
  28. #endif // __HELLOWORLD_SCENE_H__  

下面看定義
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. bool HelloWorld::init()  
  2. {     
  3.     //首先創建scrollView  
  4.     auto scroll_layer = Layer::create();//創建scrollView中的容器層  
  5.     scroll_layer->setPosition(Point::ZERO);  
  6.     scroll_layer->setAnchorPoint(Point::ZERO);  
  7.     scroll_layer->setContentSize(Size(600,300));//設置容器層大小為(600,300)  
  8.   
  9.     auto scrollView = ScrollView::create(Size(400,300),scroll_layer);//創建scrollView,顯示窗口大小為(400,300)  
  10.     scrollView->setDelegate(this);//設置委託  
  11.     scrollView->setDirection(ScrollView::Direction::HORIZONTAL);//設置滾動方向為水平  
  12.     scrollView->setPosition(Point(300,200));  
  13.     this->addChild(scrollView,2);  
  14.   
  15.     //創建三個對象  
  16.     auto boy = Sprite::create("boy.png");//沒錯,主角又是我們熟悉的那仨。多麼溫馨。  
  17.     boy->setPosition(Point(150,100));  
  18.     scroll_layer->addChild(boy,2);  
  19.   
  20.     auto girl = Sprite::create("girl_1.png");  
  21.     girl->setPosition(Point(300,100));  
  22.     scroll_layer->addChild(girl,2);   
  23.   
  24.     auto girl3 = Sprite::create("girl_3.png");  
  25.     girl3->setPosition(Point(450,100));  
  26.     scroll_layer->addChild(girl3,2);   
  27.    
  28.     sp_vec.pushBack(boy);//將三個對象放入容器中  
  29.     sp_vec.pushBack(girl);  
  30.     sp_vec.pushBack(girl3);  
  31.   
  32.        return true;  
  33. }  

接下來看下scrollView的委託函數,這裡只要看scrollViewDidScroll 就好了。實現效果是對象在某個坐標範圍內移動時會有縮放效果。
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void HelloWorld::scrollViewDidScroll(ScrollView* view)  
  2. {  
  3.     //在scrollView拖動時響應該函數  
  4.   
  5.     auto offsetPosX = (view->getContentOffset()).x;//獲得偏移X坐標(向右移動,偏移量為正數,向左則為負數)  
  6. //  CCLOG("offset pos is %f , %f",offsetPos.x,offsetPos.y);  
  7.   
  8.     //for 循環遍歷容器中的每個精靈  
  9.     for( auto e : sp_vec )  
  10.     {  
  11.         auto pointX = e->getPositionX();//獲得當前對象的X坐標(不管怎麼滾動,這個坐標都是不變的)  
  12.         float endPosX = pointX + offsetPosX;//將精靈的 X坐標 + 偏移X坐標  
  13.   
  14.         //當endPosX在 150~250 範圍,則對象的大小從左向右遞增  
  15.         if( endPosX > 150 && endPosX < 250 )  
  16.         {  
  17.             float x = endPosX / 150;//放大倍數為 endPosX / 150;  
  18.             e->setScale(x);  
  19.             CCLOG("x = %f",x);  
  20.         }  
  21.         //當endPosX在 250~350 範圍,則對象的大小從左向右遞減  
  22.         else if( endPosX > 250 && endPosX < 350 )   
  23.         {  
  24.             //下面這個公式不好解釋,我就這麼說吧:  
  25.             //假設 endPosX = 200,那麼放大倍數應該是 200 / 150 = 1.33左右,那麼當endPosX = 300時,出於對稱的原理,我們以250為對稱中心,那麼  
  26.             //300 的放大倍數也應該是 1.33。這就是下面的公式由來  
  27.             float a = endPosX - 250;  
  28.             float b = 250 - a;  
  29.   
  30.             float x = b / 150;  
  31.             e->setScale(x);  
  32.         }  
  33.         else   
  34.         {  
  35.             //不是在上面的範圍,則設置為正常大小  
  36.             e->setScale(1.0f);  
  37.         }  
  38.     }     
  39. }  
  40. void HelloWorld::scrollViewDidZoom(ScrollView* view)  
  41. {  
  42.     //do something  
  43. }  
  44. void HelloWorld::scrollViewMoveOver(ScrollView* view)  
  45. {  
  46.     //do something  
  47. }  

恩,註釋寫的很清楚啦,但我還是要稍微補充一些東東:我們應該知道,對象放到滾動層上(如scroll_layer->addChild(boy)),那麼不管對象在scrollView上如何移動,它獲得的坐標都是不會變的(如boy->getPosition()是不變的數值),這種情況下,如果我們想實現對象在某個坐標範圍內會有縮放效果,那麼只是去獲取對象的坐標肯定是行不通的,所以肯定要找一個時刻在變化的」參照物」來利用下,該找什麼呢?沒錯,就是scrollView的偏移坐標(scrollView->getContentOffset())!只要scrollView移動一下,那麼它的 偏移量也隨之改變。我這裡就是利用對象的坐標與scrollView的偏移坐標之間不可告人的秘密,從而實現當前的目的。
下面看下運行效果。

沒有留言:

張貼留言

cocos2dx-lua 建立滑鼠監聽

重要關鍵字  EVENT_MOUSE_SCROLL addEventListenerWithSceneGraphPriority      if IsPc() then --建立滑鼠監聽         local listener = cc.EventListenerMouse...