I'm trying to spin an circle image based on user swipe.Now I've done by considering the as two parts. one is the left side and other is the right side. If the user swipes down from right half means it rotates clockwise and swipe up means anti clock wise. In left side I've done the vice versa. So now my image will rotate fine only when I touch the left and right half.. on touching top and bottom .. its behaving differently. I've even tried ny calculating the radians.. its also not working Can any one suggest me to identify clockwise or anticlock wise in a better way...
Thank u, Lakshmi jones
You should approach this problem with trignometry. Assuming you know the starting point of swipe (a1,b1) and the ending point of swipe (a2,b2) The circles centre is at (x,y)
If we know the difference of angles made by lines (x,y)->(a1,b1) and (x,y)->(a2,b2) we will know whether to rotate clockwise or anticlockwise based on whether the above said angle is positive or negative.
Angle made by a line is calculated below. Let the red angle be red
if(a1-x==0){
if(b1-y>0) red=pi/2
else red = 3*pi/2
}
else{
tan(red) = abs((b1-y)/(a1-x))
red = tan-inverse( abs((b1-y)/(a1-x)) )
if(a1-x<0){
if(b1-y<=0)
red+=pi;
else
red+=pi/2
}
else if(a1-x>0 && b1-y<0){
red+=3*pi/2
}
}
See here to know how to calculate tan-inverse.
Similarly calculate the value of angle green. After doing that just comparing the value of green and red will let you know what to do.
if(red - green == pi || red - green == 0){
do_nothing();
}else if(red - green > 0){
rotate_clockwise();
}else{
rotate_anticlockwise();
}
By using the acceleration/velocity data of the swipe you could rotate the circle with the same acceleration/velocity.
Have you ever tried this tutorial for your problem. This will help you for sure.
The .h file for calculating the swipe
#import <UIKit/UIKit.h>
#import "SMRotaryProtocol.h"
@interface SMRotaryWheel : UIControl
@property (weak) id <SMRotaryProtocol> delegate;
@property (nonatomic, strong) UIView *container;
@property int numberOfSections;
@property CGAffineTransform startTransform;
@property (nonatomic, strong) NSMutableArray *cloves;
@property int currentValue;
- (id) initWithFrame:(CGRect)frame andDelegate:(id)del withSections:(int)sectionsNumber;
And the .m file is
#import "SMRotaryWheel.h"
#import <QuartzCore/QuartzCore.h>
#import "SMCLove.h"
@interface SMRotaryWheel()
- (void)drawWheel;
- (float) calculateDistanceFromCenter:(CGPoint)point;
- (void) buildClovesEven;
- (void) buildClovesOdd;
- (UIImageView *) getCloveByValue:(int)value;
- (NSString *) getCloveName:(int)position;
@end
static float deltaAngle;
static float minAlphavalue = 0.6;
static float maxAlphavalue = 1.0;
@implementation SMRotaryWheel
@synthesize delegate, container, numberOfSections, startTransform, cloves, currentValue;
- (id) initWithFrame:(CGRect)frame andDelegate:(id)del withSections:(int)sectionsNumber {
if ((self = [super initWithFrame:frame])) {
self.currentValue = 0;
self.numberOfSections = sectionsNumber;
self.delegate = del;
[self drawWheel];
}
return self;
}
- (void) drawWheel {
container = [[UIView alloc] initWithFrame:self.frame];
CGFloat angleSize = 2*M_PI/numberOfSections;
for (int i = 0; i < numberOfSections; i++) {
UIImageView *im = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"segment.png"]];
im.layer.anchorPoint = CGPointMake(1.0f, 0.5f);
im.layer.position = CGPointMake(container.bounds.size.width/2.0-container.frame.origin.x,
container.bounds.size.height/2.0-container.frame.origin.y);
im.transform = CGAffineTransformMakeRotation(angleSize*i);
im.alpha = minAlphavalue;
im.tag = i;
if (i == 0) {
im.alpha = maxAlphavalue;
}
UIImageView *cloveImage = [[UIImageView alloc] initWithFrame:CGRectMake(12, 15, 40, 40)];
cloveImage.image = [UIImage imageNamed:[NSString stringWithFormat:@"icon%i.png", i]];
[im addSubview:cloveImage];
[container addSubview:im];
}
container.userInteractionEnabled = NO;
[self addSubview:container];
cloves = [NSMutableArray arrayWithCapacity:numberOfSections];
UIImageView *bg = [[UIImageView alloc] initWithFrame:self.frame];
bg.image = [UIImage imageNamed:@"bg.png"];
[self addSubview:bg];
UIImageView *mask = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 58, 58)];
mask.image =[UIImage imageNamed:@"centerButton.png"] ;
mask.center = self.center;
mask.center = CGPointMake(mask.center.x, mask.center.y+3);
[self addSubview:mask];
if (numberOfSections % 2 == 0) {
[self buildClovesEven];
} else {
[self buildClovesOdd];
}
[self.delegate wheelDidChangeValue:[self getCloveName:currentValue]];
}
- (UIImageView *) getCloveByValue:(int)value {
UIImageView *res;
NSArray *views = [container subviews];
for (UIImageView *im in views) {
if (im.tag == value)
res = im;
}
return res;
}
- (void) buildClovesEven {
CGFloat fanWidth = M_PI*2/numberOfSections;
CGFloat mid = 0;
for (int i = 0; i < numberOfSections; i++) {
SMClove *clove = [[SMClove alloc] init];
clove.midValue = mid;
clove.minValue = mid - (fanWidth/2);
clove.maxValue = mid + (fanWidth/2);
clove.value = i;
if (clove.maxValue-fanWidth < - M_PI) {
mid = M_PI;
clove.midValue = mid;
clove.minValue = fabsf(clove.maxValue);
}
mid -= fanWidth;
NSLog(@"cl is %@", clove);
[cloves addObject:clove];
}
}
- (void) buildClovesOdd {
CGFloat fanWidth = M_PI*2/numberOfSections;
CGFloat mid = 0;
for (int i = 0; i < numberOfSections; i++) {
SMClove *clove = [[SMClove alloc] init];
clove.midValue = mid;
clove.minValue = mid - (fanWidth/2);
clove.maxValue = mid + (fanWidth/2);
clove.value = i;
mid -= fanWidth;
if (clove.minValue < - M_PI) {
mid = -mid;
mid -= fanWidth;
}
[cloves addObject:clove];
NSLog(@"cl is %@", clove);
}
}
- (float) calculateDistanceFromCenter:(CGPoint)point {
CGPoint center = CGPointMake(self.bounds.size.width/2.0f, self.bounds.size.height/2.0f);
float dx = point.x - center.x;
float dy = point.y - center.y;
return sqrt(dx*dx + dy*dy);
}
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
float dist = [self calculateDistanceFromCenter:touchPoint];
if (dist < 40 || dist > 100)
{
// forcing a tap to be on the ferrule
NSLog(@"ignoring tap (%f,%f)", touchPoint.x, touchPoint.y);
return NO;
}
float dx = touchPoint.x - container.center.x;
float dy = touchPoint.y - container.center.y;
deltaAngle = atan2(dy,dx);
startTransform = container.transform;
UIImageView *im = [self getCloveByValue:currentValue];
im.alpha = minAlphavalue;
return YES;
}
- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
{
CGPoint pt = [touch locationInView:self];
float dist = [self calculateDistanceFromCenter:pt];
if (dist < 40 || dist > 100)
{
// a drag path too close to the center
NSLog(@"drag path too close to the center (%f,%f)", pt.x, pt.y);
// here you might want to implement your solution when the drag
// is too close to the center
// You might go back to the clove previously selected
// or you might calculate the clove corresponding to
// the "exit point" of the drag.
}
float dx = pt.x - container.center.x;
float dy = pt.y - container.center.y;
float ang = atan2(dy,dx);
float angleDifference = deltaAngle - ang;
container.transform = CGAffineTransformRotate(startTransform, -angleDifference);
return YES;
}
- (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
{
CGFloat radians = atan2f(container.transform.b, container.transform.a);
CGFloat newVal = 0.0;
for (SMClove *c in cloves) {
if (c.minValue > 0 && c.maxValue < 0) { // anomalous case
if (c.maxValue > radians || c.minValue < radians) {
if (radians > 0) { // we are in the positive quadrant
newVal = radians - M_PI;
} else { // we are in the negative one
newVal = M_PI + radians;
}
currentValue = c.value;
}
}
else if (radians > c.minValue && radians < c.maxValue) {
newVal = radians - c.midValue;
currentValue = c.value;
}
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
CGAffineTransform t = CGAffineTransformRotate(container.transform, -newVal);
container.transform = t;
[UIView commitAnimations];
[self.delegate wheelDidChangeValue:[self getCloveName:currentValue]];
UIImageView *im = [self getCloveByValue:currentValue];
im.alpha = maxAlphavalue;
}
- (NSString *) getCloveName:(int)position {
NSString *res = @"";
switch (position) {
case 0:
res = @"Circles";
break;
case 1:
res = @"Flower";
break;
case 2:
res = @"Monster";
break;
case 3:
res = @"Person";
break;
case 4:
res = @"Smile";
break;
case 5:
res = @"Sun";
break;
case 6:
res = @"Swirl";
break;
case 7:
res = @"3 circles";
break;
case 8:
res = @"Triangle";
break;
default:
break;
}
return res;
}
@end
Main Methods which will help you to track the swipe are
- (float) calculateDistanceFromCenter:(CGPoint)point
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
- (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
May this will help you :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With