Draw images evenly spaced along a path in iOS

后端 未结 2 1591
长情又很酷
长情又很酷 2021-01-01 03:13

What I want to do is move my finger across the screen (touchesMoved) and draw evenly spaced images (perhaps CGImageRefs) along the points generated by the touchesMoved. I ca

相关标签:
2条回答
  • 2021-01-01 03:15

    Assuming that you already have code that tracks the user's touch as they move their touch around the screen, it sounds like you want to detect when they have moved a distance equal to the length of your image, at which time you want to draw another copy of your image under their touch.

    To achieve this, I think you will need to:

    • calculate the length (width) of your image
    • implement code to draw copies of your image onto your view, rotated to any angle
    • each time the user's touch moves (e.g. in touchesMoved:):
      • calculate the delta of the touch each time it moves and generate the "length" of that delta (e.g. something like sqrt(dx^2 + dy^2))
      • accumulate the distance since the last image was drawn
      • if the distance has reached the length of your image, draw a copy of your image under the touch's current position, rotated appropriately (probably according to the vector from the position of the last image to the current position)

    How does that sound?

    0 讨论(0)
  • 2021-01-01 03:32

    First of all HUGE props go out to Kendall. So, based on his answer, here is the code to take a UIImage, draw it on screen along a path (not a real pathRef, just a logical path created by the points) based on the distance between the touches and then rotate the image correctly based on the VECTOR of the current and previous points. I hope you like it:

    First you need to load an image to be used as a CGImage over and over again:

    NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"arrow.png" ofType:nil];
      UIImage *img = [UIImage imageWithContentsOfFile:imagePath];
      image = CGImageRetain(img.CGImage);
    

    make sure in your dealloc that you call

     CGImageRelease(image);
    

    then in touchesBegan, just store the starting point in a var that is scoped outside the method (declare it in your header like this :) in this case I am drawing into a UIView

    @interface myView : UIView {
        CGPoint lastPoint;
        }
    @end
    

    then in touches Began:

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    

    {

    UITouch *touch = [touches anyObject];
    lastPoint = [touch locationInView:self];
    

    }

    and finally in touchesMoved, draw the bitmap to the screen and then when your distance has moved enough (in my case 73, since my image is 73 pixels x 73 pixels) draw that image to the screen, save the new image and set lastPoint equal to 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;
    }
    

    this will create an image that looks like this :

    enter image description here

    Going to add the following (with some changes to the above code in order to try and fill in the voids where touchesMoved is missing some points when you move fast:

    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);
    }
    
    0 讨论(0)
提交回复
热议问题