限定pan手势只能在圆内移动view

效果:

虽然看起来很简单,但实现原理还是稍微有点复杂-_-!!

核心的地方,就是需要计算pan手势的点与指定点的距离,不能超过这个距离,超过了就让动画还原,很容易理解:)

//
//  RootViewController.m
//  Circle
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"

@interface RootViewController ()

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 限定范围用的layer
    CALayer *circleLayer        = [CALayer layer];
    circleLayer.frame           = (CGRect){CGPointZero, CGSizeMake(250, 250)};
    circleLayer.position        = self.view.center;
    circleLayer.cornerRadius    = 250/2.f;
    circleLayer.opacity         = 0.5f;
    circleLayer.backgroundColor = [UIColor orangeColor].CGColor;
    [self.view.layer addSublayer:circleLayer];

    // 移动手势
    UIPanGestureRecognizer *pan =         [[UIPanGestureRecognizer alloc] initWithTarget:self
                                                action:@selector(gestureEvent:)];

    //  用于移动用的view
    UIView *move = [[UIView alloc] initWithFrame:(CGRect){CGPointZero, CGSizeMake(50, 50)}];
    move.backgroundColor    = [UIColor cyanColor];
    move.center             = self.view.center;
    move.layer.cornerRadius = 50/2.f;
    [move addGestureRecognizer:pan];
    [self.view addSubview:move];
}

- (void)gestureEvent:(UIPanGestureRecognizer *)gesture
{
    // 获取手势坐标点
    CGPoint translation = [gesture translationInView:gesture.view];

    // 开始
    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        [UIView animateWithDuration:0.2 animations:^{
            gesture.view.backgroundColor = [UIColor redColor];
        }];
    }

    // 状态改变
    if (gesture.state == UIGestureRecognizerStateChanged)
    {
        gesture.view.center = CGPointMake(gesture.view.center.x + translation.x,
                                          gesture.view.center.y + translation.y);

        // 计算手势的点与指定坐标的距离
        CGPoint pointA    = gesture.view.center;
        CGPoint pointB    = self.view.center;
        CGFloat distanceX = pointA.x - pointB.x;
        CGFloat distanceY = pointA.y - pointB.y;
        CGFloat distance  = sqrt(distanceX*distanceX + distanceY*distanceY);

        // 当距离在125.f以内时的一些操作
        if (distance <= 125.f)
        {
            [gesture setTranslation:CGPointZero
                             inView:gesture.view];
        }
        else
        {
            // 先关闭手势(不允许用户继续与手势交互)
            gesture.enabled = NO;

            [UIView animateWithDuration:0.2f animations:^{
                gesture.view.center          = self.view.center;
                gesture.view.backgroundColor = [UIColor cyanColor];
            } completion:^(BOOL finished) {
                // 动画结束后再次开启手势
                gesture.enabled = YES;
            }];
        }
    }

    // 结束
    if (gesture.state == UIGestureRecognizerStateEnded)
    {
        [UIView animateWithDuration:0.2f animations:^{
            gesture.view.center = self.view.center;
            gesture.view.backgroundColor = [UIColor cyanColor];
        }];
    }
}

@end

核心代码处:

1. 计算坐标值

2. 距离超出指定范围的时候就必须要关闭pan手势并执行动画,动画结束后再开启pan手势,相当重要哦.

限定pan手势只能在圆内移动view

时间: 2024-08-29 17:01:34

限定pan手势只能在圆内移动view的相关文章

限定文本框只能输入数字实例代码

限定文本框只能输入数字实例代码:有时候文本框中可以输入的内容只能够限定为数字,比如邮编和电话号码等.实现此中效果的方法有多种,比较常用的比如有正则表达式方式,不过这里咱们不采用这个,下面介绍一下如何通过keyCode属性值实现此效果.代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content=&

如何检测一个圆在多个圆内?

问题定义: 存在多个半径相同的圆,和一个半径不同的圆,如何判断半径不同的圆完全在一群圆内.下图演示了几种情况,左边是完全在圆内,右边不是. 解决方法之一: 对于红圆在某个黑圆之内或者在所有黑圆之外等的特例情形,可以用简单的圆圆之间的几何判断算法得到结果,对于其余部分相交的一般情形,如果同时满足以下两个条件则红圆在黑圆内: 1. 红圆与所有黑圆的交点都在黑圆内: 2. 黑圆之间的交点如果在红圆内,则其也必然在黑圆内. 否则,红圆不在黑圆内.

PHP限制网页只能在微信内置浏览器中查看并显示

微信现在算是火了,围绕微信开发的应用也越来越多了,前段时间,自己公司需要,用PHP写了一个微信应用,为了防止自己辛苦写成的PHP应用被盗用,于是通过PHP做了限制,只能在微信自带的浏览器中才能打开本应用,一开始无头绪,后经多查证,总算把这功能弄出来了,现在把具体的代码分享给大家. 1 2 3 4 5 6 7 8 <?php $useragent = addslashes($_SERVER['HTTP_USER_AGENT']); if(strpos($useragent, 'MicroMesse

圆内,求离圆心最远的整数点 hiho一下第111周 Farthest Point

1 // 圆内,求离圆心最远的整数点 hiho一下第111周 Farthest Point 2 // 思路:直接暴力绝对T 3 // 先确定x范围,每个x范围内,离圆心最远的点一定是y轴两端的点.枚举x的范围,再比较y 4 // O(n) 5 6 #include <bits/stdc++.h> 7 using namespace std; 8 #define LL long long 9 const double inf = 123456789012345.0; 10 const LL MO

判断一个点是否在圆内

/* * 判断一个点是不是在圆内 *  *  */public class Demo { public static void main(String[] args) {  //提示用户定义圆形和半径  Scanner sc = new Scanner(System.in);  //请输入圆形坐标  System.out.println("请输入圆心坐标:");  double a1 = sc.nextDouble();  double a2 = sc.nextDouble();   

Problem E: 点在圆内吗?

Description 定义一个Point类和Circle类,用于判断给定的一系列的点是否在给定的圆内. 其中,Point类: 1.有2个成员x和y,分别为其横坐标和纵坐标:1个静态成员numOfPoints,用于计算生成的点的个数. 2.具有构造函数.析构函数和拷贝构造函数,具体格式输出根据样例自行判断. 3. 具有静态方法int getNumOfPoints(),用于返回numOfPoints的值. 4. 具有int getX()和int getY()方法,用于获取横坐标和纵坐标. Circ

圆内三角形统计

[题目描述] 在一个圆的圆周上有N(N <= 100)个点,用线段将它们彼此相连,任意三条线段在圆内都没有公共交点,询问这些线段能构成多少个顶点在圆内的三角形. [输入描述] 输入一个正整数N. [输出描述] 输出一个数表示答案. [样例输入] 6 [样例输出] 1

计算Pan手势到指定点的角度

计算Pan手势到指定点的角度 效果图: 源码: // // RootViewController.m // Circle // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "Radian.h" #import "FrameAccessor.h" @interface RootViewController ()

CODEVS1056 圆内三角形统计(大水题!!!)

题目描述:圆周上有N(N<=100)个点,用线段将它们彼此相连.这些线段中任意三条在圆内都没有公共交点,问这些线段能构成多少个顶点在圆内的三角形? 思路:坑死我吧!!!我苦心孤诣,刻苦钻研了半个小时...结果就是一个简单的c(6,n)...每一个园内三角形的三边都是圆上不同的点,所以就是从n个点钟取6个的组合数... 之所以写这道题,是因为这种简单而又神奇的思路能解决好多问题...看来我要好好学习了!!! code: #include<iostream> #include<cstd