Cocos2d-x3.0 可旋转的饼图

时间:2022-05-01 12:09:14

本文效果类代码:http://download.csdn.net/detail/qqmcy/7349165

效果:

Cocos2d-x3.0 可旋转的饼图

这个饼图是我参照iOS下的一个饼图效果制作的,主要功能实现了。但效果有待后期改进。下面附上使用方法。

首先,我们要先在Cocos2d-x框架下添加一个画扇形的方法:

CCDrawingPrimitives.h

这个文件下添加如下代码:

    
    /********************************************************画扇形****/
    void drawSolidfanshaped( const Point& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY);
    void drawSolidfanshaped( const Point& center, float radius, float angle, unsigned int segments);
    
    
      /************************************************************/

CCDrawingPrimitives.cpp添加如下代码:

void drawSolidfanshaped( const Point& center, float radius, float angle, unsigned int segments)
    {
        drawSolidfanshaped(center, radius, angle, segments, 1.0f, 1.0f);
    }
    
void drawSolidfanshaped( const Point& center, float radius, float angle, unsigned int segments, float scaleX, float scaleY)
{
    
    lazy_init();

        
    const float coef = (float)angle/segments;  //系数:一段有多少度,angle为弧度制,要先通过CC_DEGREES_TO_RADIANS()转化
        
        GLfloat *vertices = (GLfloat*)calloc( sizeof(GLfloat)*2*(segments+2), 1);  //分配内存空间
        if( ! vertices )
            return;
        
        vertices[0] = center.x;
        vertices[1] = center.y;
        
        for(unsigned int i = 0;i <= segments; i++) {
            float rads = i*coef;
            GLfloat j = radius * cosf(rads + angle) * scaleX + center.x;
            GLfloat k = radius * sinf(rads + angle) * scaleY + center.y;
            
            vertices[(i+1)*2] = j;     //x坐标
            vertices[(i+1)*2+1] = k;   //y坐标
        }
        /*vertices[(segments+1)*2] = center.x;
         vertices[(segments+1)*2+1] = center.y;*/
        
            s_shader->use();
            s_shader->setUniformsForBuiltins();
           s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
        
        GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
        
#ifdef EMSCRIPTEN
        setGLBufferData(vertices, sizeof(GLfloat)*2*(segments+2));
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, 0);
#else
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
#endif // EMSCRIPTEN
        
        glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) segments+1);
        
    ::free(vertices);
        
    
        
        CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,segments+1);
        
}

下面是饼图的使用方法:

创建一个Layout类

DJPieLayout.h

//
//  DJPieLayout.h
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#ifndef __TestUI__DJPieLayout__
#define __TestUI__DJPieLayout__

#include "ui/CocosGUI.h"
#include "DJPieRotateLayerManager.h"

USING_NS_CC;


class DJPieLayout:public ui::Layout ,public DJPieRotateLayerManagerDelegate{
    
public:
    CREATE_FUNC(DJPieLayout);
    
    virtual bool init();
    
    void selectedFinish(DJPieRotateLayerManager* djpieChartLayer , int index,bool canLayerOpen) ;
    
    
    
};

#endif /* defined(__TestUI__DJPieLayout__) */

DJPieLayout.cpp

//
//  DJPieLayout.cpp
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#include "DJPieLayout.h"


bool DJPieLayout::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
        
        std::vector<Color4B> colorVec;
        std::vector<float> angleVec;
        
        Color4B c = Color4B(24, 195, 243, 255);
        Color4B c1 = Color4B(251, 151, 36, 255);
        Color4B c2 = Color4B(248, 251, 38, 255);
        Color4B c3 = Color4B(247, 49, 35, 255);
        Color4B c4 = Color4B(146, 246, 125, 255);
        Color4B c5 = Color4B(255, 170, 213, 255);
        Color4B c6 = Color4B(255, 70, 213, 255);
        
        colorVec.push_back(c);
        colorVec.push_back(c1);
        colorVec.push_back(c2);
        colorVec.push_back(c3);
        colorVec.push_back(c4);
        colorVec.push_back(c5);
        colorVec.push_back(c6);
        
        
        
        angleVec.push_back(20.0);
        angleVec.push_back(130.0);
        angleVec.push_back(30.0);
        angleVec.push_back(80.0);
        angleVec.push_back(30.0);
        angleVec.push_back(70.0);

        
        DJPieRotateLayerManager* djplm = DJPieRotateLayerManager::create();
        djplm->delegate = this;
        
        djplm->angleVec.assign(angleVec.begin(), angleVec.end());
        
        
        djplm->colorVec.assign(colorVec.begin(), colorVec.end());
        
        
        
        
        djplm->setPosition(100,100);
        djplm->addPieLayour();
        
        addChild(djplm);
        
        
        bRet  = true;
    } while (0);
    return bRet;
}

void DJPieLayout::selectedFinish(DJPieRotateLayerManager *djpieChartLayer, int index,bool canLayerOpen)
{
    log("%d,bool = %d",index,canLayerOpen);
}




将这个Layout添加到HelloWorldScene中:

在init()方法中添加:

  DJPieLayout* djPieLayout = DJPieLayout::create();
    addChild(djPieLayout);

这样就OK了。

下面我附上具体实现的代码:

扇形节点类

DJPieNode.h

//
//  DJPieNode.h
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#ifndef __TestUI__DJPieNode__
#define __TestUI__DJPieNode__

#include "cocos2d.h"
#include "ui/CocosGUI.h"


USING_NS_CC;

class DJPieNode:public ui::Layout {
    
public:
    CREATE_FUNC(DJPieNode);
    
    
    
    CC_SYNTHESIZE(Point, _centerPoint, CenterPoint);
    CC_SYNTHESIZE(Color4B, _pieColor, PieColor);
    CC_SYNTHESIZE(float, _pieRadius, PieRadius); //半径
    CC_SYNTHESIZE(float, _pieAngle, PieAngle);   //角度
    
    
    
    
    virtual bool init();
    void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated);
    void onDraw(const kmMat4 &transform, bool transformUpdated);
    CustomCommand _customCommand;
};



#endif /* defined(__TestUI__DJPieNode__) */

DJPieNode.cpp

//
//  DJPieNode.cpp
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#include "DJPieNode.h"


bool DJPieNode::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
        
        
        
        
        
        
        
        
        bRet = true;
    } while (0);
    return bRet;
}




void DJPieNode::draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
{
    _customCommand.init(_globalZOrder);
    _customCommand.func = CC_CALLBACK_0(DJPieNode::onDraw, this,transform,transformUpdated);
    renderer->addCommand(&_customCommand);
    
}


void DJPieNode::onDraw(const kmMat4 &transform, bool transformUpdated)
{
    kmGLPushMatrix();
    kmGLLoadMatrix(&transform);
    CHECK_GL_ERROR_DEBUG();
    DrawPrimitives::setDrawColor4B(_pieColor.r, _pieColor.g, _pieColor.b, _pieColor.a);
    
    DrawPrimitives::drawSolidfanshaped(_centerPoint, _pieRadius, CC_DEGREES_TO_RADIANS(_pieAngle), 1890, 1, 1);
    
    
    kmGLPopMatrix();
}



DJPieNodeLayout.h节点布局

//
//  DJPieNodeLayout.h
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#ifndef __TestUI__DJPieNodeLayout__
#define __TestUI__DJPieNodeLayout__

#include "cocos-ext.h"
#include "ui/CocosGUI.h"
#include "DJPieNode.h"






USING_NS_CC;
USING_NS_CC_EXT;



class DJPieNodeLayout:public ui::Layout{
    
public:
    
    
    CREATE_FUNC(DJPieNodeLayout);
    CC_SYNTHESIZE(Size, _winSize, WinSize);
    CC_SYNTHESIZE(Point, _centerPoint, CenterPoint);
    CC_SYNTHESIZE(Color4B, _pieColor, PieColor);
    CC_SYNTHESIZE(bool, m_isSelected, IsSelected);
    
    CC_SYNTHESIZE(float, _pieRadius, PieRadius); //半径
    CC_SYNTHESIZE(float, _pieAngle, PieAngle);   //角度
    
     CC_SYNTHESIZE(float, _angleNum, AngleNum);  //角度累计
    CC_SYNTHESIZE_RETAIN(DJPieNode* , pieNode, PieNode);
    
    virtual bool init();
    void addPieNode(int num);
    
    void    setSliceSelectedAtIndex(int index);  //选择时的方法
    void setsliceDeselectedAtIndex(int index);   //取消选择时的方法
    
    bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unusedEvent);
    
};

#endif /* defined(__TestUI__DJPieNodeLayout__) */

DJPieNodeLayout.cpp

//
//  DJPieNodeLayout.cpp
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#include "DJPieNodeLayout.h"
#include "VisibleRect.h"

bool DJPieNodeLayout::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
        
        Color4B c = Color4B(24, 195, 243, 255);
        Color4B c1 = Color4B(251, 151, 36, 255);
        Color4B c2 = Color4B(248, 251, 38, 255);
        Color4B c3 = Color4B(247, 49, 35, 255);
        Color4B c4 = Color4B(146, 246, 125, 255);
        Color4B c5 = Color4B(255, 170, 213, 255);
        
        std::vector<Color4B> colorVec;
        colorVec.push_back(c);
        colorVec.push_back(c1);
        colorVec.push_back(c2);
        colorVec.push_back(c3);
        colorVec.push_back(c4);
        colorVec.push_back(c5);
        
        std::vector<float> angleVec;
        angleVec.push_back(40);
        angleVec.push_back(100);
        angleVec.push_back(60);
        angleVec.push_back(50);
        angleVec.push_back(30);
        angleVec.push_back(80);
        //
        //        this->setSize();
        //
        // this->setSize(Size(500, 500));
        
        
        
        
        bRet = true;
    } while (0);
    return bRet;
}
void DJPieNodeLayout::addPieNode(int num)
{
    
    
        pieNode = DJPieNode::create();
        pieNode->setSize(Size(200, 200));

        pieNode->setCenterPoint(Point(0, 0));
        pieNode->setPieColor(_pieColor);
        pieNode->setPieAngle(_pieAngle);
        pieNode->setPieRadius(_pieRadius);
        
        float rotation = _pieAngle - (90 - _pieAngle) / 2;
        pieNode->setRotation(rotation);
    
    
        addChild(pieNode);
}
bool DJPieNodeLayout::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unusedEvent)
{
    return true;
}


void DJPieNodeLayout::setSliceSelectedAtIndex(int index)
{
    m_isSelected = true;
    MoveTo* moveTo = MoveTo::create(0.2f, Point(10, 10));
    
    pieNode->runAction(moveTo);
    
}

void DJPieNodeLayout::setsliceDeselectedAtIndex(int index)
{
    m_isSelected = false;
    MoveTo* moveTo = MoveTo::create(0.2f, Point(0, 0));
    
    pieNode->runAction(moveTo);
}

DJPieLayoutManager.h 画出饼图的类

//
//  DJPieLayoutManager.h
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#ifndef __TestUI__DJPieLayoutManager__
#define __TestUI__DJPieLayoutManager__

#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "DJPieNodeLayout.h"

USING_NS_CC;


class DJPieLayoutManager :public ui::Layout
{
    
public:
    CREATE_FUNC(DJPieLayoutManager);
    
    virtual bool init();
   std::vector<float> angleVec;
    std::vector<Color4B> colorVec;
    void addPieLayout();
    
    CC_SYNTHESIZE(Vector<DJPieNodeLayout*>, _djPieNodeLayoutVec, DJPieNodeLayoutVec);
    void pieSelected(int selIndex);
    void notifyDelegateOfSelectionChangeFrom(int previousSelection,int newSelection);
    
    void    setSliceSelectedAtIndex(int index);
    void setsliceDeselectedAtIndex(int index);
    
    
    
    
private:
    int _selectedSliceIndex;
    
};


#endif /* defined(__TestUI__DJPieLayoutManager__) */

DJPieLayoutManager.cpp

//
//  DJPieLayoutManager.cpp
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#include "DJPieLayoutManager.h"
#include "VisibleRect.h"

bool DJPieLayoutManager::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!ui::Layout::init());
        
         _selectedSliceIndex = -1;
        Color4B c = Color4B(24, 195, 243, 255);
        Color4B c1 = Color4B(251, 151, 36, 255);
        Color4B c2 = Color4B(248, 251, 38, 255);
        Color4B c3 = Color4B(247, 49, 35, 255);
        Color4B c4 = Color4B(146, 246, 125, 255);
        Color4B c5 = Color4B(255, 170, 213, 255);
         Color4B c6 = Color4B(255, 70, 213, 255);
        std::vector<Color4B> colorVec;
        colorVec.push_back(c);
        colorVec.push_back(c1);
        colorVec.push_back(c2);
        colorVec.push_back(c3);
        colorVec.push_back(c4);
        colorVec.push_back(c5);
        colorVec.push_back(c6);
        
        
        std::vector<float> angleVec;
        angleVec.push_back(60);
        angleVec.push_back(60);
        angleVec.push_back(60);
        angleVec.push_back(60);
        angleVec.push_back(60);
        angleVec.push_back(60);
        angleVec.push_back(40);
        
        
        Size winSize =VisibleRect::getVisibleRect().size;
        
        
        
        
        
        
        
      
        
        
        bRet = true;
    } while (0);
    return bRet;
}

void DJPieLayoutManager::addPieLayout()
{
      float angleNum = 0;
    for (int i = 0; i < angleVec.size(); i++) {
        
        DJPieNodeLayout* pieNode = DJPieNodeLayout::create();
        //            pieNode->setBackGroundColorType(cocos2d::ui::LAYOUT_COLOR_GRADIENT);
        //            pieNode->setBackGroundColor(Color3B(164, 4, 64), Color3B(192, 192, 192));
        pieNode->setSize(Size(200, 200));
        pieNode->setPieColor(colorVec.at(i));
        pieNode->setPieAngle(angleVec.at(i));
        pieNode->setPieRadius(200);
        pieNode->addPieNode(i);
        _djPieNodeLayoutVec.pushBack(pieNode);
        
    
        if (i != 0) {
            
            
            angleNum +=angleVec.at(i - 1)  +(90 - angleVec.at(i-1)) / 2 - (90 -  angleVec.at(i)) / 2;
            RotateBy* rb = RotateBy::create(0.1f, angleNum);
            pieNode->runAction(rb);
            
        }
        
        
        addChild(pieNode);
        
    }
    

}






void DJPieLayoutManager::pieSelected(int selIndex)
{
    notifyDelegateOfSelectionChangeFrom(_selectedSliceIndex, selIndex);
}

void DJPieLayoutManager::notifyDelegateOfSelectionChangeFrom(int previousSelection,int newSelection)
{
    if (previousSelection != newSelection) {
        _selectedSliceIndex = newSelection;
        
        if (newSelection != -1)
        {
            setSliceSelectedAtIndex(newSelection);
        }
        
        if (previousSelection != -1) {
            setsliceDeselectedAtIndex(previousSelection);
        }
        
    }
    else if (newSelection != -1)
    {
        DJPieNodeLayout* djLayout = _djPieNodeLayoutVec.at(newSelection);
        if (djLayout->getIsSelected()) {
            setsliceDeselectedAtIndex(newSelection);
        }
        else{
            setSliceSelectedAtIndex(newSelection);
        }
        
    }
}


void DJPieLayoutManager::setSliceSelectedAtIndex(int index)
{
    DJPieNodeLayout* djLayout = _djPieNodeLayoutVec.at(index);
    djLayout->setSliceSelectedAtIndex(index);
}

void DJPieLayoutManager::setsliceDeselectedAtIndex(int index)
{
    DJPieNodeLayout* djLayout = _djPieNodeLayoutVec.at(index);
    djLayout->setsliceDeselectedAtIndex(index);
}




DJPieRotateLayerManager.h旋转控制类

//
//  DJPieRotateLayerManager.h
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#ifndef __TestUI__DJPieRotateLayerManager__
#define __TestUI__DJPieRotateLayerManager__





class DJPieRotateLayerManager;

class DJPieRotateLayerManagerDelegate
{
public:
    
    virtual void selectedFinish(DJPieRotateLayerManager* djpieChartLayer , int index ,bool canLayerOpen) = 0;
    
};

#include "cocos2d.h"
#include "DJPieLayoutManager.h"

USING_NS_CC;

class DJPieRotateLayerManager:public Layer {
    
public:
    CREATE_FUNC(DJPieRotateLayerManager);
    
    
    DJPieRotateLayerManagerDelegate* delegate;
    
    
    
    
    virtual bool init();
    Size winSize;
    DJPieLayoutManager* djLayout;
    
    
    float mAbsoluteTheta;
    float        mRelativeTheta;
    
    float m_beforeDegrees;   //上次触摸的角度
    float m_currentDegrees;  //当前触摸的角度
    bool m_IstouchStart;    //判断是开始触摸还是触摸中
    float offsetDegrees;
    
    float m_beforeTime;
    float m_currentTime;
    std::vector<Color4B> colorVec;
    std::vector<float> angleVec;
    std::vector<float> endAngleVec; //记录每个扇形结束的角度
    
    
    float mDragBeforeDate;  //上次触摸的时间
    
    void  pieRotationEnd();
    
    double getPieRotation(double rotation);  //换算饼图的角度 使其在360至 - 360之间
    
    void setSliceSelectedAtIndex(int index);
     void tapStopped();
    void addPieLayour();
    
    
private:
    
    
    std::vector<float> rotationAngleVec;
    
    bool canLayerOpen;  //是否有扇形展开
    
    int selectedIndex;  //选择的是第几个
    
    bool isTapStopped; 
    
    float mDragSpeed;  //速度
    
    void update(float delta);
    
    float touchStopTime;
    
    bool isAutoRotation;  
    
    int touchIndex();
    

   
    
};

#endif /* defined(__TestUI__DJPieRotateLayerManager__) */

DJPieRotateLayerManager.cpp

//
//  DJPieRotateLayerManager.cpp
//  TestUI
//
//  Created by 杜甲 on 14-5-12.
//
//

#include "DJPieRotateLayerManager.h"
#include "VisibleRect.h"
#include <string.h>
#include <stdio.h>
#include "stdlib.h"
#define K_EPSINON        (1e-127)
#define IS_ZERO_FLOAT(X) (X < K_EPSINON && X > -K_EPSINON)

#define K_FRICTION              6.0f   // 摩擦系数
#define K_MAX_SPEED             12.0f
#define K_POINTER_ANGLE         (M_PI / 2)

bool DJPieRotateLayerManager::init()
{
    bool bRet = false;
    do {
        CC_BREAK_IF(!Layer::init());
        
        
        selectedIndex = -1;
        canLayerOpen = false;
        isTapStopped = false;
        isAutoRotation  = false;
        
        mDragSpeed = 0;
        
        
        
        
        
        
        
        
       
        
        auto listener1 = EventListenerTouchOneByOne::create();
        listener1->setSwallowTouches(true);
        
        
        listener1->onTouchBegan = [=](cocos2d::Touch *touch, cocos2d::Event *unused_event)
        {
            
            
            isTapStopped = IS_ZERO_FLOAT(mDragSpeed);
            
            
            
            
            
            Point location = this->convertTouchToNodeSpace(touch);
           // log("location.x = %f,location.y = %f",location.x,location.y);
            Point locationParent =  this->getParent()->convertTouchToNodeSpace(touch);
           // log("locationParent.x = %f,locationParent.y = %f",locationParent.x,locationParent.y);
            
            Point piePoint = djLayout->getPosition();//Point(300, 400);
            Point normalized = (piePoint - location).normalize();
            
            float angleRadians = atan2(normalized.y, -normalized.x);
            float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
            
            m_beforeDegrees = angleDegrees;
           
            
            
            
            m_IstouchStart = true;
            
            return true;
            
        };
        listener1->onTouchMoved = [ = ](cocos2d::Touch *touch, cocos2d::Event *unused_event)
        {
            
            
            if (canLayerOpen) {
                djLayout->pieSelected(selectedIndex);
                canLayerOpen = false;
            }
            
            
            Point location = this->convertTouchToNodeSpace(touch);
            
            Point piePoint =  djLayout->getPosition();
            //Point(winSize.width /2, winSize.height / 2);
            Point normalized = (piePoint - location).normalize();
            
            double angleRadians = atan2(normalized.y, -normalized.x);
            
            double angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
            
            m_currentDegrees = angleDegrees;
            
            
            offsetDegrees = m_currentDegrees - m_beforeDegrees;
            
            
            double pieRotation = djLayout->getRotation() ;
            
             
            
            double degreesDiff = pieRotation + offsetDegrees;
            
            degreesDiff = getPieRotation(degreesDiff);
            
            
            djLayout->setRotation( degreesDiff);
            
            
            m_beforeDegrees = m_currentDegrees;
            
            mDragSpeed = (2* M_PI ) / fabs(touchStopTime);
            
            
        };
        
        listener1->onTouchEnded = [ = ](cocos2d::Touch *touch, cocos2d::Event *unused_event)
        {
            
            if (IS_ZERO_FLOAT(mDragSpeed)) {
                if (isTapStopped) {
                    tapStopped();
                    return ;
                }else{
                    
                }
            }
            
            
            
            mDragSpeed = 0;
            Point location = this->convertTouchToNodeSpace(touch);
            
            Point piePoint = djLayout->getPosition();//Point(winSize.width /2, winSize.height / 2);
            Point normalized = (piePoint - location).normalize();
            
            float angleRadians = atan2(normalized.y, -normalized.x);
            float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
            
            m_currentDegrees = angleDegrees;
            
            
            offsetDegrees = m_currentDegrees - m_beforeDegrees;
            
            
            
            float degreesDiff = offsetDegrees * mDragSpeed;
            
            // _djPieRenderLayer->setRotation(angleDegrees);
            isAutoRotation = true;//转动开始
            CallFunc* callc = CallFunc::create(CC_CALLBACK_0(DJPieRotateLayerManager::pieRotationEnd, this));
            RotateBy* rb = RotateBy::create(0.2f, degreesDiff);
            Sequence* seq = Sequence::create(rb,callc, NULL);
            
            djLayout->runAction(seq);
            
        };
        
        
        
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
        
        
      
        
        scheduleUpdate();
        
        bRet = true;
    } while (0);
    return bRet;
}


void DJPieRotateLayerManager::addPieLayour()
{
    winSize = VisibleRect::getVisibleRect().size;
    
    djLayout = DJPieLayoutManager::create();
    djLayout->angleVec = angleVec;
    djLayout->colorVec = colorVec;
    djLayout->addPieLayout();
    
    djLayout->setPosition(Point(300, 400));
    addChild(djLayout);
    //djLayout->setRotation((60 - 50) / 2 + 15);
    //djLayout->setRotation(  angleVec.at(5) + angleVec.at(4) + angleVec.at(0) + angleVec.at(1) + 15);
    log("djLayout->getRotation(); = %f",djLayout->getRotation());
    
    float angleSum = 0;
    std::vector<float>::iterator it;
    for (it = angleVec.begin(); it != angleVec.end(); it++) {
        angleSum += *it;
        endAngleVec.push_back(angleSum);
        
    }
    
    
    angleSum = 0;
    for (int i = (int)angleVec.size() - 1; i >=0; i--)
    {
        
        angleSum += angleVec.at(i);
        log("angleSum %d = %f",i,angleSum);
        rotationAngleVec.push_back(angleSum);
    }
    

}



void DJPieRotateLayerManager::update(float delta)
{
    touchStopTime += delta;
}


double DJPieRotateLayerManager::getPieRotation(double rotation)
{
    if (rotation >= 360 || rotation <= -360) {
        
        
        
        
      const  char* rc = StringUtils::format("%f",rotation / 360.0).c_str();
        char tempRc[] = {0};
        sprintf(tempRc, rc);
        
        char* num = strtok(tempRc, ".");
        
        int rn = atoi(num);
        
        
        //log("%s",num);
        rotation -= rn * 360;
        
    }
    return rotation;
}


void DJPieRotateLayerManager::pieRotationEnd()
{
    float djRotation =djLayout->getRotation();
    //log("djRotationAAAA = %f",djRotation);
    //djRotation = djLayout->getRotation() + angleVec.at(0) ;//+ (90 - angleVec.at(0)) / 2;
    djRotation = getPieRotation(djRotation);
    if (djRotation < 0) {
        djRotation =360 + djRotation;
    }
    djRotation = djRotation - 90 + (90 - endAngleVec.at(0)) / 2 - 90;


   
    
    if (djRotation < 0) {
        djRotation =360 + djRotation;
    }
    
    
    
    
    log("djRotation = %f",djRotation);
//    djLayout->setRotation(90 + (90-angleVec.at(0)) / 2 + angleVec.at(0)  + angleVec.at(1) / 2) ;
    int selIndex = 0;
    
    float currentIndexEndAngle = 0;
    for (; selIndex < rotationAngleVec.size(); selIndex++) {
        
        if (djRotation < rotationAngleVec.at(selIndex)) {
            
            currentIndexEndAngle = rotationAngleVec.at(selIndex);
            break;
        }
    }
    
    
    
    selIndex = (int)rotationAngleVec.size() - 1 - selIndex;
    
    /***********************暂时修改*/
    //    float destinationAngle = currentIndexEndAngle + angleVec.at(selIndex)/2;
    float destinationAngle = currentIndexEndAngle - angleVec.at(selIndex)/2;
    djRotation =  destinationAngle - djRotation;
        
   
    CallFunc* callfc = CallFunc::create(CC_CALLBACK_0(DJPieRotateLayerManager::setSliceSelectedAtIndex, this,selIndex));
    RotateBy* rb = RotateBy::create(0.2f, djRotation);
    Sequence* seq = Sequence::create(rb,callfc, NULL);
    djLayout->runAction(seq);
    selectedIndex = selIndex;
    
   
   
    
    
}


void DJPieRotateLayerManager::setSliceSelectedAtIndex(int index)
{
    //选择哪个扇形
    canLayerOpen = true;
    
    djLayout->pieSelected(index);
    mDragSpeed = 0;
     isAutoRotation = false;
    
    if (delegate != nullptr) {
        delegate->selectedFinish(this, index,canLayerOpen);
        
    }
}


void DJPieRotateLayerManager::tapStopped()
{
    int tapAreaIndex = touchIndex();
    log("tapAreaIndex = %d,selectedIndex = %d",tapAreaIndex,selectedIndex);
    
    djLayout->pieSelected(tapAreaIndex);
    
    if (tapAreaIndex != selectedIndex) {
        //if (canLayerOpen) {
        
        selectedIndex = tapAreaIndex;
            canLayerOpen = true;
       // }

    }else{
        canLayerOpen = false;
    }
    
    
    
    
    if (delegate != nullptr) {
        delegate->selectedFinish(this, tapAreaIndex,canLayerOpen);
        
    }
    
}

int DJPieRotateLayerManager::touchIndex()
{
    int selIndex = 0;
  // m_beforeDegrees = m_beforeDegrees + angleVec.at(0) + (90 - angleVec.at(0)) / 2 + djLayout->getRotation();
    m_beforeDegrees = m_beforeDegrees -  djLayout->getRotation() + angleVec.at(0) + (90 - angleVec.at(0)) / 2;
    
   // log("m_beforeDegrees = %f",m_beforeDegrees);
    
    m_beforeDegrees = getPieRotation(m_beforeDegrees);
    if (m_beforeDegrees < 0) {
        m_beforeDegrees =360 + m_beforeDegrees;
    }
    
    
    
    float currentIndexEndAngle = 0;
    for (; selIndex < angleVec.size(); selIndex++) {
        if (m_beforeDegrees < endAngleVec.at(selIndex)) {
            currentIndexEndAngle = endAngleVec.at(selIndex);
            break;
        }
    }
    
    
    /******************************************************************************************/
    float destinationAngle = 0 ;
    
        destinationAngle = 90+    angleVec.at(0)   +  (90- angleVec.at(0))/2 ;

        destinationAngle =   destinationAngle  - currentIndexEndAngle  + angleVec.at(selIndex) / 2;
    
    
    //selectedIndex = selIndex;

    
    CallFunc* callfc = CallFunc::create(CC_CALLBACK_0(DJPieRotateLayerManager::setSliceSelectedAtIndex, this,selIndex));
    
      RotateTo* rb = RotateTo::create(0.2f,destinationAngle );
    
    Sequence* seq = Sequence::create(rb,callfc, NULL);
    djLayout->runAction(rb);
//
    log("selIndexAA = %d",selIndex);
    
    
    return selIndex;
}



原文地址http://write.blog.csdn.net/postedit/25867133