2014-10-02 30 views
1

從這篇文章Drag UIView around Shape Comprised of CGMutablePaths採取下一步Drag UIView around Shape Comprised of CGMutablePaths,我試圖添加一條線固定在pathLayer_的中心,另一端與圓形對象一起被拖動(circleLayer在handleView_)上的路徑(圖-8)。iOS拖動形狀固定到中心

example

線都有自己層andview和路徑中(空隙)initHandleView發起。

第一:我不能夠獲得線要經過pathLayer_中心:

- (void)viewDidLoad { 
[super viewDidLoad]; 
[self initPathLayer]; 
[self initHandleView]; 
[self initHandlePanGestureRecognizer]; 
} 


- (void)initPathLayer { 
pathLayer_ = [CAShapeLayer layer]; 
pathLayer_.lineWidth = 1; 
pathLayer_.fillColor = nil; 
pathLayer_.strokeColor = [UIColor lightGrayColor].CGColor; 
pathLayer_.lineCap = kCALineCapButt; 
pathLayer_.lineJoin = kCALineJoinRound; 
pathLayer_.frame = self.view.bounds; 
pathLayerCenter_ = CGPointMake(CGRectGetMidX(pathLayer_.frame), CGRectGetMidY(pathLayer_.frame)); 
[self.view.layer addSublayer:pathLayer_]; 
} 


- (void)initHandleView { 
handlePathPointIndex_ = 0; 
CGRect rect = CGRectMake(0, 0, 30, 30); 
CAShapeLayer *circleLayer = [CAShapeLayer layer]; 
circleLayer.fillColor = [UIColor redColor].CGColor; 
circleLayer.strokeColor = [UIColor redColor].CGColor; 
circleLayer.lineWidth = 2; 
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(rect, circleLayer.lineWidth, circleLayer.lineWidth)]; 
circleLayer.frame = rect; 
circleLayer.path = circlePath.CGPath; 
handleView_ = [[UIView alloc] initWithFrame:rect]; 

CGRect lineRect = CGRectMake(0,0,CGRectGetMaxX([[UIScreen mainScreen] bounds]), CGRectGetMaxY([[UIScreen mainScreen] bounds])); 
CGPoint center = CGPointMake(CGRectGetMidX(pathLayer_.frame), CGRectGetMidY(pathLayer_.frame)); 
lineView_ = [[UIView alloc] initWithFrame:lineRect]; 
CAShapeLayer *lineLayer = [CAShapeLayer layer]; 
lineLayer.fillColor = [UIColor blueColor].CGColor; 
lineLayer.strokeColor = [UIColor blueColor].CGColor; 
lineLayer.lineWidth = 2; 
lineLayer.frame = self.view.bounds; 
UIBezierPath *linePath = [UIBezierPath bezierPath]; 
CGPoint circlePoint = CGPointMake(handleView_.center.x, handleView_.center.y); 
[linePath moveToPoint:center]; //Center 
[linePath addLineToPoint:circlePoint]; 
[linePath moveToPoint:circlePoint]; //Handle 
lineLayer.path = linePath.CGPath; 

[handleView_.layer insertSublayer:circleLayer above:handleView_.layer]; 
[handleView_.layer insertSublayer:lineLayer above:handleView_.layer]; 
// handleView_.layer.masksToBounds = YES; 
float direction = DEGREES_TO_RADIANS(10); 

CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(direction); 
[handleView_ setTransform:rotationTransform]; 


[self.view addSubview:lineView_]; 
[self.view addSubview:handleView_]; 

} 

其次:我不知道我做的PanGesturerecognizer正確的事:

- (void)handleWasPanned:(UIPanGestureRecognizer *)recognizer { 
switch (recognizer.state) { 
    case UIGestureRecognizerStateBegan: { 
     desiredHandleCenter_ = handleView_.center; 
     break; 
    } 

    case UIGestureRecognizerStateChanged: 
    case UIGestureRecognizerStateEnded: 
    case UIGestureRecognizerStateCancelled: { 
     CGPoint translation = [recognizer translationInView:self.view]; 
     desiredHandleCenter_.x += translation.x; 
     desiredHandleCenter_.y += translation.y; 
     [self moveHandleTowardPointAndRotateLine:desiredHandleCenter_]; 
     break; 
    } 

    default: 
     break; 
} 

[recognizer setTranslation:CGPointZero inView:self.view]; 
} 

- (void)moveHandleTowardPointAndRotateLine:(CGPoint)point { 
CGFloat earlierDistance = [self distanceToPoint:point ifHandleMovesByOffset:-1]; 
CGFloat currentDistance = [self distanceToPoint:point ifHandleMovesByOffset:0]; 
CGFloat laterDistance = [self distanceToPoint:point ifHandleMovesByOffset:1]; 
if (currentDistance <= earlierDistance && currentDistance <= laterDistance) 
    return; 

NSInteger step; 
CGFloat distance; 
if (earlierDistance < laterDistance) { 
    step = -1; 
    distance = earlierDistance; 
} else { 
    step = 1; 
    distance = laterDistance; 
} 

NSInteger offset = step; 
while (true) { 
    NSInteger nextOffset = offset + step; 
    CGFloat nextDistance = [self distanceToPoint:point ifHandleMovesByOffset:nextOffset]; 
    if (nextDistance >= distance) 
     break; 
    distance = nextDistance; 
    offset = nextOffset; 
} 
handlePathPointIndex_ += offset; 

// Make one end of the line move with handle (point) while the other is pinned to center of pathLayer_ (ie. in figure8 its the cross point, in a circle it's center) 

//CGFloat rot = [self getTouchAngle:point]; 
CGFloat rot = atan2f((point.x - pathLayerCenter_.x), -(point.y - pathLayerCenter_.y)); 
handleView_.layer.transform = CATransform3DMakeRotation(rot, 0., 0., 1.); 
[self layoutHandleView]; 
} 
+0

某些圖片上傳到imgur.com那顯示你想要的行爲。張貼鏈接到這些圖像。 – 2014-10-03 15:19:49

+0

羅布感謝您花時間。鏈接到圖像:http://imgur.com/m9eDKCl – 2014-10-03 21:25:54

回答

1

我只是要忽略你的代碼,並告訴你如何修改我的原始答案來添加你想要的行。

首先,我要使用專用的形狀圖層爲線,所以我加入了一個實例變量來引用線層:

@implementation ViewController { 
    CAShapeLayer *lineLayer_; // NEW!!! 
    UIBezierPath *path_; 
    CAShapeLayer *pathLayer_; 
    etc. 

我需要我的時候初始化線層加載視圖:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self initPathLayer]; 
    [self initHandleView]; 
    [self initHandlePanGestureRecognizer]; 
    [self initLineLayer]; // NEW!!! 
} 

- (void)initLineLayer { 
    lineLayer_ = [CAShapeLayer layer]; 
    lineLayer_.lineWidth = 1; 
    lineLayer_.fillColor = nil; 
    lineLayer_.strokeColor = [UIColor redColor].CGColor; 
    lineLayer_.lineCap = kCALineCapRound; 
    lineLayer_.lineJoin = kCALineJoinRound; 
    [self.view.layer addSublayer:lineLayer_]; 
} 

我需要佈置行層時我鋪陳我的頂層視圖(當它的第一顯示和上旋轉):

- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 
    [self createPath]; 
    [self createPathPoints]; 
    [self layoutPathLayer]; 
    [self layoutHandleView]; 
    [self layoutLineLayer]; // NEW!!! 
} 

- (void)layoutLineLayer { 
    lineLayer_.frame = self.view.bounds; 
    CGRect bounds = self.view.bounds; 
    CGPoint start = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds)); 
    CGPoint end = pathPoints_[handlePathPointIndex_]; 
    UIBezierPath *path = [UIBezierPath bezierPath]; 
    [path moveToPoint:start]; 
    [path addLineToPoint:end]; 
    lineLayer_.path = path.CGPath; 
} 

最後,我需要重新佈置行層(更新路徑),每當我更新了手柄:

- (void)moveHandleTowardPoint:(CGPoint)point { 
    // I have omitted most of this method body for brevity. 
    // Just copy it from the original answer. 

    ... 
    ... 

    handlePathPointIndex_ += offset; 
    [self layoutHandleView]; 
    [self layoutLineLayer]; // NEW!!! 
} 

結果:

enter image description here

+0

工程就像一個魅力,謝謝 – 2014-10-04 18:16:22