cocos2dx3.x 类似 coverflow效果

来源:互联网 发布:淘宝儿童摇摆车扭扭车 编辑:程序博客网 时间:2024/05/23 18:33

更新:

1.改成3.x

2.增加移动完成回调函数

3.增加水平和竖直分辨(直接在原来的上面改的,懒得动)

h文件:

#ifndef __CoverView_H__#define __CoverView_H__#include "cocos2d.h"#include "cocos-ext.h"USING_NS_CC;using namespace extension;class CoverView : public Node, public extension::ScrollViewDelegate{public:CoverView();~CoverView();/**** @param scrollView的rect* @param scrollView滚动size* @param card之间的距离* @param card之间的缩放*/static CoverView* create(Rect swBox, Size slSize, float disDistance, float disScale);virtual bool init(Rect swBox, Size slSize, float disDistance, float disScale);virtual void onEnter();virtual void onExit();bool onTouchBegan(Touch* touch, Event* event);void onTouchMoved(Touch* touch, Event* event);void onTouchEnded(Touch* touch, Event* event);void onTouchCancelled(Touch* touch, Event* event);void initData();void scrollViewDidScroll(extension::ScrollView* view);void scrollViewDidZoom(extension::ScrollView* view);void adjustCardScale(Point adjustPoint);void adjustScrollView(Point adjustPoint);void adjusetEndScrollView();void cardViewEnd_callBack(Node* pSender);int getCurCardIndex();//当前中间card索引 从0开始void addCard(Node * card);void addCard(Node * card, int zOrder);void addCard(Node* card, int zOrder, int tag);Node* getCardByIndex(int index);void startMiddleIndex(int index);CC_SYNTHESIZE(Point, swPosition, SwPosition);//scrollView 位置CC_SYNTHESIZE(Size, swSize, SwSize);//scrollView大小CC_SYNTHESIZE(Size, slSize, SlSize);//scrollLayer 大小CC_SYNTHESIZE(float, disDistance, DisDistance);//card距离间隔CC_SYNTHESIZE(float, disScale, DisScale);//crad缩放间隔CC_SYNTHESIZE(Rect, swBox, SwBox);//scrollview 边框CC_SYNTHESIZE(Layer*, scrollLayer, scrollLayer);//scrollView的containLayerCC_SYNTHESIZE(int, cardNum, CardNum);//card索引CC_PROPERTY(Point, offsetPosition, OffsetPosition);//card起始位置CC_SYNTHESIZE(Point, slayerPosition, SlayerPosition);//sontainLayer的位置CC_SYNTHESIZE(bool, isMove, IsMove);//是否发生了移动用于加入Menu的时候能滑动并正确响应事件CC_SYNTHESIZE(bool, isHorizontal, IsHorizontal);//是水平还是数值CC_SYNTHESIZE(bool, isIgnoreScale, IsIgnoreScale);public:std::function<void(Node* card , int selIndex)> selCallBack;std::function<void()>startCallBack;private:Size wSize;std::vector<Node*> cardArray;extension::ScrollView* scrollView;};#endif


.cpp文件

#include "CoverView.h"CoverView::CoverView(){}CoverView::~CoverView(){    //CC_SAFE_RELEASE_NULL(cardArray);}CoverView* CoverView::create(Rect swBox, Size slSize, float disDistance, float disScale){    CoverView* cover = new CoverView();    if (cover && cover->init(swBox, slSize, disDistance, disScale))    {        cover->autorelease();        return cover;    }    CC_SAFE_DELETE(cover);    return NULL;}bool CoverView::init(Rect swBox, Size slSize, float disDistance, float disScale){    if (!Node::init()) return false;    this->swBox = swBox;    this->swPosition = swBox.origin;    this->swSize = swBox.size;    this->slSize = slSize;    this->disDistance = disDistance;    this->disScale = disScale;    initData();    return true;}void CoverView::initData(){    wSize = Director::sharedDirector()->getWinSize();    cardNum = 0;    selCallBack = nullptr;    startCallBack = nullptr;    isIgnoreScale = abs(disScale) < 0.0001f;    offsetPosition = Vec2(swSize.width / 2, swSize.height / 2);    scrollLayer = Layer::create();    scrollLayer->setAnchorPoint(Vec2::ZERO);    scrollLayer->setPosition(Vec2::ZERO);    scrollLayer->setContentSize(slSize);    slayerPosition = Vec2::ZERO;    isMove = true;    isHorizontal = false;    scrollView = extension::ScrollView::create(swSize, scrollLayer);    scrollView->setAnchorPoint(Vec2::ZERO);    scrollView->setContentOffset(Vec2(0, 0));    scrollView->setTouchEnabled(false);    scrollView->setDelegate(this);    //scrollView->setClippingToBounds(false);    scrollView->setDirection(extension::ScrollView::Direction::VERTICAL);    addChild(scrollView, 1);}void CoverView::onEnter(){    Node::onEnter();    auto dispatcher = Director::getInstance()->getEventDispatcher();    auto listener = EventListenerTouchOneByOne::create();    listener->onTouchBegan = CC_CALLBACK_2(CoverView::onTouchBegan, this);    listener->onTouchMoved = CC_CALLBACK_2(CoverView::onTouchMoved, this);    listener->onTouchEnded = CC_CALLBACK_2(CoverView::onTouchEnded, this);    listener->onTouchCancelled = CC_CALLBACK_2(CoverView::onTouchCancelled, this);    listener->setSwallowTouches(true);    dispatcher->addEventListenerWithSceneGraphPriority(listener, this);}void CoverView::onExit(){    removeAllChildren();    Node::onExit();}bool CoverView::onTouchBegan(Touch* touch, Event* event){    auto target = static_cast<Node*>(event->getCurrentTarget());    // 获取当前点击点所在相对按钮的位置坐标    Point locationInNode = target->convertToNodeSpace(touch->getLocation());    if (swBox.containsPoint(locationInNode))    {        if(startCallBack)        {            startCallBack();        }        return true;    }    return false;}void CoverView::onTouchMoved(Touch* touch, Event* event){    Vec2 scroll_prepoint = touch->getPreviousLocation();    Vec2 scroll_movepoint = touch->getLocation();        // 获取事件所绑定的 target    auto target = static_cast<Node*>(event->getCurrentTarget());    // 获取当前点击点所在相对按钮的位置坐标    Point locationInNode = target->convertToNodeSpace(scroll_movepoint);    if (swBox.containsPoint(locationInNode))    {        Vec2 adjustPoint = scroll_movepoint - scroll_prepoint;        scrollLayer->stopAllActions();        adjustScrollView(adjustPoint);        adjustCardScale(adjustPoint);    }}void CoverView::onTouchEnded(Touch* touch, Event* event){    Vec2 scroll_prepoint = touch->getPreviousLocation();    Vec2 scroll_endpoint = touch->getLocation();    float disX = scroll_endpoint.x - scroll_endpoint.x;    scrollLayer->stopAllActions();    adjusetEndScrollView();    Vec2 curPosition = scrollLayer->getPosition();    float distance = slayerPosition.distance(curPosition);    if (distance < 5.0f) isMove = false;}void CoverView::onTouchCancelled(Touch* touch, Event* event){    onTouchEnded(touch, event);}void CoverView::adjustCardScale(Vec2 adjustPoint){    if (isIgnoreScale) return;    if(isHorizontal)    {        for(auto card : cardArray)        {            float offset = scrollView->getContentOffset().x;            float posX = card->getPositionX() + offset;            float disMid = abs(swSize.width / 2 - posX);            float scale = 1 - disMid / disDistance*disScale;            card->setScale(scale);            int zOr = (int)(1000 - disMid*0.1);            card->setZOrder(zOr);        }    }    else    {        for (auto card : cardArray)        {            float offset = scrollView->getContentOffset().y;            float posY = card->getPositionY() + offset;            float disMid = abs(swSize.height / 2 - posY);            float scale = 1 - disMid / disDistance*disScale;            card->setScale(scale);            int zOr = (int)(1000 - disMid*0.1);            card->setZOrder(zOr);        }    }    }void CoverView::adjustScrollView(Vec2 adjustPoint){    Vec2 endPoint = scrollView->getContentOffset()+ Vec2(0,adjustPoint.y);    if (isHorizontal) endPoint = scrollView->getContentOffset()+ Vec2(adjustPoint.x, 0);    scrollView->unscheduleAllSelectors();    scrollView->setContentOffset(endPoint, false);}void CoverView::adjusetEndScrollView(){    if(isHorizontal)    {        float minX = LONG_MAX;        float midX = swSize.width / 2;        //获取距离中间最小值的card          for (auto card : cardArray)        {            float offset = scrollView->getContentOffset().x;            //转化父类坐标              float posX = card->getPositionX() + offset;            float disMid = midX - posX;            if (abs(disMid) < abs(minX)) minX = disMid;        }        for (auto item : cardArray)        {            //转化父类坐标              float offset = scrollView->getContentOffset().x;            float posX = item->getPositionX() + offset;            //距离中间长度              float disMid = abs(midX - posX - minX);             if (isIgnoreScale == false)            {                //目标scale                  float scale = 1 - disMid / disDistance*disScale;                ScaleTo* scaleBy = ScaleTo::create(0.2f, scale);                item->runAction(scaleBy);            }            int zOr = (int)(1000 - disMid*0.1);            item->setZOrder(zOr);        }        Layer* scrollLayer = (Layer*)scrollView->getContainer();        MoveBy* moveBy = MoveBy::create(0.2f, Vec2(minX, 0));        CallFuncN* callFuncN = CallFuncN::create(this, callfuncN_selector(CoverView::cardViewEnd_callBack));        Sequence* seq = Sequence::create(moveBy, callFuncN, NULL);        scrollLayer->runAction(seq);        //scrollLayer->runAction(moveBy);      }    else    {        float minY = LONG_MAX;        float midY = swSize.height / 2;        //获取距离中间最小值的card        for (auto card : cardArray)        {            float offset = scrollView->getContentOffset().y;            //转化父类坐标            float posY = card->getPositionY() + offset;            float disMid = midY - posY;            if (abs(disMid) < abs(minY)) minY = disMid;        }        for (auto item : cardArray)        {            //转化父类坐标            float offset = scrollView->getContentOffset().y;            float posY = item->getPositionY() + offset;            //距离中间长度            float disMid = abs(midY - posY - minY);            if(isIgnoreScale == false)            {                //目标scale                float scale = 1 - disMid / disDistance*disScale;                ScaleTo* scaleBy = ScaleTo::create(0.2f, scale);                item->runAction(scaleBy);            }            int zOr = (int)(1000 - disMid*0.1);            item->setZOrder(zOr);        }        Layer* scrollLayer = (Layer*)scrollView->getContainer();        MoveBy* moveBy = MoveBy::create(0.2f, Vec2(0, minY));        //CallFuncN* callFuncN = CallFuncN::create(this, callfuncN_selector(CoverView::cardViewEnd_callBack));        CallFuncN* callFuncN = CallFuncN::create(std::bind(&CoverView::cardViewEnd_callBack, this, std::placeholders::_1));        Sequence* seq = Sequence::create(moveBy, callFuncN, NULL);        scrollLayer->runAction(seq);    }}void CoverView::cardViewEnd_callBack(Node* pSender){    //NotificationCenter::sharedNotificationCenter()->postNotification(ROOMSELECT,cardArray);    slayerPosition = scrollLayer->getPosition();    isMove = true;    if (selCallBack)    {        int index = getCurCardIndex();        selCallBack(getCardByIndex(index),index);    }}void CoverView::scrollViewDidScroll(extension::ScrollView* view){}void CoverView::scrollViewDidZoom(extension::ScrollView* view){}void CoverView::addCard(Node * card){    int zOrder = 1000 - cardNum;    this->addCard(card, zOrder, 0);}void CoverView::addCard(Node * card, int zOrder){    this->addCard(card, zOrder, 0);}void CoverView::addCard(Node* card, int zOrder, int tag){    if (card == nullptr) return;    if(isHorizontal)    {        float positionX = offsetPosition.x + disDistance*cardNum;        float scale = 1 - disScale*cardNum;        card->setPosition(Vec2(positionX, offsetPosition.y));        card->setScale(scale);        cardArray.push_back(card);        scrollLayer->addChild(card, zOrder, tag);        cardNum++;    }    else    {        float positionY = offsetPosition.y + disDistance*cardNum;        float scale = 1 - disScale*cardNum;        card->setPosition(Vec2(offsetPosition.x, positionY));        card->setScale(scale);        cardArray.push_back(card);        scrollLayer->addChild(card, zOrder, tag);        cardNum++;        //Log("crad%d:[%f , %f]",cardNum,card->getPositionX(),card->getPositionY());    }    }int CoverView::getCurCardIndex(){    if(isHorizontal)    {        float distance1 = -scrollLayer->getPositionX();        float distance2 = swSize.width / 2 - offsetPosition.x;        //+5 浮点数误差          int index = (distance1 + distance2 + 5) / (disDistance);        index = std::min((int)cardArray.size() - 1, index);        index = std::max(0, index);        return index;    }    else    {        float distance1 = -scrollLayer->getPositionY();        float distance2 = swSize.height / 2 - offsetPosition.y;        //+5 浮点数误差        int index = (distance1 + distance2 + 5) / (disDistance);        index = std::min((int)cardArray.size() - 1, index);        index = std::max(0, index);        return index;    }    return 0;}void CoverView::setOffsetPosition(Vec2 var){    if(isHorizontal)    {        offsetPosition = var;        cardNum = 0;        for (auto card : cardArray)        {            float positionX = offsetPosition.x + disDistance*cardNum;            card->setPosition(Vec2(positionX, offsetPosition.y));            cardNum++;        }        adjustCardScale(Vec2::ZERO);    }    else    {        offsetPosition = var;        cardNum = 0;        for (auto card : cardArray)        {            float positionY = offsetPosition.y + disDistance*cardNum;            card->setPosition(Vec2(offsetPosition.x, positionY));            cardNum++;        }        adjustCardScale(Vec2::ZERO);    }    }Vec2 CoverView::getOffsetPosition(){    return offsetPosition;}Node* CoverView::getCardByIndex(int index){    if (index<0 || index > cardArray.size() - 1) return nullptr;    return cardArray[index];}void CoverView::startMiddleIndex(int index){    int cardsCount = cardArray.size();    if (index<0 || index > cardsCount - 1) return;    auto newoffsetPosition = offsetPosition + Vec2(0,-disDistance*index);    if (isHorizontal) newoffsetPosition = offsetPosition + Vec2(-disDistance*index,0);    setOffsetPosition(newoffsetPosition);}


样例:

auto view = CoverView::create(Rect(0, 0, conSize.width, conSize.height),Size(conSize.width * 3, conSize.width), disSpace, 0.2f);view->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);container_polish->addChild(view);for (int i = 0; i < 12; i++){auto bottomSp = createSp("#meijia_xuankuang_2_6.png");view->addCard(bottomSp, 1, ++baseTag);}view->setIsHorizontal(true);view->startMiddleIndex(2);view->selCallBack = [&](Node* card ,int selIndex){log("card index:%d", selIndex);};

下载地址:coverflow效果

3 0