Limiting a pan gesture recognizer to an ImageView? - ios

I have an ImageView containing a circular gradient and a panGestureRecognizer that I want to limit specifically to the gradient to prevent interference with the UISliders in the view or the white background.
How do I only recognize touches within the gradient?
As of now, I am using this equation with bad results :
CGPoint lastPoint = [sender locationOfTouch: sender.numberOfTouches - 1 inView: gradientView];
CGPoint center = CGPointMake((size.width/2), (size.height /2));
These variables are used to indicate the center of the gradient. This is the equation :
if((lastPoint.x - center.x) + (lastPoint.y - center.y)/2 < radius)
{
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:saturationSlider.value brightness:hellSlider.value alpha:alphaSlider.value];
if ([color getRed: &r green: &g blue:&b alpha: &a])
{
NSLog(#"Color value - R : %g G : %g : B %g", r*255, g*255, b*255);
}
float red = r;
float green = g;
float blue = b;
rText.text = [NSString stringWithFormat:#"%.0f",rSlider.value];
gText.text = [NSString stringWithFormat:#"%.0f",green*255];
bText.text = [NSString stringWithFormat:#"%.0f",blue*255];
colorView.backgroundColor = [UIColor colorWithRed:(rText.text.floatValue/255) green:(gText.text.floatValue/255) blue:(bText.text.floatValue/255) alpha:alphaSlider.value];
rSlider.value = red*255;
gSlider.value = green*255;
bSlider.value = blue*255;
alphaText.text = [NSString stringWithFormat:#"%.2f",alphaSlider.value];
brightnessText.text = [NSString stringWithFormat:#"%.2f",hellSlider.value];
saturationText.text = [NSString stringWithFormat:#"%.2f",saturationSlider.value];
}
This code above is inside my panGestureRecognizer's method.

You can add another UIView on the top of that circular view and apply gesture to that View.
UIView *gestureView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
[gestureView.layer setCornerRadius:gestureView.frame.size.width/2];
This will give you a circular UIView.
Adjust the size and the position according to your need.

Related

Unable to scale shapes to match the dimensions of UIView

I have created a custom view that draws shapes of varying sides. The view is added to main view as a subview as given below. The shapes are of different dimensions.
My source code is given below
-(instancetype) initWithSides:(NSUInteger) sides andFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor clearColor]];
self.sides = sides;
self.radius = CGRectGetWidth(self.frame) * 1.5 / sides);
}
return self;
}
-(void) drawRect:(CGRect) frame {
// Sides is passed as constructor argument. 4 sides means a quadrilateral etc.
// Get CGPAthRef instance
CGFloat angle = DEGREES_TO_RADIANS(360 / ((CGFloat) self.sides));
int count = 0;
CGFloat xCoord = CGRectGetMidX(self.frame);
CGFloat yCoord = CGRectGetMidY(self.frame);
while (count < self.sides) {
CGFloat xPosition =
xCoord + self.radius * cos(angle * ((CGFloat) count));
CGFloat yPosition =
yCoord + self.radius * sin(angle * ((CGFloat) count));
[self.points addObject:[NSValue valueWithCGPoint:CGPointMake(xPosition, yPosition)]];
count ++;
}
NSValue* v = [self.points firstObject];
CGPoint first = v.CGPointValue;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, first.x, first.y);
for (int ix = 1; ix < [self.points count]; ix++) {
NSValue* pValue = [self.points objectAtIndex:ix];
CGPoint p = pValue.CGPointValue;
CGPathAddLineToPoint(path, nil, p.x, p.y);
}
CGPathCloseSubpath(path);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, path);
[self colourView:context withPath:path];
}
-(void) colourView:(CGContextRef) context withPath:(CGPathRef) ref {
NSUInteger num = arc4random_uniform(8) + 1;
UIColor* color = nil;
switch (num) {
case 1:
color = [UIColor redColor];
break;
case 2:
color = [UIColor greenColor];
break;
case 3:
color = [UIColor yellowColor];
break;
case 4:
color = [UIColor blueColor];
break;
case 5:
color = [UIColor orangeColor];
break;
case 6:
color = [UIColor brownColor];
break;
case 7:
color = [UIColor purpleColor];
break;
case 8:
color = [UIColor blackColor];
break;
default:
break;
}
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillPath(context);
}
This constitutes one single shape. This is how I am drawing the rest of the views.
-(void) initDrawView {
NSUInteger width = CGRectGetWidth(self.view.bounds) / 8;
NSUInteger height = (CGRectGetHeight(self.view.frame))/ 8;
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
for (int i = 0 ; i < 8; i++) {
CGFloat yCoord = i * height + i * 15;
for (int j = 0; j < 8; j ++) {
int side = 3 + arc4random() % 8;
CGFloat xCoord = j * width;
SimpleRegularPolygonView* view =
[[SimpleRegularPolygonView alloc] initWithSides:side andFrame:CGRectMake(xCoord, yCoord, width, height)];
[view sizeToFit];
view.viewEffectsDelegate = self;
[view setTag: (8 * i + j)];
[self.view addGestureRecognizer:singleFingerTap];
[self.view addSubview:view];
}
}
}
1) I don't know how to make them have the same dimensions. How can I do that? (First image)
2) the images don't scale up to the size of the UIView (Second image).
Your current code makes the radius inversely proportional to the number of sides:
self.radius = CGRectGetWidth(self.frame) * 1.5 / sides;
so the more sides, the smaller the image. A quick fix would be to just make the radius half the frame width:
self.radius = CGRectGetWidth(self.frame) /2;
This will mean shapes with an even number of sides fill the frame width. But those with an odd number of sides will appear to have space to the left. If you want to adjust for that you will need more detailed calculations for the width, and you will also need to move the "centre" of the shape. For an odd number sides, the radius would need to be:
self.radius = CGRectGetWidth(self.frame) /(1 + cos(angle / 2));
and xCoord would need to be:
CGFloat xCoord = CGRectGetMinX(self.frame) + self.radius * cos(angle/2);

Objective C - how to know if point is inside a quarter of circle?

I drew a quarter of a circle inside a rectangle.
Rectangle:
UIView *Rectangle = [[UIView alloc] initWithFrame:CGRectMake(0,0,[[UIScreen mainScreen] bounds].size.width,[[UIScreen mainScreen] bounds].size.height-292)];
Rectangle.backgroundColor = [UIColor lightGrayColor];
Rectangle.layer.zPosition = -5;
Quarter of Cirlce:
CGPoint center;
center.x = 0;
center.y = 0;
float radius = [[UIScreen mainScreen] bounds].size.width;
UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:0
endAngle:M_PI
clockwise:YES];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setPath:[circle CGPath]];
Then I added the rectangle in the view and added the circle inside the rectangle:
[self.view addSubview:Rectangle];
[Rectangle.layer addSublayer:circleLayer];
Then I started drawing little rectangles of 1 width and 1 height that I consider as points, and randomly added them into the view with a for loop, coloring the points inside the circle with green and points outside of the circle with red
int compteurPointsinCercle = 0 ;
int compteurPointsOutCercle = 0 ;
float XcenterCircle = center.x;
float YcenterCircle = center.y;
for (int i = 0 ; i < 50000 ; i++ )
{
float xvalue = arc4random_uniform([[UIScreen mainScreen] bounds].size.width);
float yvalue = arc4random_uniform([[UIScreen mainScreen] bounds].size.height-292);
// (x - center_x)^2 + (y - center_y)^2 < radius^2
float valeurPoint = (xvalue - XcenterCircle)*2 + (yvalue -YcenterCircle)*2;
NSLog(#"(Inside for), valeurPoint is : %f",valeurPoint);
if ( valeurPoint < (radius*2) )
{
// Point is inside of circle (green color)
compteurPointsinCercle++;
UIView *Rectangle2 = [[UIView alloc] initWithFrame:CGRectMake(xvalue,yvalue,1,1)];
Rectangle2.backgroundColor = [UIColor greenColor];
[self.view addSubview:Rectangle2];
}
else if ( valeurPoint > (radius*2) )
{
// Point is outside of circle (red color)
compteurPointsOutCercle++;
UIView *Rectangle2 = [[UIView alloc] initWithFrame:CGRectMake(xvalue,yvalue,1,1)];
Rectangle2.backgroundColor = [UIColor redColor];
[self.view addSubview:Rectangle2];
}
}
I test if the point is inside the circle using this :
float valeurPoint = (xvalue - XcenterCircle)*2 + (yvalue -YcenterCircle)*2;
where xvalue and yvalue are the coordinates of the point that will be created, and XcenterCircle and YcenterCircle are the coordiantes of the center of the circle.
I have something wrong because it gives me this result (it dosent test correctly if the point is inside the circle or not: a part of the points inside of the circle are considered outside):
can you tell me what I am doing wrong here ? and how can I exactly the points inside the circle ?
* is not power operation, it is multiplication.
float valeurPoint = (xvalue - XcenterCircle) * (xvalue - XcenterCircle) + (yvalue -YcenterCircle)*(yvalue -YcenterCircle);
if ( valeurPoint < (radius * radius) )
Should fix your problem
or using the pow function:
float valeurPoint = pow((xvalue - XcenterCircle), 2) + pow((yvalue -YcenterCircle), 2);
You can also use hypot function directly (although the performance can be slightly worse because of sqrt calculation)
float distance = hypotf((xvalue - XcenterCircle), (yvalue -YcenterCircle));
if (distance < radius)
EDIT:
Thanks #Alex for suggestion. The best solution is to use the native method -[UIBerierPath containsPoint:]. Then you won't have to calculate the distance at all.

Calling UIGestureRecognizer from UITouch object

I am trying to associate a Gesture with UITouch object because I need to pass data through a target action Method.
I have something implemented but it is inefficient,it get 100% of the CPU processing, it is probably because it is coded incorrectly.
There is my instance method for the UITouch event which call the UIPangesture
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
return YES;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePan:)];
[self addGestureRecognizer: panGesture];
}
There is my instance method for the UIPAnGestureRecognizer
- (IBAction)handlePan:(UIPanGestureRecognizer *)event
{
if (event.numberOfTouches==1)
{
CGPoint lastPoint = [event locationOfTouch: event.numberOfTouches - 1 inView: event.view];
CGRect bounds = self.bounds;
CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
CGPoint delta = CGPointMake(lastPoint.x - center.x, lastPoint.y - center.y);
CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
angle = fmod(angle, M_PI * 2.0);
angle += angle >= 0 ? 0 : M_PI * 2.0;
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
if ([color getRed: &r green: &g blue:&b alpha: &a]){
rValue = r;
gValue = g;
bValue = b;
[self setNeedsDisplay];
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self updateLabels];
}
}
}
And there there the methods which call the action method to obtain the variables from the color picker
- (void)setup:(CsoundObj *)csoundObj
{
NSLog(#"Color value - R : %f G : %f : B %f", rValue, gValue, bValue);
channelPtrR = [csoundObj getInputChannelPtr:#"mix" channelType:CSOUND_CONTROL_CHANNEL];
channelPtrG = [csoundObj getInputChannelPtr:#"pitch" channelType:CSOUND_CONTROL_CHANNEL];
channelPtrB = [csoundObj getInputChannelPtr:#"c" channelType:CSOUND_CONTROL_CHANNEL];
cachedValueR = rValue;
cachedValueG = gValue;
cachedValueB = bValue;
self.cacheDirty = YES;
[self addTarget:self action:#selector(updateValueCache:) forControlEvents:UIControlEventValueChanged];
}
- (void)updateValueCache:(id)sender
{
cachedValueR = ((CustomView*)sender).rValue;
cachedValueG = ((CustomView*)sender).gValue;
cachedValueB = ((CustomView*)sender).bValue;
self.cacheDirty = YES;
}
- (void)updateValuesToCsound
{
if (self.cacheDirty) {
*channelPtrR = cachedValueR;
*channelPtrG = cachedValueG;
*channelPtrB = cachedValueB;
self.cacheDirty = NO;
}
}
- (void)updateValuesFromCsound
{
}
- (void)cleanup
{
[self removeTarget:self action:#selector(updateValueCache:) forControlEvents:UIControlEventValueChanged];
}
I know the problem it is on the instance method for the UITouch event which call the UIPangesture, any other way to do it more efficiently?
I think that you are calling this section of code way too often:
CGPoint lastPoint = [event locationOfTouch: event.numberOfTouches - 1 inView: event.view];
CGRect bounds = self.bounds;
CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
CGPoint delta = CGPointMake(lastPoint.x - center.x, lastPoint.y - center.y);
CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
angle = fmod(angle, M_PI * 2.0);
angle += angle >= 0 ? 0 : M_PI * 2.0;
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
if ([color getRed: &r green: &g blue:&b alpha: &a]){
rValue = r;
gValue = g;
bValue = b;
[self setNeedsDisplay];
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self updateLabels];
}
You are likely calling it when there is no change, or little change. There are two things you could do to reduce the number of calls. You can test for a significant change in the angle like this:
//class property
#property (nonatomic, assign) CGFloat lastAngle;
//In your code
CGFloat deltaAngle = fabs(self.lastAngle - angle)
if (deltaAngle > 0.5) { //select whatever delta works best
angle += angle >= 0 ? 0 : M_PI * 2.0;
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
if ([color getRed: &r green: &g blue:&b alpha: &a]){
rValue = r;
gValue = g;
bValue = b;
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self updateLabels];
[self setNeedsDisplay];
}
}
Or you can test for time since the last update like this:
//class property
#property (nonatomic, retain) NSDate *lastTime;
//set it when the view loads
self.lastTime = [NSDate date];
//In your code
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:lastdate];
self.lastTime = [NSDate date];
if (interval > 0.05) { //select whatever time interval works best
angle += angle >= 0 ? 0 : M_PI * 2.0;
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:1. brightness:1. alpha:1];
if ([color getRed: &r green: &g blue:&b alpha: &a]){
rValue = r;
gValue = g;
bValue = b;
[self sendActionsForControlEvents:UIControlEventValueChanged];
[self updateLabels];
[self setNeedsDisplay];
}
}
Also, are you sure you need the [self setNeedsDisplay] ?

Adding an indicator at the current touch position?

I am developing a color selector and using a circular gradient and a panGesture to pick the color.
Can I add a crosshair or something else to the current touch position?
I need the crosshair to be visible but it should not interfere with the gradient.
This is the code that adds the gradient :
- (void)viewDidLoad
{
[super viewDidLoad];
CGSize size = CGSizeMake(self.view.bounds.size.width, ((self.view.bounds.size.height)/2));
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0);
[[UIColor whiteColor] setFill];
UIRectFill(CGRectMake(0, 0,size.width,size.height));
int sectors = 180;
float radius = MIN(size.width, size.height)/2;
float angle = 2 * M_PI/sectors;
UIBezierPath *bezierPath;
for ( int i = 0; i < sectors; i++)
{
CGPoint center = CGPointMake(((size.width)/2), ((size.height)/2));
bezierPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:i * angle endAngle:(i + 1) * angle clockwise:YES];
[bezierPath addLineToPoint:center];
[bezierPath closePath];
UIColor *color = [UIColor colorWithHue:((float)i)/sectors saturation:1. brightness:1. alpha:1];
[color setFill];
[color setStroke];
[bezierPath fill];
[bezierPath stroke];
}
img = UIGraphicsGetImageFromCurrentImageContext();
gradientView = [[UIImageView alloc]initWithImage:img];;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePan:)];
colorView = [[UIView alloc] init];
colorView.frame = CGRectMake(0, 00, 50, 50);
rText.textAlignment = NSTextAlignmentCenter;
gText.textAlignment = NSTextAlignmentCenter;
bText.textAlignment = NSTextAlignmentCenter;
saturationText.textAlignment = NSTextAlignmentCenter;
alphaText.textAlignment = NSTextAlignmentCenter;
brightnessText.textAlignment = NSTextAlignmentCenter;
rText.keyboardType = UIKeyboardTypeNumberPad;
gText.keyboardType = UIKeyboardTypeNumberPad;
bText.keyboardType = UIKeyboardTypeNumberPad;
saturationText.keyboardType = UIKeyboardTypeNumberPad;
alphaText.keyboardType = UIKeyboardTypeNumberPad;
brightnessText.keyboardType = UIKeyboardTypeNumberPad;
gradientView.frame = CGRectMake(0,0,size.width,size.height);
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:gradientView];
gradientView.userInteractionEnabled = YES;
[gradientView addGestureRecognizer: panGesture];
[self.view addSubview:colorView];
}
The handlePan method :
- (IBAction)handlePan:(UIPanGestureRecognizer *)sender
{
if (sender.numberOfTouches)
{
CGSize size = CGSizeMake(self.view.bounds.size.width, (self.view.bounds.size.height)/2);
float radius = MIN(size.width, size.height)/2;
[alphaSlider addTarget:self action:#selector(changeOpacity:) forControlEvents:UIControlEventValueChanged];
[hellSlider addTarget:self action:#selector(changeBrightness:) forControlEvents:UIControlEventValueChanged];
[saturationSlider addTarget:self action:#selector(saturate:) forControlEvents:UIControlEventValueChanged];
[rSlider addTarget:self action:#selector(redSlider:) forControlEvents:UIControlEventValueChanged];
[gSlider addTarget:self action:#selector(greenSlider:) forControlEvents:UIControlEventValueChanged];
[bSlider addTarget:self action:#selector(blueSlider:) forControlEvents:UIControlEventValueChanged];
CGPoint lastPoint = [sender locationOfTouch: sender.numberOfTouches - 1 inView: gradientView];
CGPoint center = CGPointMake((size.width/2), (size.height /2));
CGPoint delta = CGPointMake(lastPoint.x - center.x, lastPoint.y - center.y);
CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
angle = fmod(angle, M_PI * 2.0);
angle += angle >= 0 ? 0 : M_PI * 2.0;
if((lastPoint.x - center.x) + (lastPoint.y - center.y)/2 < radius)
{
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:saturationSlider.value brightness:hellSlider.value alpha:alphaSlider.value];
if ([color getRed: &r green: &g blue:&b alpha: &a])
{
NSLog(#"Color value - R : %g G : %g : B %g", r*255, g*255, b*255);
}
float red = r;
float green = g;
float blue = b;
rText.text = [NSString stringWithFormat:#"%.0f",rSlider.value];
gText.text = [NSString stringWithFormat:#"%.0f",green*255];
bText.text = [NSString stringWithFormat:#"%.0f",blue*255];
colorView.backgroundColor = [UIColor colorWithRed:(rText.text.floatValue/255) green:(gText.text.floatValue/255) blue:(bText.text.floatValue/255) alpha:alphaSlider.value];
rSlider.value = red*255;
gSlider.value = green*255;
bSlider.value = blue*255;
alphaText.text = [NSString stringWithFormat:#"%.2f",alphaSlider.value];
brightnessText.text = [NSString stringWithFormat:#"%.2f",hellSlider.value];
saturationText.text = [NSString stringWithFormat:#"%.2f",saturationSlider.value];
}
}
}
Question is solved, thank you.
Well, you definitely 'can' add a crosshair at your current touch position.
I can tell you one of the many possible ways of doing this.
Implement the
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer
action handler.
Load an image of a crosshair into an UIImage (say overlayImage):
overlayImage =[UIImage imageNamed:#"crosshair.png"];
and set it into an UIView (say overlayView).
[This can be done in your viewDidLoad method itself.]
Now, add the following code to your handlePan method:
CGPoint translation = [recognizer translationInView:colorView]; //whichever view you want.
_overlayView.center = CGPointMake(_overlayView.center.x + translation.x,
_overlayView.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:colorView];
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [recognizer velocityInView:colorView];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 800;
// NSLog(#"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
CGPoint finalPoint = CGPointMake(_overlayView.center.x + (velocity.x * slideFactor),
_overlayView.center.y + (velocity.y * slideFactor));
finalPoint.x = MIN(MAX(finalPoint.x, 0), colorView.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 0), colorView.bounds.size.height);
[UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
_overlayView.center = finalPoint;
} completion:nil];
That should do the trick.
You may also try doing this by implementing the touchesBegan and touchesMoved method.

Limiting a pan gesture recognizer to a specific circle

I am using a circular gradient, drawn in an image view, as a color wheel for my color picker. I want to limit the pan gesture recognizer's shouldReceiveTouch: to the gradient's position so that the rest of the view is not affected by the pan gesture recognizer.
How do I do specify circular bounds matching the gradient's radius?
EDIT: I have tried the following code without effect :
if (sender.numberOfTouches)
{
CGSize size = CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height/3);
float radius = MIN(size.width, size.height)/2;
[alphaSlider addTarget:self action:#selector(changeOpacity:) forControlEvents:UIControlEventValueChanged];
[hellSlider addTarget:self action:#selector(changeBrightness:) forControlEvents:UIControlEventValueChanged];
[saturationSlider addTarget:self action:#selector(saturate:) forControlEvents:UIControlEventValueChanged];
[rSlider addTarget:self action:#selector(redSlider:) forControlEvents:UIControlEventValueChanged];
[gSlider addTarget:self action:#selector(greenSlider:) forControlEvents:UIControlEventValueChanged];
[bSlider addTarget:self action:#selector(blueSlider:) forControlEvents:UIControlEventValueChanged];
CGPoint lastPoint = [sender locationOfTouch: sender.numberOfTouches - 1 inView: gradientView];
CGPoint center = CGPointMake((size.width/2), (size.height /2));
CGPoint delta = CGPointMake(lastPoint.x - center.x, lastPoint.y - center.y);
CGFloat angle = (delta.y == 0 ? delta.x >= 0 ? 0 : M_PI : atan2(delta.y, delta.x));
angle = fmod(angle, M_PI * 2.0);
angle += angle >= 0 ? 0 : M_PI * 2.0;
if((lastPoint.x - center.x) + (lastPoint.y - center.y)/2 < radius)
{
UIColor *color = [UIColor colorWithHue: angle / (M_PI * 2.0) saturation:saturationSlider.value brightness:hellSlider.value alpha:alphaSlider.value];
if ([color getRed: &r green: &g blue:&b alpha: &a])
{
NSLog(#"Color value - R : %g G : %g : B %g", r*255, g*255, b*255);
}
float red = r;
float green = g;
float blue = b;
rText.text = [NSString stringWithFormat:#"%.0f",rSlider.value];
gText.text = [NSString stringWithFormat:#"%.0f",green*255];
bText.text = [NSString stringWithFormat:#"%.0f",blue*255];
colorView.backgroundColor = [UIColor colorWithRed:(rText.text.floatValue/255) green:(gText.text.floatValue/255) blue:(bText.text.floatValue/255) alpha:alphaSlider.value];
rSlider.value = red*255;
gSlider.value = green*255;
bSlider.value = blue*255;
alphaText.text = [NSString stringWithFormat:#"%.2f",alphaSlider.value];
brightnessText.text = [NSString stringWithFormat:#"%.2f",hellSlider.value];
saturationText.text = [NSString stringWithFormat:#"%.2f",saturationSlider.value];
}
}
}
It seems to work on the right side of the gradient and quits receiving color updates, left and lower side are still updating. I need to limit the panGesture appropriately in order for it to stop interfering with my UISliders.
Any ideas?
You just need to hit-test the touch event to see if it's within the circle's area. To do this you'll need to know the center point of your circle, and its radius.
A general equation for doing this is covered on this existing question:
Equation for testing if a point is inside a circle

Resources