【问题标题】:Draw images evenly spaced along a path in iOS在 iOS 中沿路径均匀地绘制图像
【发布时间】:2011-08-05 03:42:17
【问题描述】:

我想要做的是在屏幕上移动我的手指 (touchesMoved),然后沿着 touchesMoved 生成的点绘制均匀分布的图像(可能是 CGImageRefs)。我可以画线,但我想要生成的是看起来像这样的东西(对于这个例子,我使用的是箭头的图像,但它可以是任何图像,可以是我的狗的照片:))主要是以在 iPhone 或 iPad 上用手指绘图时获得均匀分布的图像。

【问题讨论】:

    标签: ios drawing core-graphics


    【解决方案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 必须相对于箭头的方向。
    猜你喜欢
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多