Reposition CGPath/UIBezierPath in View

后端 未结 4 863
梦如初夏
梦如初夏 2021-02-03 10:32

Is it possible to reposition an already drawn CGPath/UIBezierPath on a view? I would like to move or change a path\'s position then perhaps recall the drawinRect method to just

相关标签:
4条回答
  • 2021-02-03 10:48

    /// Provide cgpath to it and tanslate it by given point.

    func translate(path : CGPath?, by point: CGPoint) -> CGPath? {
    
        let bezeirPath = UIBezierPath()
        guard let prevPath = path else {
            return nil
        }
        bezeirPath.cgPath = prevPath
        bezeirPath.apply(CGAffineTransform(translationX: point.x, y: point.y))
    
        return bezeirPath.cgPath
    }
    
    0 讨论(0)
  • 2021-02-03 10:57

    I did it a bit different from other answers above.

    Let's suppose you want to move a circle, first I define its center coordinates and radius in global variables, like this:

    var center: CGPoint = CGPoint(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2)
    var radius: CGFloat = 10
    

    I draw this circle like in the code bellow:

    override func draw(_ rect: CGRect) {
        super.draw(rect)  
        drawCircle()
    }
    
    func drawCircle() {
        let circle = UIBezierPath(
            arcCenter: self.center,
            radius: CGFloat(self.radius),
            startAngle: CGFloat(0),
            endAngle: CGFloat(2*Double.pi),
            clockwise: true)
    
        let circleLayer = CAShapeLayer()
            circleLayer.path = circle.cgPath
            circleLayer.fillColor = UIColor.clear.cgColor
            circleLayer.strokeColor = UIColor.black.cgColor
            circleLayer.lineWidth = 10.0
            layer.addSublayer(circleLayer)
    }
    

    Inside the UIView, I have a touchesMoved(), like this:

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
        if let touch = touches.first {
            let pos = touch.location(in: self)
    
            if (pow(pos.x-self.center.x,2) + pow(pos.y-self.center.y,2) <= pow(self.radius,2)){
                    self.center = CGPoint(x: pos.x, y: pos.y)
            }
    
            setNeedsDisplay()
        }
    }
    

    Everytime the touch is inside the circle, its center coordinates are updated and the UIView is redrawn with setNeedDisplay(), so the circle moves.

    Hope it helps someone!

    0 讨论(0)
  • 2021-02-03 10:58

    /// Translate cgPath from its center to give point.No need to move shape layer .Moving path will make app smooth

    func translate(path : CGPath?, by point: CGPoint) -> CGPath? {
    
        let bezeirPath = UIBezierPath()
        guard let prevPath = path else {
            return nil
        }
        bezeirPath.cgPath = prevPath
        bezeirPath.apply(CGAffineTransform(translationX: point.x, y: point.y))
    
        return bezeirPath.cgPath
    }
    
    0 讨论(0)
  • 2021-02-03 11:07

    From your question it sounds like you are drawing the path using Core Graphics inside drawRect: (as compared to using a CAShapeLayer) so I'll explain the version first.

    Moving a CGPath

    You can create a new path by transforming another path. A translation transform moves the transformed object a certain distance in x and y. So using a translation transform you can move your existing path a certain number of points in both x and y.

    CGAffineTransform translation = CGAffineTransformMakeTranslation(xPixelsToMove,
                                                                     yPixelsToMove);
    CGPathRef movedPath = CGPathCreateCopyByTransformingPath(originalCGPath,
                                                             &translation);
    

    Then you could use the movedPath to draw the same way you are already doing.

    You could also change modify the same path

    yourPath = CGPathCreateCopyByTransformingPath(yourPath,
                                                  &translation);
    

    and simply redraw it.

    Moving a shape layer

    If you are using a shape layer, moving it is even easier. Then you only have to change the position of the layer using the position property.

    Update:

    If you want to use a shape layer you can simply create a new CAShapeLayer and set its path to be your CGPath. You will need QuartzCore.framework for this since CAShapeLayer is part of Core Animation.

    CAShapeLayer *shape = [CAShapeLayer layer];
    shape.path = yourCGParth;
    shape.fillColor = [UIColor redColor].CGColor;
    
    [someView.layer addSublayer:shape];
    

    Then to move the shape you simply change its position.

    shape.position = thePointYouWantToMoveTheShapeTo;
    
    0 讨论(0)
提交回复
热议问题