簡體   English   中英

如何繼續drawRect:當手指在屏幕上時

[英]How to continue to drawRect: when finger on screen

我有當前代碼:

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    self.objectPoint = [[touches anyObject] locationInView:self];
    float x, y;
    if (self.objectPoint.x > self.objectPoint.x) {
        x = self.objectPoint.x + 1;
    }
    else x = self.objectPoint.x - 1;
    if (self.fingerPoint.y > self.objectPoint.y) {
        y = self.objectPoint.y + 1;
    }
    else y = self.minionPoint.y - 1;
    self.objectPoint = CGPointMake(x, y);

    [self setNeedsDisplay];
}

我的問題是我要讓物體一直跟隨您的手指,直到您將手指從屏幕上移開。 如果我的手指在移動,它只會跟隨。 touchesEnded僅在我將手指從屏幕上touchesEnded時才有效,所以那也不是我想要的。 如何啟用可以解決我問題的功能?

如果您想觸摸屏幕的一部分,並且想要在不放開手指的情況下沿該方向移動繪制的對象,則有兩種方法。

進場方法是使用某種形式的計時器,這種方法會在用戶將手指按住在屏幕上時重復調用一種方法(因為,正如您所指出的,移動時您只會獲得touchesMoved更新)。 雖然NSTimer是您遇到的最常見的計時器,但在這種情況下,您需要使用一種稱為顯示鏈接的專用計時器,即CADisplayLink ,它可以在執行屏幕更新時觸發。 因此,您將:

  • touchesBegan ,捕獲用戶在屏幕上觸摸的位置並啟動CADisplayLink

  • touchesMoved ,您將更新用戶的觸摸位置(但只有在他們移動手指時才會調用);

  • touchesEnded ,您可能會停止顯示鏈接;

  • CADisplayLink處理程序中,您將更新位置(並且您需要知道其移動速度)。

因此,它看起來像:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.velocity = 100.0;     // 100 points per second
    self.touchLocation = [[touches anyObject] locationInView:self];

    [self startDisplayLink];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.touchLocation = [[touches anyObject] locationInView:self];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self stopDisplayLink];
}

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    self.lastTimestamp = CACurrentMediaTime();   // initialize the `lastTimestamp`
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    // figure out the time elapsed, and reset the `lastTimestamp`

    CFTimeInterval currentTimestamp = CACurrentMediaTime();
    CFTimeInterval elapsed = currentTimestamp - self.lastTimestamp;
    self.lastTimestamp = currentTimestamp;

    // figure out distance to touch and distance we'd move on basis of velocity and elapsed time

    CGFloat distanceToTouch  = hypotf(self.touchLocation.y - self.objectPoint.y, self.touchLocation.x - self.objectPoint.x);
    CGFloat distanceWillMove = self.velocity * elapsed;

    // this does the calculation of the angle between the touch location and
    // the current `self.objectPoint`, and then updates `self.objectPoint` on
    // the basis of (a) the angle; and (b) the desired velocity.

    if (distanceToTouch == 0.0)                  // if we're already at touchLocation, then just quit
        return;
    if (distanceToTouch < distanceWillMove) {    // if the distance to move is less than the target, just move to touchLocation
        self.objectPoint = self.touchLocation;
    } else {                                     // otherwise, calculate where we're going to move to
        CGFloat angle = atan2f(self.touchLocation.y - self.objectPoint.y, self.touchLocation.x - self.objectPoint.x);
        self.objectPoint = CGPointMake(self.objectPoint.x + cosf(angle) * distanceWillMove,
                                       self.objectPoint.y + sinf(angle) * distanceWillMove);
    }
    [self setNeedsDisplay];
}

並使用它,您需要定義一些屬性:

@property (nonatomic) CGFloat velocity;
@property (nonatomic) CGPoint touchLocation;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CFTimeInterval lastTimestamp;

如果要用手指拖動它,則需要:

  • touchesBegan ,保存起始locationInView以及要拖動的對象的“原始位置”;

  • touchesMoved ,獲取新的locationInView ,計算該locationInView與原始locationInView之間的增量(“平移”),將其添加到視圖的已保存“原始位置”,然后使用該值來更新視圖。

這樣,當您在屏幕上拖動對象時,該對象將用手指跟蹤100%。


例如,您可能會:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.touchBeganLocation = [[touches anyObject] locationInView:self];
    self.originalObjectPoint = self.objectPoint;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint location = [[touches anyObject] locationInView:self];
    CGPoint translation = CGPointMake(location.x - self.touchBeganLocation.x, location.y - self.touchBeganLocation.y);
    self.objectPoint = CGPointMake(self.originalObjectPoint.x + translation.x, self.originalObjectPoint.y + translation.y);
    [self setNeedsDisplay];
}

可能無需多說,您需要一些屬性來跟蹤這兩個新的CGPoint值:

@property (nonatomic) CGPoint originalObjectPoint;
@property (nonatomic) CGPoint touchBeganLocation;

坦白地說,我可能會使用手勢識別器,但這是使用touchesBegantouchesMoved拖動的示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM