Draw line animated

前端 未结 4 1804
终归单人心
终归单人心 2020-12-12 17:58

I want to have a line in the center of the screen and animate it like a snake

This is step by step animation I want to make

How can I do this?

相关标签:
4条回答
  • 2020-12-12 17:59

    My need was something similar - wanted to let the motion of a shape trace a line in the scene, but was having great difficulty synchronizing animation in CAShapeLayer with animation in SKScene.

    So ended up using a different approach:

    import SpriteKit
    import PlaygroundSupport
    import AVFoundation
    
    let start = CGPoint(x: 100, y: 50)
    let end = CGPoint(x: 200, y: 50)
    let control = CGPoint(x: 150, y: 100);
    var motion: SKAction = SKAction();
    
    let radius: CGFloat = 20;
    let bounds = CGRect(x: 0, y: 0, width: 400, height: 200)
    let skview = SKView(frame: bounds)
    PlaygroundPage.current.liveView = skview
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    class MyScene: SKScene,AVSpeechSynthesizerDelegate {
        var motionComplete = false
        var redline: SKShapeNode = SKShapeNode();
        var greenball: SKShapeNode = SKShapeNode();
        override func sceneDidLoad() {
    
            greenball = SKShapeNode(circleOfRadius: radius);
            greenball.position = start;
            greenball.fillColor = .green;
    
            let motionpath = CGMutablePath();
    
            motionpath.move(to: start)
            motionpath.addQuadCurve(to: end, control: control)
    
            motion = SKAction.follow(motionpath, asOffset: false, orientToPath: true,duration: 2);
    
            let linepath = CGMutablePath();
            linepath.move(to: start);
            redline = SKShapeNode(path: linepath);
            redline.strokeColor = .red;
            redline.lineWidth = 5;
    
            greenball.run(motion) {
                self.motionComplete = true;
            };
    
            self.addChild(greenball);
            self.addChild(redline);
        }
    
        override func update(_ currentTime: TimeInterval) {
    
            if (motionComplete == false) {
                let cgpath = self.redline.path as! CGMutablePath;
                cgpath.addLine(to: greenball.position);
                self.redline.path = cgpath;
    
            }
        }
    
    
    }
    
    
    
    let scene = MyScene(size: CGSize(width: 400, height: 200));
    scene.scaleMode = SKSceneScaleMode.aspectFill
    scene.size = skview.bounds.size
    skview.presentScene(scene)
    

    Result:

    0 讨论(0)
  • 2020-12-12 18:08

    This technique can also be used, its added as border you can mold it your way. First create a path and then draw lines on it accordingly

        let path = UIBezierPath()
    

    i have given x, y values according to my need, you can change it according to yours

    path.move(to: CGPoint(x: 134, y: 209))//
        path.addLine(to: CGPoint(x: (131 + 93), y: 209))// for drawing line
        path.addQuadCurve(to: CGPoint(x: (131 + 97), y: 212) , controlPoint: CGPoint(x: (131 + 93), y: 209))// for drawing a curve
        path.addLine(to: CGPoint(x: (131 + 97) , y: (209 + 33 )))
        path.addQuadCurve(to: CGPoint(x: (131 + 93), y: (209 + 37)), controlPoint:  CGPoint(x: (131 + 97) , y: (209 + 33 )))
        path.addLine(to: CGPoint(x: 135, y: (209 + 37)))
        path.addQuadCurve(to: CGPoint(x: 131, y: 209 + 33), controlPoint: CGPoint(x: 135, y: 209 + 37))
        path.addLine(to: CGPoint(x: 131, y: 213))
        path.addQuadCurve(to: CGPoint(x: 134, y: 209), controlPoint:CGPoint(x: 131, y: 213) )
         let shapelayer = CAShapeLayer()//create shape layer object
        shapelayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
        shapelayer.strokeColor = #colorLiteral(red: 0.06274510175, green: 0, blue: 0.1921568662, alpha: 1).cgColor
        shapelayer.lineWidth = 2
        shapelayer.path = path.cgPath
        view.layer.addSublayer(shapelayer)
        let animation = CABasicAnimation(keyPath: "strokeEnd")// create animation and add it to shape layer
        animation.fromValue = 0
        animation.duration = 3
        shapelayer.add(animation, forKey: "MyAnimation")
        self.shapelayer = shapelayer
    

    That's all. Hope it can help someone, as i also achieved this after a few hours effort because didn't find the exact solution. check this link as well:

    https://github.com/Shahijabeen/BorderAnimation

    0 讨论(0)
  • 2020-12-12 18:20

    You can animate the end of the stroke of a path on a CAShapeLayer, e.g.,

    weak var shapeLayer: CAShapeLayer?
    
    @IBAction func didTapButton(_ sender: Any) {
        // remove old shape layer if any
    
        self.shapeLayer?.removeFromSuperlayer()
    
        // create whatever path you want
    
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 10, y: 50))
        path.addLine(to: CGPoint(x: 200, y: 50))
        path.addLine(to: CGPoint(x: 200, y: 240))
    
        // create shape layer for that path
    
        let shapeLayer = CAShapeLayer()
        shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
        shapeLayer.strokeColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1).cgColor
        shapeLayer.lineWidth = 4
        shapeLayer.path = path.cgPath
    
        // animate it
    
        view.layer.addSublayer(shapeLayer)
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0
        animation.duration = 2
        shapeLayer.add(animation, forKey: "MyAnimation")
    
        // save shape layer
    
        self.shapeLayer = shapeLayer
    }
    

    That yields:

    Clearly, you can change the UIBezierPath to whatever suits your interests. For example, you could have spaces in the path. Or you don't even need to have rectilinear paths:

    let path = UIBezierPath()
    path.move(to: CGPoint(x: 10, y: 130))
    path.addCurve(to: CGPoint(x: 210, y: 200), controlPoint1: CGPoint(x: 50, y: -100), controlPoint2: CGPoint(x: 100, y: 350))
    

    You can also combine animation of both the start and end of the stroke in a CAAnimationGroup:

    // create shape layer for that path (this defines what the path looks like when the animation is done)
    
    let shapeLayer = CAShapeLayer()
    shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
    shapeLayer.strokeColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1).cgColor
    shapeLayer.lineWidth = 5
    shapeLayer.path = path.cgPath
    shapeLayer.strokeStart = 0.8
    
    let startAnimation = CABasicAnimation(keyPath: "strokeStart")
    startAnimation.fromValue = 0
    startAnimation.toValue = 0.8
    
    let endAnimation = CABasicAnimation(keyPath: "strokeEnd")
    endAnimation.fromValue = 0.2
    endAnimation.toValue = 1.0
    
    let animation = CAAnimationGroup()
    animation.animations = [startAnimation, endAnimation]
    animation.duration = 2
    shapeLayer.add(animation, forKey: "MyAnimation")
    

    Yielding:

    CoreAnimation gives you a lot of control over how the stroked path is rendered.

    0 讨论(0)
  • 2020-12-12 18:20

    One method is using a UIView with the background color. Try something like this.

    let screenWidth = UIScreen.main.bounds.width
    let screenHeight = UIScreen.main.bounds.height
    let redLine = UIView()
    redline.backgroundColor = UIColor.red
    redLine.frame = GCRect(x: screenWidth / 2, y: screenHeight / 2, width: 0, height: 0)
    
    UIView.animate(withDuration: 2, animations: {
        redLine.frame = GCRect(x: screenWidth / 2, y: screenHeight / 2, width: 0, height: (screenHeight / 2) - 4)
    }) { finished in
        redLine.frame = GCRect(x: screenWidth / 2, y: (screenHeight / 2) - 4, width: 0, height: 1)
    }
    

    With this, you can achieve any amount of red line movement.

    The other method is to actually draw a line. I won't go into detail about that, but would recommend this article.

    One last thing... On stack overflow we appreciate people who show they properly researched a topic before just asking a question. Using google, I was able to quickly come up with many tutorials on how to do what you are looking for. Try to do research yourself, because often a tutorial will have far more detail that is important than a stack overflow answer.

    0 讨论(0)
提交回复
热议问题