Ios 如何在我的swift应用程序中设置绘制svg路径的动画?
在我的ios swift应用程序中,我有Ios 如何在我的swift应用程序中设置绘制svg路径的动画?,ios,swift,svg,swift3,uibezierpath,Ios,Swift,Svg,Swift3,Uibezierpath,在我的ios swift应用程序中,我有SVG文件-它是一个地图标记的形状,现在我想用动画来绘制它。由于使用了pocketSVG,我成功地显示了图形。我的代码如下: @IBOutlet weak var mainLogoView: UIView! override func viewDidLoad() { super.viewDidLoad() let url = Bundle.main.url(forResource: "mainLogo", withExtension:
SVG
文件-它是一个地图标记的形状,现在我想用动画来绘制它。由于使用了pocketSVG
,我成功地显示了图形。我的代码如下:
@IBOutlet weak var mainLogoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "mainLogo", withExtension: "svg")!
//initialise a view that parses and renders an SVG file in the bundle:
let svgImageView = SVGImageView.init(contentsOf: url)
//scale the resulting image to fit the frame of the view, but
//maintain its aspect ratio:
svgImageView.contentMode = .scaleAspectFit
//layout the view:
svgImageView.translatesAutoresizingMaskIntoConstraints = false
mainLogoView.addSubview(svgImageView)
svgImageView.topAnchor.constraint(equalTo: mainLogoView.topAnchor).isActive = true
svgImageView.leftAnchor.constraint(equalTo: mainLogoView.leftAnchor).isActive = true
svgImageView.rightAnchor.constraint(equalTo: mainLogoView.rightAnchor).isActive = true
svgImageView.bottomAnchor.constraint(equalTo: mainLogoView.bottomAnchor).isActive = true
Timer.scheduledTimer(timeInterval: TimeInterval(2), target: self, selector: "functionHere", userInfo: nil, repeats: false)
}
func functionHere(){
self.performSegue(withIdentifier: "MainSegue", sender: nil)
}
func animateSVG(From startProportion: CGFloat, To endProportion: CGFloat, Duration duration: CFTimeInterval = animationDuration) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration
animation.fromValue = startProportion
animation.toValue = endProportion
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
svgLayer.strokeEnd = endProportion
svgLayer.strokeStart = startProportion
svgLayer.add(animation, forKey: "animateRing")
}
因此,基本上在我的ViewController中,我在故事板上添加了一个名为mainLogoView
的视图,然后在那里显示SVG文件。现在,因为它是一个形状标记,非常类似于:我想画它-在2秒钟的时间里,我想画出圆圈周围的形状
我怎么做
====编辑:
按照Josh的建议,我注释掉了我的viewdiload
中的大部分代码,取而代之的是:
let url = Bundle.main.url(forResource: "mainLogo", withExtension: "svg")!
for path in SVGBezierPath.pathsFromSVG(at: url)
{
var layer:CAShapeLayer = CAShapeLayer()
layer.path = path.cgPath
layer.lineWidth = 4
layer.strokeColor = orangeColor.cgColor
layer.fillColor = UIColor.white.cgColor
mainLogoView.addSubview(layer)
}
但是现在最后一行抛出了一个错误
Cannot convert value of type 'CAShapeLayer' to expected argument type 'UIView'
另外,在编辑了我的代码之后,您能给我一个提示吗?我如何在这里使用Josh的方法?而不是使用imageView方法将SVG转换为cgPath。将此路径指定给CAShapeLayer并将该形状层添加到视图中。可以按如下方式设置CAShapeLayer的endStroke动画:
@IBOutlet weak var mainLogoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "mainLogo", withExtension: "svg")!
//initialise a view that parses and renders an SVG file in the bundle:
let svgImageView = SVGImageView.init(contentsOf: url)
//scale the resulting image to fit the frame of the view, but
//maintain its aspect ratio:
svgImageView.contentMode = .scaleAspectFit
//layout the view:
svgImageView.translatesAutoresizingMaskIntoConstraints = false
mainLogoView.addSubview(svgImageView)
svgImageView.topAnchor.constraint(equalTo: mainLogoView.topAnchor).isActive = true
svgImageView.leftAnchor.constraint(equalTo: mainLogoView.leftAnchor).isActive = true
svgImageView.rightAnchor.constraint(equalTo: mainLogoView.rightAnchor).isActive = true
svgImageView.bottomAnchor.constraint(equalTo: mainLogoView.bottomAnchor).isActive = true
Timer.scheduledTimer(timeInterval: TimeInterval(2), target: self, selector: "functionHere", userInfo: nil, repeats: false)
}
func functionHere(){
self.performSegue(withIdentifier: "MainSegue", sender: nil)
}
func animateSVG(From startProportion: CGFloat, To endProportion: CGFloat, Duration duration: CFTimeInterval = animationDuration) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration
animation.fromValue = startProportion
animation.toValue = endProportion
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
svgLayer.strokeEnd = endProportion
svgLayer.strokeStart = startProportion
svgLayer.add(animation, forKey: "animateRing")
}
我确实遇到了同样的问题,这是我的解决方案。svgWidth、svgHeight是svg标记的宽度和高度
let url = Bundle.main.url(forResource: "mainLogo", withExtension: "svg")!
for path in SVGBezierPath.pathsFromSVG(at: url)
{
var layer:CAShapeLayer = CAShapeLayer()
layer.transform = CATransform3DMakeScale(CGFloat(mainLogoView.frame.width/svgWidth), CGFloat(mainLogoView.frame.height/svgHeight), 1)
layer.path = path.cgPath
layer.lineWidth = 4
layer.strokeColor = orangeColor.cgColor
layer.fillColor = UIColor.white.cgColor
layer.transform = CATransform3DMakeScale(2, 2, 1)
mainLogoView.layer.addSublayer(layer)
}
嗯,你能提供一个更详细的代码示例吗?我不确定这里的strokeEnd
和animateRing
是什么,我也不知道如何准确地将svg转换为cgPath:(您应该更改动画标识符,但无论如何它完全是任意的;它只是您动画的名称。strokeEnd是CAShapeLayer的一部分。请参阅文档:嗯,好的,您能给我一些示例,说明如何在代码中准确调用此函数吗?animateSVG(从:0到:1,持续时间:2)在两秒钟内将路径从路径长度的0%划到100%。请检查我原始问题的编辑部分好吗?层不是UIView,但UIView有层属性。您需要将shapeLayer作为子层添加到层中。MainLogView.layer.addSublayer(层)。此外,如果您有多个路径(如果链接它们,您可以这样做),动画将不正确。目的是您有一个路径,并且该路径中的所有点都按正确的顺序排列。谢谢,我最终成功地绘制了它:)我使用了:for path in SVGBezierPath.pathsFromSVG(at:url){var layer:CAShapeLayer=CAShapeLayer()
您应该将SVG文件缩放到正确的大小。如果您需要可变大小,则需要在viewDidLayoutSubviews中计算它,并使用图层的.transform属性进行缩放。Josh,您能不能这样做并编写一段简单的代码?我怎么能做到这一点?我不知道它是如何工作的,也找不到可靠的教程:(