zoukankan      html  css  js  c++  java
  • 简单手势识别

    模拟iOS原生手势,简单实现点击(双击)、长按、滑动、拖动等功能。

    代码如下:

    //
    //  CGesture.h
    //  ActionLabel
    //
    //  Created by xujw on 16/3/15.
    
    /*  手势识别 仿iphone  简单长按 点击(双击等) 滑动 拖动等。
     *  使用方法:
     *  auto gesture = CGesture::createTapGesture(target,callback,taps);
     *  this->addChild(gestrue)
     */
    
    #ifndef CGesture_h
    #define CGesture_h
    
    #include <stdio.h>
    #include "cocos2d.h"
    USING_NS_CC;
    
    typedef enum gestureDirection
    {
        kDirectUp = 0,
        kDirectDown = 1,
        kDirectLeft = 2,
        kDirectRight = 3
    }GestureDirection;
    
    typedef std::function<void(Touch*)> GestureCallback;
    typedef std::function<void(Touch*,GestureDirection)> SwipeGestureCallback;
    
    #define SHAKE_LENGTH 100
    
    class CGesture:public Layer
    {
    private:
        bool _isCanTouch;
        int _tapNum;
    public:
        CGesture();
        ~CGesture();
        bool init();
        CREATE_FUNC(CGesture);
    public:
        //点击
        static CGesture* createTapGesture(Node*target,GestureCallback callback,int tapsRequired=1);
        //长按
        static CGesture* createLongPressGesture(Node*target,GestureCallback callback,float delay = 1.0f);
        //滑动
        static CGesture* createSwipeGesture(Node*target,SwipeGestureCallback callback);
        //拖动
        static CGesture* createPanGestrue(Node*target,GestureCallback callback);
    };
    #endif /* CGesture_h */
    
    //
    //  CGesture.cpp
    //  ActionLabel
    //
    //  Created by xujw on 16/3/15.
    //
    //
    
    #include "CGesture.h"
    #include <time.h>
    
    CGesture::CGesture()
    :_isCanTouch(false)
    ,_tapNum(0)
    {}
    CGesture::~CGesture()
    {}
    
    bool CGesture::init()
    {
        if (!Layer::init())
        {
            return false;
        }
    
        return true;
    }
    
    CGesture* CGesture::createTapGesture(Node*target,GestureCallback callback,int tapsRequired)
    {
        CCASSERT(callback && target, "callback or target is null");
    
        auto parent = target->getParent();
    
        auto gesture = CGesture::create();
    
        auto lis = EventListenerTouchOneByOne::create();
        lis->onTouchBegan = [=](Touch *touch,Event *event)
        {
            auto box = target->getBoundingBox();
            auto pos = touch->getLocation();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
            if (box.containsPoint(pos))
            {
                gesture->_tapNum ++;
            }
    
            return true;
        };
        lis->onTouchMoved = [=](Touch *touch,Event *event)
        {
            auto startPos = touch->getStartLocation();
            auto curPos = touch->getLocation();
            auto subPos = curPos - startPos;
            if (fabs(subPos.x)>=10 || fabs(subPos.y)>=10)
            {
                gesture->_tapNum = 0;
                gesture->unschedule("GestureTapNumReset");
            }        
        };
        lis->onTouchEnded = [=](Touch *touch,Event *event)
        {
            if (gesture->_tapNum >= tapsRequired)
            {
                auto box = target->getBoundingBox();
                auto pos = touch->getLocation();
                auto parent = target->getParent();
                if (parent) {
                    pos = parent->convertToNodeSpace(pos);
                }
                if (box.containsPoint(pos))
                {
                    gesture->_tapNum = 0;
                    gesture->unschedule("GestureTapNumReset");
                    callback(touch);
                }
            }
            gesture->scheduleOnce([=](float dt)
            {
                gesture->_tapNum = 0;
            }, 0.5, "GestureTapNumReset");
        };
    
        gesture->getEventDispatcher()->addEventListenerWithSceneGraphPriority(lis, target);
    
        return gesture;
    }
    
    CGesture* CGesture::createLongPressGesture(Node*target,GestureCallback callback,float delay)
    {
        CCASSERT(callback && target, "callback or target is null");
    
        auto parent = target->getParent();
    
        auto gesture = CGesture::create();
    
        auto lis = EventListenerTouchOneByOne::create();
        lis->onTouchBegan = [=](Touch *touch,Event *event)
        {
            auto box = target->getBoundingBox();
            auto pos = touch->getLocation();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
            if (box.containsPoint(pos))
            {
                gesture->scheduleOnce([=](float){
                    gesture->_isCanTouch = true;
                }, delay, "GestureChangeTouchState");
                return true;
            }
            else
            {
                return false;
            }
        };
        lis->onTouchMoved = [=](Touch *touch,Event *event)
        {
            //长按时滑动算取消
            auto startPos = touch->getStartLocation();
            auto curPos = touch->getLocation();
            auto subPos = curPos - startPos;
            if (fabs(subPos.x)>=10 || fabs(subPos.y)>=10)
            {
                gesture->unschedule("GestureChangeTouchState");
                gesture->_isCanTouch = false;
            }
        };
        lis->onTouchEnded = [=](Touch *touch,Event *event)
        {
            auto box = target->getBoundingBox();
            auto pos = touch->getLocation();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
    
            if (gesture->_isCanTouch)
            {
                if (box.containsPoint(pos))
                {
                    callback(touch);
                }
            }
            else
            {
                gesture->unschedule("GestureChangeTouchState");
            }
            gesture->_isCanTouch = false;
        };
    
        gesture->getEventDispatcher()->addEventListenerWithSceneGraphPriority(lis, target);
    
        return gesture;
    }
    
    CGesture* CGesture::createSwipeGesture(Node*target,SwipeGestureCallback callback)
    {
        CCASSERT(callback && target, "callback or target is null");
    
        auto parent = target->getParent();
        auto gesture = CGesture::create();
    
        auto lis = EventListenerTouchOneByOne::create();
        lis->onTouchBegan = [=](Touch *touch,Event *event)
        {
            auto pos = touch->getLocation();
            auto box = target->getBoundingBox();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
            if (box.containsPoint(pos))
            {
                gesture->_isCanTouch = true;
            }
            else{
                gesture->_isCanTouch = false;
            }
            return gesture->_isCanTouch;
        };
        lis->onTouchMoved = [=](Touch *touch,Event *event){};
        lis->onTouchEnded = [=](Touch *touch,Event *event)
        {
            auto pos = touch->getLocation();
            auto box = target->getBoundingBox();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
            //起始点都在target范围内才响应
            if (!gesture->_isCanTouch || !box.containsPoint(pos))
            {
                gesture->_isCanTouch = false;
                return ;
            }
    
            auto startPos = touch->getStartLocation();
            auto curPos = touch->getLocation();
            auto subPos = curPos - startPos;
    
            if (fabs(subPos.x) > fabs(subPos.y))
            {
                //左右移动
                if (subPos.x > SHAKE_LENGTH)
                {
                    //向右移动
                    callback(touch,kDirectRight);
                }
                else if (subPos.x < -SHAKE_LENGTH)
                {
                    //向左移动
                    callback(touch,kDirectLeft);
                }
            }
            else
            {
                if (subPos.y > SHAKE_LENGTH)
                {
                    //向上移动
                    callback(touch,kDirectUp);
                }
                else if (subPos.y < -SHAKE_LENGTH)
                {
                    //向下移动
                    callback(touch,kDirectDown);
                }
            }
        };
        gesture->getEventDispatcher()->addEventListenerWithSceneGraphPriority(lis, gesture);
        return gesture;
    }
    
    CGesture* CGesture::createPanGestrue(Node*target,GestureCallback callback)
    {
        CCASSERT(callback && target, "callback or target is null");
    
        auto parent = target->getParent();
    
        auto gesture = CGesture::create();
    
        auto lis = EventListenerTouchOneByOne::create();
        lis->onTouchBegan = [=](Touch *touch,Event *event)
        {
            auto box = target->getBoundingBox();
            auto pos = touch->getLocation();
            if (parent) {
                pos = parent->convertToNodeSpace(pos);
            }
            if (box.containsPoint(pos))
            {
                gesture->_isCanTouch = true;
            }
            return true;
        };
        lis->onTouchMoved = [=](Touch *touch,Event *event)
        {
            if (gesture->_isCanTouch)
            {
                callback(touch);
            }
        };
        lis->onTouchEnded = [=](Touch *touch,Event *event)
        {
            gesture->_isCanTouch = false;
        };
        gesture->getEventDispatcher()->addEventListenerWithSceneGraphPriority(lis, target);
        return gesture;
    }

    代码下载Git

  • 相关阅读:
    tableView//collectionView加载时的动画
    关于collectionView和tableView的两种cell的出列方法的区别
    缓存的实现,主要是图片缓存整理
    android context获取目录详解
    Android网络传输中必用的两个加密算法:MD5 和 RSA 及Base64加密总结
    listview 与 button 焦点 在item添加下列属性
    VScode 安装必备
    centos7 安装docker
    1290
    MySQL“Another MySQL daemon already running with the same unix socket” 报错信息处理
  • 原文地址:https://www.cnblogs.com/skyxu123/p/9543805.html
Copyright © 2011-2022 走看看