我如何使图像旋转基于我的手指滑动的方向
我想旋转一个基于用户swipe.C圈的图像,我已经完成了考虑作为两部分。一个是左侧,另一个是右侧。 如果用户从右半侧向下滑动,则表示它顺时针旋转,向上滑动意味着反时钟。在左边我做了反过来。所以,现在只有当我触摸左右半边时,我的图像才会正常旋转..在触摸顶部和底部时..其行为不同。 我甚至试过NY计算弧度..其还没有工作 任何一个可以建议我来标识顺时针或anticlock以更好的方式明智...我如何使图像旋转基于我的手指滑动的方向
谢谢U, 拉克希米·琼斯
有无你曾经尝试this教程为您的问题。这肯定会对你有所帮助。
计算刷卡
#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;
与.m文件.h文件是
#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
主要方法,这将有助于您跟踪刷卡是
- (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
愿这能帮助你:)
你应该用trignometry来解决这个问题。假设你知道刷卡的起点(A1,B1)和刷卡的结束点(A2,B2) 圆圈中心在(X,Y)
如果我们知道的差异(x,y) - >(a1,b1)和(x,y) - >(a2,b2)所形成的角度,我们将知道是基于上述角度是正还是负来顺时针或逆时针旋转。
由一条直线构成的角度计算如下。 让红角红
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
}
}
见here知道如何计算晒黑逆。
同样计算角度绿色的值。做完之后,只需比较绿色和红色的值就可以让你知道该怎么做。
if(red - green == pi || red - green == 0){
do_nothing();
}else if(red - green > 0){
rotate_clockwise();
}else{
rotate_anticlockwise();
}
通过使用刷卡的加速度/速度数据,你可以用旋转相同的加速度/速度的圈子。
虽然三角学是数学的一种方法,但它更简单,并且需要更少的处理器能力才能完成此操作。
供参考图片:
的要旋转表盘中心点Ç。
在用户界面上,你必须得到一个刷卡起点一个和“刷卡载体” 小号,显示了如何将用户的手指移动。如果OS只提供了一个第二点乙一段时间后甲,然后计算小号 = 乙 - 甲。
要计算的小号这切线在ç为中心的圆穿过一个的组件。这将允许用户在任何地方开始他/她的滑动,并将其作为关于点C的扭矩来对待。这应该是直观的。
这并不难。圆的半径显示为向量r = A-C。垂直于这个矢量被称为“r perp”,用图片中的“图钉”符号显示。它只是点(-y,x),其中x和y是r的组成部分。
p投影到PERP(ř)的签字长度只是一个归一化点积:
这是一个标量是正的,如果旋转是逆时针围绕C,顺时针方向为负。所以标志告诉你旋转的方向。绝对值告诉你旋转多少或多快。
假设我们已经刷卡矢量小号存储为sx
和sy
和中心ç为cx
和cy
。那么伪代码只是:
r_perp_x = cy - ay; r_perp_y = ax - cx;
signed_length_p = (sx * r_perp_x + sy * r_perp_y)/sqrt(r_perp_x^2 + r_perp_y^2)
所需号码是signed_length_p
。
唯一需要注意的是忽略触碰A接近C。他们可以产生非常大的输出值或零除。这很容易解决。只要检查r的长度,并退出,如果它低于一些合理的价值。
如果你目前的解决方案对你来说“几乎没有问题” - 最简单的做法是......只是两个区域固定它:
现在你的图像顺时针您的旋转,每当用户刷卡
- 右或上(开始A区)
- 向右或向下(B区启动)
- 向左或向下(始于区d)
- 向左或向上(C区启动)
....其他 - 逆时针旋转它。
我已经做了类似的东西与Xamarin.iOS但我怀疑你想看到C#代码,所以也许这GitHub的项目会给你必要的信息: