// // KKCutGridView.m // WWImageEdit // // Created by 邬维 on 2017/1/16. // Copyright © 2017年 kook. All rights reserved. // #import "KKCutGridView.h" #import "KKCutCircle.h" #import "KKCutGridLayer.h" static const NSUInteger kLeftTopCircleView = 1; static const NSUInteger kLeftBottomCircleView = 2; static const NSUInteger kRightTopCircleView = 3; static const NSUInteger kRightBottomCircleView = 4; @implementation KKCutGridView{ KKCutGridLayer *_gridLayer; //4个角 KKCutCircle *_ltView; KKCutCircle *_lbView; KKCutCircle *_rtView; KKCutCircle *_rbView; } - (id)initWithSuperview:(UIView*)superview frame:(CGRect)frame{ self = [super initWithFrame:frame]; if(self){ [superview addSubview:self]; _gridLayer = [[KKCutGridLayer alloc] init]; _gridLayer.frame = self.bounds; [self.layer addSublayer:_gridLayer]; _ltView = [self clippingCircleWithTag:kLeftTopCircleView]; _lbView = [self clippingCircleWithTag:kLeftBottomCircleView]; _rtView = [self clippingCircleWithTag:kRightTopCircleView]; _rbView = [self clippingCircleWithTag:kRightBottomCircleView]; UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGridView:)]; [self addGestureRecognizer:panGesture]; self.clippingRect = self.bounds; } return self; } //4个角的拖动圆球 - (KKCutCircle*)clippingCircleWithTag:(NSInteger)tag { KKCutCircle *view = [[KKCutCircle alloc] initWithFrame:CGRectMake(0, 0, 75, 75)]; view.tag = tag; UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panCircleView:)]; [view addGestureRecognizer:panGesture]; [self.superview addSubview:view]; return view; } - (void)removeFromSuperview { [super removeFromSuperview]; [_ltView removeFromSuperview]; [_lbView removeFromSuperview]; [_rtView removeFromSuperview]; [_rbView removeFromSuperview]; } - (void)setBgColor:(UIColor *)bgColor { _gridLayer.bgColor = bgColor; } - (void)setGridColor:(UIColor *)gridColor { _gridLayer.gridColor = gridColor; } - (void)setClippingRect:(CGRect)clippingRect { _clippingRect = clippingRect; _ltView.center = [self.superview convertPoint:CGPointMake(_clippingRect.origin.x, _clippingRect.origin.y) fromView:self]; _lbView.center = [self.superview convertPoint:CGPointMake(_clippingRect.origin.x, _clippingRect.origin.y+_clippingRect.size.height) fromView:self]; _rtView.center = [self.superview convertPoint:CGPointMake(_clippingRect.origin.x+_clippingRect.size.width, _clippingRect.origin.y) fromView:self]; _rbView.center = [self.superview convertPoint:CGPointMake(_clippingRect.origin.x+_clippingRect.size.width, _clippingRect.origin.y+_clippingRect.size.height) fromView:self]; _gridLayer.clippingRect = clippingRect; [self setNeedsDisplay]; } - (void)setNeedsDisplay { [super setNeedsDisplay]; [_gridLayer setNeedsDisplay]; } //拖动4个角 - (void)panCircleView:(UIPanGestureRecognizer*)sender { CGPoint point = [sender locationInView:self]; CGPoint dp = [sender translationInView:self]; CGRect rct = self.clippingRect; const CGFloat W = self.frame.size.width; const CGFloat H = self.frame.size.height; CGFloat minX = 0; CGFloat minY = 0; CGFloat maxX = W; CGFloat maxY = H; CGFloat ratio = (sender.view.tag == kLeftBottomCircleView || sender.view.tag == kRightTopCircleView) ? -0 : 0; switch (sender.view.tag) { case kLeftTopCircleView: // upper left { maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W); maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H); if(ratio!=0){ CGFloat y0 = rct.origin.y - ratio * rct.origin.x; CGFloat x0 = -y0 / ratio; minX = MAX(x0, 0); minY = MAX(y0, 0); point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; } else{ point.y = point.x * ratio + y0; } } else{ point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); } rct.size.width = rct.size.width - (point.x - rct.origin.x); rct.size.height = rct.size.height - (point.y - rct.origin.y); rct.origin.x = point.x; rct.origin.y = point.y; break; } case kLeftBottomCircleView: // lower left { maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W); minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H); if(ratio!=0){ CGFloat y0 = (rct.origin.y + rct.size.height) - ratio* rct.origin.x ; CGFloat xh = (H - y0) / ratio; minX = MAX(xh, 0); maxY = MIN(y0, H); point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; } else{ point.y = point.x * ratio + y0; } } else{ point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); } rct.size.width = rct.size.width - (point.x - rct.origin.x); rct.size.height = point.y - rct.origin.y; rct.origin.x = point.x; break; } case kRightTopCircleView: // upper right { minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W); maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H); if(ratio!=0){ CGFloat y0 = rct.origin.y - ratio * (rct.origin.x + rct.size.width); CGFloat yw = ratio * W + y0; CGFloat x0 = -y0 / ratio; maxX = MIN(x0, W); minY = MAX(yw, 0); point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; } else{ point.y = point.x * ratio + y0; } } else{ point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); } rct.size.width = point.x - rct.origin.x; rct.size.height = rct.size.height - (point.y - rct.origin.y); rct.origin.y = point.y; break; } case kRightBottomCircleView: // lower right { minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W); minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H); if(ratio!=0){ CGFloat y0 = (rct.origin.y + rct.size.height) - ratio * (rct.origin.x + rct.size.width); CGFloat yw = ratio * W + y0; CGFloat xh = (H - y0) / ratio; maxX = MIN(xh, W); maxY = MIN(yw, H); point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; } else{ point.y = point.x * ratio + y0; } } else{ point.x = MAX(minX, MIN(point.x, maxX)); point.y = MAX(minY, MIN(point.y, maxY)); } rct.size.width = point.x - rct.origin.x; rct.size.height = point.y - rct.origin.y; break; } default: break; } self.clippingRect = rct; } //移动裁剪view - (void)panGridView:(UIPanGestureRecognizer*)sender { static BOOL dragging = NO; static CGRect initialRect; if(sender.state==UIGestureRecognizerStateBegan){ CGPoint point = [sender locationInView:self]; dragging = CGRectContainsPoint(_clippingRect, point); initialRect = self.clippingRect; } else if(dragging){ CGPoint point = [sender translationInView:self]; CGFloat left = MIN(MAX(initialRect.origin.x + point.x, 0), self.frame.size.width-initialRect.size.width); CGFloat top = MIN(MAX(initialRect.origin.y + point.y, 0), self.frame.size.height-initialRect.size.height); CGRect rct = self.clippingRect; rct.origin.x = left; rct.origin.y = top; self.clippingRect = rct; } } @end