opencv实战项目 手势识别-手势控制鼠标

这篇具有很好参考价值的文章主要介绍了opencv实战项目 手势识别-手势控制鼠标。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

手势识别系列文章目录

手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。

1.  opencv实现手部追踪(定位手部关键点)

2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用)

3.手势识别-手势音量控制(opencv)

4.opencv实战项目 手势识别-手势控制鼠标

未完待续

本专栏记录作者的学习之旅会一直更新下去,欢迎订阅一起学习进步


本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等

opencv实战项目 手势识别-手势控制鼠标,opencv实战,opencv,人工智能,计算机视觉

 

代码需要用到opencv   HandTraqckModule模块   mediapipe模块和一个鼠标控制模块autopy


一、HandTraqckModule模块 

前面的文章中有封装手部检测模块的教程,这边简单的介绍一下

import cv2
import mediapipe as mp
import time

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):
        """
        初始化手势检测器对象。

        Args:
            mode (bool): 是否检测多只手。默认为False,只检测单只手。
            maxHands (int): 最多检测的手的数量。默认为2。
            detectionCon (float): 手势检测的置信度阈值。默认为0.5。
            trackCon (float): 手势跟踪的置信度阈值。默认为0.5。
        """
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        # 创建 Mediapipe Hands 模块和绘制工具对象
        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
                                       self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        """
        检测手势并在图像上绘制关键点和连接线。

        Args:
            img (numpy.ndarray): 输入图像。
            draw (bool): 是否在图像上绘制标记。默认为True。

        Returns:
            numpy.ndarray: 绘制了关键点和连接线的图像。
        """
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        
        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                                               self.mpHands.HAND_CONNECTIONS)
        return img

 

这是第一个小模块,用于创建手势检测器对象以及进行手势检测并在图像上绘制关键点和连接线。下面是对第一个小模块的详细解释:

  1. handDetector 类:定义了手势检测器对象,它具有以下初始化参数和方法。

    • __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):初始化函数,创建手势检测器对象并设置相关参数。

      • mode:是否检测多只手,默认为False。
      • maxHands:最多检测的手的数量,默认为2。
      • detectionCon:手势检测的置信度阈值,默认为0.5。
      • trackCon:手势跟踪的置信度阈值,默认为0.5。
    • findHands(self, img, draw=True):检测手势并在图像上绘制关键点和连接线。

      • img:输入图像(numpy数组)。
      • draw:是否在图像上绘制标记,默认为True。
    • mpHands:Mediapipe Hands 模块。

    • hands:Hand 模型,用于手势检测。

    • mpDraw:Mediapipe 绘制工具。

    • tipIds:手指末端关键点的ID列表。

  2. findHands 方法:接收输入图像,检测手势,并在图像上绘制关键点和连接线。

    • img:输入图像(numpy数组)。
    • draw:是否在图像上绘制标记,默认为True。
  3. imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB):将BGR格式的图像转换为RGB格式,以便Mediapipe处理。

  4. self.results = self.hands.process(imgRGB):使用Mediapipe Hand模型处理图像,得到手势检测结果。

  5. if self.results.multi_hand_landmarks::如果检测到多只手。

  6. for handLms in self.results.multi_hand_landmarks::遍历每只检测到的手。

  7. self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS):在图像上绘制手势关键点和连接线。

  8. 返回绘制了关键点和连接线的图像。

    def findPosition(self, img, handNo=0, draw=True):
        """
        获取手指关键点位置和包围框。

        Args:
            img (numpy.ndarray): 输入图像。
            handNo (int): 指定要分析的手的索引。默认为0,即第一只手。
            draw (bool): 是否在图像上绘制标记。默认为True。

        Returns:
            list: 手指关键点列表。
            tuple: 包围框坐标 (xmin, ymin, xmax, ymax)。
        """
        xList = []
        yList = []
        bbox = []
        self.lmList = []

        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(myHand.landmark):
                # 获取关键点在图像中的坐标
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                xList.append(cx)
                yList.append(cy)
                self.lmList.append([id, cx, cy])
                if draw:
                    # 在图像上绘制关键点
                    cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED)

            xmin, xmax = min(xList), max(xList)
            ymin, ymax = min(yList), max(yList)
            bbox = xmin, ymin, xmax, ymax

            if draw:
                # 在图像上绘制包围框
                cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20),
                              (0, 255, 0), 2)

        return self.lmList, bbox

 

这是第二个小模块,用于获取手指关键点位置和包围框。下面是对第二个小模块的详细解释:

  1. findPosition 方法:在图像上绘制手指关键点,并返回手指关键点的坐标列表以及手的包围框坐标。

    • img:输入图像(numpy数组)。
    • handNo:指定要分析的手的索引,默认为0,即第一只手。
    • draw:是否在图像上绘制标记,默认为True。
  2. xListyList:用于存储手指关键点的 x 和 y 坐标。

  3. bbox:包围框的坐标,用于确定手的位置。

  4. self.lmList:手指关键点的列表,格式为 [id, x, y]。

  5. myHand = self.results.multi_hand_landmarks[handNo]:获取指定索引的手势关键点信息。

  6. for id, lm in enumerate(myHand.landmark)::遍历手的关键点。

  7. h, w, c = img.shape:获取图像的高度、宽度和通道数。

  8. cx, cy = int(lm.x * w), int(lm.y * h):计算关键点在图像中的坐标。

  9. xList.append(cx)yList.append(cy):将坐标添加到列表中。

  10. self.lmList.append([id, cx, cy]):将关键点信息添加到关键点列表中。

  11. if draw::如果绘制标记为True。

  12. cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED):在图像上绘制关键点。

  13. xmin, xmax = min(xList), max(xList)ymin, ymax = min(yList), max(yList):计算包围框的坐标。

  14. bbox = xmin, ymin, xmax, ymax:设置包围框的坐标。

  15. cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20), (0, 255, 0), 2):在图像上绘制包围框。

  16. 返回手指关键点列表和包围框坐标。

    def fingersUp(self):
        """
        判断手指是否伸展。

        Returns:
            list: 包含每个手指的状态,1表示伸展,0表示弯曲。
        """
        fingers = []

        # 判断拇指是否伸展
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # 判断其他手指是否伸展
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

        return fingers

    def findDistance(self, p1, p2, img, draw=True, r=15, t=3):
        """
        计算两个关键点之间的距离。

        Args:
            p1 (int): 第一个关键点的索引。
            p2 (int): 第二个关键点的索引。
            img (numpy.ndarray): 输入图像。
            draw (bool): 是否在图像上绘制标记。默认为True。
            r (int): 圆的半径,用于标记关键点。默认为15。
            t (int): 绘制线条的粗细。默认为3。

        Returns:
            float: 两个关键点之间的距离。
            numpy.ndarray: 绘制了距离标记的图像。
            list: 包含关键点坐标的列表 [x1, y1, x2, y2, cx, cy]。
        """
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            # 在图像上绘制线条和关键点
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
        
        # 计算两个关键点之间的距离
        length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]

 

这是第三个小模块,用于判断手指是否伸展以及计算两个关键点之间的距离。下面是对第三个小模块的详细解释:

  1. fingersUp 方法:判断每个手指是否伸展,返回包含手指状态的列表。

    • 返回值:包含每个手指状态的列表,1表示伸展,0表示弯曲。
  2. findDistance 方法:计算两个关键点之间的距离,并在图像上绘制标记。

    • p1p2:两个关键点的索引。
    • img:输入图像(numpy数组)。
    • draw:是否在图像上绘制标记,默认为True。
    • r:圆的半径,用于标记关键点,默认为15。
    • t:绘制线条的粗细,默认为3。
  3. x1, y1 = self.lmList[p1][1:]x2, y2 = self.lmList[p2][1:]:获取两个关键点的坐标。

  4. cx, cy = (x1 + x2) // 2, (y1 + y2) // 2:计算两个关键点的中心坐标。

  5. if draw::如果绘制标记为True。

  6. cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t):在图像上绘制连接两个关键点的线条。

  7. cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED):在两个关键点处绘制实心圆圈,用于标记关键点。

  8. cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED):在关键点中心绘制实心圆圈,用于标记距离的中心。

  9. length = math.hypot(x2 - x1, y2 - y1):使用勾股定理计算两个关键点之间的距离。

  10. 返回值:返回计算的距离、绘制了标记的图像和包含关键点坐标的列表 [x1, y1, x2, y2, cx, cy]。

 

完整代码

"""
Hand Tracking Module

"""

import cv2
import mediapipe as mp
import time
import math
import numpy as np

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
        self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        # print(results.multi_hand_landmarks)

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                    self.mpHands.HAND_CONNECTIONS)

        return img

    def findPosition(self, img, handNo=0, draw=True):
        xList = []
        yList = []
        bbox = []
        self.lmList = []
        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(myHand.landmark):
                # print(id, lm)
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                xList.append(cx)
                yList.append(cy)
                # print(id, cx, cy)
                self.lmList.append([id, cx, cy])
                if draw:
                    cv2.circle(img, (cx, cy), 5, (255, 0, 255), cv2.FILLED)

        xmin, xmax = min(xList), max(xList)
        ymin, ymax = min(yList), max(yList)
        bbox = xmin, ymin, xmax, ymax

        if draw:
            cv2.rectangle(img, (xmin - 20, ymin - 20), (xmax + 20, ymax + 20),
            (0, 255, 0), 2)

        return self.lmList, bbox

    def fingersUp(self):
        fingers = []
        # Thumb
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # Fingers
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

            # totalFingers = fingers.count(1)

        return fingers

    def findDistance(self, p1, p2, img, draw=True,r=15, t=3):
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
            length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]

def main():
    pTime = 0
    cTime = 0
    cap = cv2.VideoCapture(1)
    detector = handDetector()
    while True:
        success, img = cap.read()
        img = detector.findHands(img)
        lmList, bbox = detector.findPosition(img)
        if len(lmList) != 0:
            print(lmList[4])

        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime

        cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
        (255, 0, 255), 3)

        cv2.imshow("Image", img)
        cv2.waitKey(1)

if __name__ == "__main__":
    main()

 

二、主代码

import cv2
import numpy as np
import HandTrackingModule as htm
import time
import autopy

##########################
wCam, hCam = 640, 480
frameR = 100  # Frame Reduction
smoothening = 7
#########################

pTime = 0
plocX, plocY = 0, 0
clocX, clocY = 0, 0

cap = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)
detector = htm.handDetector(maxHands=1)
wScr, hScr = autopy.screen.size()
# print(wScr, hScr)

while True:
    # 1. Find hand Landmarks
    success, img = cap.read()
    img = detector.findHands(img)
    lmList, bbox = detector.findPosition(img)
    # 2. Get the tip of the index and middle fingers
    if len(lmList) != 0:
        x1, y1 = lmList[8][1:]
        x2, y2 = lmList[12][1:]
        # print(x1, y1, x2, y2)

    # 3. Check which fingers are up
    fingers = detector.fingersUp()
    # print(fingers)
    cv2.rectangle(img, (frameR, frameR), (wCam - frameR, hCam - frameR),
                  (255, 0, 255), 2)
    # 4. Only Index Finger : Moving Mode
    if fingers[1] == 1 and fingers[2] == 0:
        # 5. Convert Coordinates
        x3 = np.interp(x1, (frameR, wCam - frameR), (0, wScr))
        y3 = np.interp(y1, (frameR, hCam - frameR), (0, hScr))
        # 6. Smoothen Values
        clocX = plocX + (x3 - plocX) / smoothening
        clocY = plocY + (y3 - plocY) / smoothening

        # 7. Move Mouse
        autopy.mouse.move(wScr - clocX, clocY)
        cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
        plocX, plocY = clocX, clocY

    # 8. Both Index and middle fingers are up : Clicking Mode
    if fingers[1] == 1 and fingers[2] == 1:
        # 9. Find distance between fingers
        length, img, lineInfo = detector.findDistance(8, 12, img)
        print(length)
        # 10. Click mouse if distance short
        if length < 40:
            cv2.circle(img, (lineInfo[4], lineInfo[5]),
                       15, (0, 255, 0), cv2.FILLED)
            autopy.mouse.click()

    # 11. Frame Rate
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (20, 50), cv2.FONT_HERSHEY_PLAIN, 3,
                (255, 0, 0), 3)
    # 12. Display
    cv2.imshow("Image", img)
    cv2.waitKey(1)

 

下面是代码的主要功能和操作步骤的解释:

  1. 导入所需的库和模块(cv2numpyHandTrackingModuletimeautopy)以及一些配置参数。

  2. 创建摄像头对象 cap,设置摄像头的宽度和高度为 wCamhCam

  3. 创建一个 handDetector 对象 detector,用于检测手势。在这里,我们只使用一个手,所以设置 maxHands=1

  4. 获取屏幕的宽度和高度,以便后面的坐标转换。

  5. 进入一个无限循环,不断处理视频帧。

  6. 在循环中,首先从摄像头获取一帧图像,并调用 detector.findHands 方法来检测手势。然后,调用 detector.findPosition 方法获取手势的关键点坐标和边界框。

  7. 根据检测到的手势关键点,判断手指的状态(是否抬起)。

  8. 绘制一个矩形框作为活动区域,用于移动鼠标。

  9. 当食指抬起而中指不抬起时,进入移动模式。将手势坐标转换为屏幕上的坐标,然后进行平滑处理,最后使用 autopy.mouse.move 方法移动鼠标。

  10. 绘制一个实心圆表示食指的位置,并更新上一次的位置。

  11. 当食指和中指同时抬起时,进入点击模式。计算食指和中指之间的距离,如果距离小于阈值,执行鼠标点击操作。

  12. 计算并显示帧率。

  13. 将处理后的图像显示在窗口中,按下任意键退出循环。

利用摄像头捕获的图像,检测手势,然后根据手指状态来模拟鼠标操作。移动模式下,用食指位置移动鼠标;点击模式下,用食指和中指之间的距离来模拟鼠标点击。这样可以实现通过手势来控制鼠标的功能。

opencv实战项目 手势识别-手势控制鼠标,opencv实战,opencv,人工智能,计算机视觉

 

需要注意的是,运行代码前,需要将食指放在摄像头前。否则会报错

遇到其他错误,可以评论区留言,大家一起解决

  文章来源地址https://www.toymoban.com/news/detail-643079.html

到了这里,关于opencv实战项目 手势识别-手势控制鼠标的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手势识别-手势音量控制(opencv)

     本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 手势识别系列文章 1.opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.手势识别-手势音量控制(open

    2024年02月13日
    浏览(39)
  • 基于mediapipe和opencv的手势控制电脑鼠标

    通过我的上一篇文章,可以了解到mediapipe关于手部检测的使用方法。这时我们就可以进行一些更加炫酷的操作。这篇文章我就来讲解一下如何用手势来控制电脑鼠标。 在开始之前我们要介绍一个能够操作电脑鼠标的库pyautogui,这里我简单介绍一下该库的一些函数,方便大家观

    2024年02月07日
    浏览(29)
  • 基于ESP32-CAM 和 OpenCV 设计的手势控制虚拟鼠标

    概述 在本文中,我们将使用 ESP32-CAM 和 OpenCV开发 手势控制虚拟鼠标 。ESP32  Camera Module 和 Python 程序可用于无线控制 鼠标跟踪 和 点击 操作。 入门者必须具备 Python、 图像处理 、嵌入式系统以及物联网的丰富知识。首先,我们将了解如何控制鼠标跟踪和单击,以及运行 pyt

    2024年02月09日
    浏览(39)
  • OpenCV C++案例实战二十二《手势识别》

    本文将使用OpenCV C++ 实现手势识别效果。本案例主要可以分为以下几个步骤: 1、手部关键点检测 2、手势识别 3、效果显示 接

    2024年02月05日
    浏览(71)
  • OpenCV+python实现摄像头简单手势识别--进度条控制亮度

    例如:随着人工智能的不断发展,计算机视觉这门技术也越来越重要,很多人都开启了学习计算机视觉,本文在Opencv基础上实现了摄像头简单手势识别–进度条控制亮度的基础内容,并没有使用深度学习技术,因此准确率并不高。 ∙ bullet ∙ 第一步: 开启摄像头,检测每帧图

    2023年04月08日
    浏览(35)
  • OpenCV项目开发实战--基于Python/C++实现鼠标注释图像和轨迹栏来控制图像大小

    鼠标指针是图形用户界面 (GUI) 中的关键组件。没有它,您就无法真正考虑与 GUI 进行交互。那么,让我们深入了解 OpenCV 中鼠标和轨迹栏的内置函数。我们将演示如何使用鼠标来注释图像,以及如何使用轨迹栏来控制图像的大小 我们将使用下图来演示 OpenCV 中鼠标指针和轨迹

    2024年02月11日
    浏览(36)
  • 课程设计——基于opencv的手势识别【真】完整项目

    一个简单的手势识别,过程很简单,主要用到了 opencv 和 sklearn 和 tkinter 三个库,下面我将会展示整个项目的代码和简要说明,并且 下面将会是完整的已经全部集成在三个 .py 文件的代码,你只需要将三个文件分别执行就可以训练出自己的手势识别模型 项目思想: 通过颜色寻

    2024年02月04日
    浏览(31)
  • 基于Python+OpenCV的手势识别系统:智能家居和智能小车的灯光控制

    基于python+opencv的手势识别系统,可控制灯的亮度,智能家居,智能小车。 基于python+opencv的手势识别系统软件。 内含svm模型,和肤色识别,锐化处理。 基于 win10+Python3.7的环境,利用Python的OpenCV、Sklearn和PyQt5等库搭建了一个较为完整的手势识别系统,用于识别日常生活中1-1

    2024年04月15日
    浏览(34)
  • 竞赛项目 深度学习手势识别算法实现 - opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习手势识别算法实现 - opencv python 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/

    2024年02月13日
    浏览(62)
  • [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互

    @ 目录 原理 交互实现 容器控件 手势开始 手势运行 手势结束 使用控件 拖拽物 创建pit集合 项目地址 定义一个拖拽物,和它拖拽的目标,拖拽物可以理解为一个平底锅(pan),拖拽目标是一个坑(pit),当拖拽物进入坑时,拖拽物就会被吸附在坑里。可以脑补一下下图: 你

    2023年04月08日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包