绘制动画线条

20

我想在屏幕中央绘制一条线,并使其像蛇一样动起来。

以下是我想要制作的逐步动画:

图片描述

我该如何实现这个效果?


1
你现在尝试了什么?你用来生成这条线的代码是什么?能否再详细说明一下? - Mr. Xcoder
我尝试过使用形状图层并对其进行动画处理,但无论如何都没有成功。如果需要帮助,请告知。 - SwiftStudier
3
代码将非常有帮助,因为我们无法读取思维。 - Mr. Xcoder
1
在 iOS 或 macOS 中?顺便说一句,即使你的尝试没有成功,你也应该分享你所尝试的内容。 - Rob
4个回答

80

您可以在CAShapeLayer上动画绘制path的末尾,例如:

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
}

这将产生:

stroked path

显然,您可以根据自己的兴趣更改 UIBezierPath。例如,路径中可以包含空格。或者你甚至不需要有直角路径:

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))

您还可以在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")

产生的结果:

enter image description here

CoreAnimation 让您对轮廓路径的渲染具有很高的控制权。


我该如何创建两个同时进行的动画? - ScottyBlades
如果你想在同一层上进行多个动画,可以像我的最终示例那样操作。如果你想同时对不同的图层/视图进行动画处理,也可以直接操作。如果你尝试了某些操作但没有达到预期效果,可以发布自己的问题,展示你的代码,描述/展示它实现了什么,以及你想要实现什么。 - Rob
好的。完成:https://stackoverflow.com/questions/49593397/how-do-i-animate-two-views-simultaneously-in-swift-programmatically - ScottyBlades
view.layer.addSublayer(shapeLayer) 这是最后一行代码。 - J A S K I E R

4
我的需求类似,希望让一个形状的运动在场景中画出一条线,但是在CAShapeLayer的动画和SKScene的动画同步方面遇到了很大的困难。
因此我采用了不同的方法:
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)

结果:

输入图像描述


0

这种技术也可以使用,它被添加为边框,您可以随意塑造它。首先创建路径,然后根据路径绘制线条。

    let path = UIBezierPath()

我根据我的需求给出了x和y的值,您可以根据自己的需要进行更改。

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

就这些了。希望能对某些人有所帮助,因为我也是在花费几个小时的努力后才实现了这一点,因为没有找到确切的解决方案。也请查看此链接:

https://github.com/Shahijabeen/BorderAnimation


0
一种方法是使用带有背景颜色的UIView。尝试像这样做。
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)
}

通过这个,你可以实现任意数量的红线移动。

另一种方法是实际绘制一条线。我不会详细介绍,但建议参考this article

最后一件事...在Stack Overflow上,我们欣赏那些在提问之前展示他们已经做了适当的研究的人。使用谷歌,我能够快速找到许多关于如何做你想要的事情的教程。尝试自己进行研究,因为通常教程会比Stack Overflow的答案提供更多重要的细节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接