CAShapeLayer的位置不正确 [英] Incorrect position of CAShapeLayer

查看:299
本文介绍了CAShapeLayer的位置不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为viewProgressUIView.它是图像中的白框.我想要一个圆形进度条,它是图像中的绿色圆圈.进度栏应留在白框内,但是您可以看到它已经消失了.

I have a UIView called viewProgress. It is the white box in the image. I want a circular progress bar, which is the green circle in the image. The progress bar should stay within the white box, but as you can see it is way off.

如何使其保留在viewProgress内部? 这里有我的动画功能:

How do I make it stay inside the viewProgress? Here you have my animation function:

func animateView() {

        let circle = viewProgress // viewProgress is a UIView

        var progressCircle = CAShapeLayer()

        let circlePath = UIBezierPath(arcCenter: circle.center, radius: circle.bounds.midX, startAngle: -CGFloat(M_PI_2), endAngle: CGFloat(3.0 * M_PI_2), clockwise: true)

        progressCircle = CAShapeLayer ()
        progressCircle.path = circlePath.CGPath
        progressCircle.strokeColor = UIColor.whiteColor().CGColor
        progressCircle.fillColor = UIColor.clearColor().CGColor
        progressCircle.lineWidth = 10.0

        circle.layer.addSublayer(progressCircle)

        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0
        animation.toValue = 0.4
        animation.duration = 1
        animation.fillMode = kCAFillModeForwards
        animation.removedOnCompletion = false

        progressCircle.addAnimation(animation, forKey: "ani")
    }

我只是在viewDidLoad()

推荐答案

基本上,您有几个问题:

Basically u have few problems:

  1. 图层的位置不正确-框架应等于parentView中父图层的边界
  2. 您的动画只能播放一次-如果您想使其无限播放,请添加animation.repeatCount = MAXFLOAT
  3. 确保所有尺寸正确-在layoutSubviews中重新创建图层,并删除先前创建的图层
  4. UIBezierPath(arcCenter...将从rightSide开始路径,您也可以使用更简单的变体,例如UIBezierPath(ovalInRect.考虑到这一点,如果您想在圆的最上端开始绘制,则还需要旋转M_PI_2的图层
  5. U还应记住,线宽为10时,您的圆弧路径的一半将由parentView的clipSubviews提供.为防止这种情况,请修改parentLayer rect
  6. 您可能还想改善lineCap的可视化效果,可以将其设置为圆形"样式
  7. 如果您不想从动画中获取完成事件,则不需要
  8. progressCircle.addAnimation(animation, forKey: "ani")动画键-在您的情况下,我看到没有delegate且没有removeOnCompletion标志设置为false,因此假设您不希望这样做.真的需要它
  1. incorrect position of your layer - frame should be equal to bounds of parent layer in parentView
  2. you animation will play only once - if u want to make it infinite add something like animation.repeatCount = MAXFLOAT
  3. to make sure that all size correct - in layoutSubviews recreate layers, with removing previously created one
  4. UIBezierPath(arcCenter... will start path from rightSide, u can also use simpler variant like UIBezierPath(ovalInRect. With this in mind u also need to rotate layer for M_PI_2 if u want to make start of drawing in the very top of circle
  5. U should also take in mind that with line width 10, half of u'r circle path will be catted by clipSubviews of parentView. To prevent this use modified parentLayer rect
  6. U can also maybe want to improve visualization of lineCap, buy setting it to "round" style
  7. progressCircle.addAnimation(animation, forKey: "ani") key for anim not required if u dont want to get completion event from animation - i your case i see there is no delegate and no removeOnCompletion flag setted to false, so make assumption that u don`t actually need it

记住所有这些代码就像:

Keeping this all in mind code can be like :

let circle = UIView(frame: CGRectMake(100, 100, 100, 100)) // viewProgress is a UIView
circle.backgroundColor = UIColor.greenColor()
view.addSubview(circle)

var progressCircle = CAShapeLayer()
progressCircle.frame = view.bounds

let lineWidth:CGFloat = 10
let rectFofOval = CGRectMake(lineWidth / 2, lineWidth / 2, circle.bounds.width - lineWidth, circle.bounds.height - lineWidth)

let circlePath = UIBezierPath(ovalInRect: rectFofOval)

progressCircle = CAShapeLayer ()
progressCircle.path = circlePath.CGPath
progressCircle.strokeColor = UIColor.whiteColor().CGColor
progressCircle.fillColor = UIColor.clearColor().CGColor
progressCircle.lineWidth = 10.0
progressCircle.frame = view.bounds
progressCircle.lineCap = "round"

circle.layer.addSublayer(progressCircle)
circle.transform = CGAffineTransformRotate(circle.transform, CGFloat(-M_PI_2))

let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = 1.1
animation.duration = 1
animation.repeatCount = MAXFLOAT
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

progressCircle.addAnimation(animation, forKey: nil)

结果实际上是这样的:

注意: 如果您想动画化动画层的旋转,还应该在动画组中添加其他动画

Note: If u want to animate rotation of animated layer u should also add additional animation in to anim group

这篇关于CAShapeLayer的位置不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆