在 iOS 中沿路径均匀地绘制图像
Posted
技术标签:
【中文标题】在 iOS 中沿路径均匀地绘制图像【英文标题】:Draw images evenly spaced along a path in iOS 【发布时间】:2011-08-05 03:42:17 【问题描述】:我想要做的是在屏幕上移动我的手指 (touchesMoved),然后沿着 touchesMoved 生成的点绘制均匀分布的图像(可能是 CGImageRefs)。我可以画线,但我想要生成的是看起来像这样的东西(对于这个例子,我使用的是箭头的图像,但它可以是任何图像,可以是我的狗的照片:))主要是以在 iPhone 或 iPad 上用手指绘图时获得均匀分布的图像。
【问题讨论】:
【参考方案1】:首先,巨大的道具送给肯德尔。因此,根据他的回答,这里是获取 UIImage 的代码,根据触摸之间的距离沿路径(不是真正的 pathRef,只是由点创建的逻辑路径)在屏幕上绘制它,然后旋转图像正确地基于当前点和先前点的向量。我希望你喜欢它:
首先,您需要反复加载要用作 CGImage 的图像:
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"arrow.png" ofType:nil];
UIImage *img = [UIImage imageWithContentsOfFile:imagePath];
image = CGImageRetain(img.CGImage);
确保在你调用的 dealloc 中
CGImageRelease(image);
然后在 touchesBegan 中,只需将起点存储在方法范围之外的 var 中(像这样在标题中声明它:)在这种情况下,我正在绘制 UIView
@interface myView : UIView
CGPoint lastPoint;
@end
然后开始接触:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self];
最后在 touchesMoved 中,将位图绘制到屏幕上,然后当您的距离移动足够大时(在我的情况下是 73,因为我的图像是 73 像素 x 73 像素)将该图像绘制到屏幕上,保存新图像并设置 lastPoint 等于 currentPoint
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *touch = [touches anyObject];
currentPoint = [touch locationInView:self];
double deltaX = lastPoint.x - currentPoint.x;
double deltaY = lastPoint.y - currentPoint.y;
double powX = pow(deltaX,2);
double powY = pow(deltaY,2);
double distance = sqrt(powX + powY);
if (distance >= 73)
lastPoint = currentPoint;
UIGraphicsBeginImageContext(self.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSaveGState(UIGraphicsGetCurrentContext());
float angle = atan2(deltaX, deltaY);
angle *= (M_PI / 180);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(currentPoint.x, currentPoint.y, 73, 73),[self CGImageRotatedByAngle:image angle:angle * -1]);
CGContextRestoreGState(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
distance = 0;
- (CGImageRef)CGImageRotatedByAngle:(CGImageRef)imgRef angle:(CGFloat)angle
CGFloat angleInRadians = angle * (M_PI / 180);
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect imgRect = CGRectMake(0, 0, width, height);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL,
rotatedRect.size.width,
rotatedRect.size.height,
8,
0,
colorSpace,
kCGImageAlphaPremultipliedFirst);
CGContextSetAllowsAntialiasing(bmContext, FALSE);
CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(bmContext,
+(rotatedRect.size.width/2),
+(rotatedRect.size.height/2));
CGContextRotateCTM(bmContext, angleInRadians);
CGContextTranslateCTM(bmContext,
-(rotatedRect.size.width/2),
-(rotatedRect.size.height/2));
CGContextDrawImage(bmContext, CGRectMake(0, 0,
rotatedRect.size.width,
rotatedRect.size.height),
imgRef);
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
CFRelease(bmContext);
[(id)rotatedImage autorelease];
return rotatedImage;
这将创建一个看起来像这样的图像:
要添加以下内容(对上面的代码进行一些更改,以便尝试填充 touchesMoved 在您快速移动时缺少一些点的空白:
CGPoint point1 = CGPointMake(100, 200);
CGPoint point2 = CGPointMake(300, 100);
double deltaX = point2.x - point1.x;
double deltaY = point2.y - point1.y;
double powX = pow(deltaX,2);
double powY = pow(deltaY,2);
double distance = sqrt(powX + powY);
distance = 0;
for (int j = 1; j * 73 < distance; j++ )
double x = (point1.x + ((deltaX / distance) * 73 * j));
double y = (point1.y + ((deltaY / distance) * 73 * j));
NSLog(@"My new point is x: %f y :%f", x, y);
【讨论】:
要添加以下内容(对上面的代码进行一些更改,以便尝试填补 touchesMoved 在快速移动时缺少一些点的空白: 感谢您的帮助,我如何绘制 x 和 y 点请建议我 为什么在for循环前的最低码框里设置distance=0?最底部的代码框如何帮助快速运动?【参考方案2】:假设您已经有代码在用户在屏幕上移动触摸时跟踪他们的触摸,听起来您想检测他们何时移动了等于图像长度的距离,此时您想要在他们的触摸下绘制您的图像的另一个副本。
要实现这一点,我认为您需要:
计算图片的长度(宽度) 实现代码以将图像副本绘制到视图上,并旋转到任意角度 每次用户的触摸移动时(例如在 touchesMoved 中:): 计算每次触摸的增量并生成该增量的“长度”(例如 sqrt(dx^2 + dy^2)) 累积距离上一张图片绘制后的距离 如果距离已达到图像的长度,则在触摸的当前位置下绘制图像的副本,并适当旋转(可能根据从最后一张图像的位置到当前位置的矢量)听起来怎么样?
【讨论】:
让我试一试。我从来没有想过要根据距离放置图像。我在想我需要在路径上添加或调整点。 正是我正在寻找的,当我清理它时将发布工作代码。 (你不知道如何计算一个合适的向量吗:)) 在实现这一点并发布您的代码方面做得很好。看起来您需要稍微偏移绘图以使箭头的尖端指向下一个的底部。尝试计算另一个向量,这次从图像的方向旋转 90 度,长度等于图像宽度的一半,然后将该向量添加到 currentPoint.x 和 .y 中,看看它的外观。 我几乎是 Forest Gumped 穿过矢量的东西。那么图像方向是当前角度吗?还是我创建一个任意点,距离我的图像宽度的一半,但在右侧 90 度......好吧,你看我对向量的理解只有 45 分钟 :) 是的!正如您所知道的,“矢量”只是指 (x, y) 位置,所以现在您需要做的就是找到正确的偏移量,以使您的一系列箭头看起来平滑。我没有对此进行测试,但在我看来,将每个箭头“左”或“右”移动其宽度的一半应该可以很好地对齐它们,这就是 90 度旋转的来源:“左”/“右” shift 必须相对于箭头的方向。以上是关于在 iOS 中沿路径均匀地绘制图像的主要内容,如果未能解决你的问题,请参考以下文章