【问题标题】:Using drawRect to draw & animate two graphs. A background graph, and a foreground graph使用 drawRect 绘制和动画两个图形。背景图和前景图
【发布时间】:2016-09-12 16:01:01
【问题描述】:

我正在使用 drawRect 绘制一个非常简单的形状(下图中为深蓝色)。

我希望这个动画从左到右,以便它增长。这里需要注意的是,我需要有一个灰色的“最大”背景,如图像的顶部所示。

现在,我通过覆盖一个白色视图来模拟这个动画,然后设置它的大小,这样看起来蓝色的动画就在右边。虽然这有效......我需要背景灰色形状始终存在。使用我的叠加白色视图,这不起作用。

这是绘制“当前代码”版本的代码:

    let context = UIGraphicsGetCurrentContext()
    CGContextMoveToPoint(context, 0, self.bounds.height - 6)
    CGContextAddLineToPoint(context, self.bounds.width, 0)
    CGContextAddLineToPoint(context, self.bounds.width, self.bounds.height)
    CGContextAddLineToPoint(context, 0, self.bounds.height)
    CGContextSetFillColorWithColor(context,UIColor(red: 37/255, green: 88/255, blue: 120/255, alpha: 1.0).CGColor)
    CGContextDrawPath(context, CGPathDrawingMode.Fill)

如何使蓝色部分从左到右设置动画,同时保持图形的灰色“最大”部分始终可见?

【问题讨论】:

    标签: ios swift animation drawrect cgcontextdrawpath


    【解决方案1】:

    drawRect 正在生成静态图片。要获得您所说的动画,我会推荐以下内容:

    1. 使用 CoreAnimation 制作动画
    2. 使用 UIBezierPath 制作您需要的形状
    3. 使用 CALayer 的蒙版在所需形状内设置动画

    这是 Playground 的示例代码:

    import UIKit
    import QuartzCore
    import XCPlayground
    
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 40))
    XCPlaygroundPage.currentPage.liveView = view
    
    let maskPath = UIBezierPath()
    
    maskPath.moveToPoint(CGPoint(x: 10, y: 30))
    maskPath.addLineToPoint(CGPoint(x: 10, y: 25))
    maskPath.addLineToPoint(CGPoint(x: 100, y: 10))
    maskPath.addLineToPoint(CGPoint(x: 100, y: 30))
    maskPath.closePath()
    
    let maskLayer = CAShapeLayer()
    maskLayer.path = maskPath.CGPath
    maskLayer.fillColor = UIColor.whiteColor().CGColor
    
    let rectToAnimateFrom = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 97, height: 40))
    let rectToAnimateTo = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 0, height: 40))
    
    let layerOne = CAShapeLayer()
    layerOne.path = maskPath.CGPath
    layerOne.fillColor = UIColor.grayColor().CGColor
    
    let layerTwo = CAShapeLayer()
    layerTwo.mask = maskLayer
    layerTwo.fillColor = UIColor.greenColor().CGColor
    
    view.layer.addSublayer(layerOne)
    view.layer.addSublayer(layerTwo)
    
    let animation = CABasicAnimation(keyPath: "path")
    animation.fromValue = rectToAnimateFrom.CGPath
    animation.toValue = rectToAnimateTo.CGPath
    animation.duration = 1
    animation.repeatCount = 1000
    animation.autoreverses = true
    
    layerTwo.addAnimation(animation, forKey: "Nice animation")
    

    【讨论】:

    • @SVGred - 哇,太棒了!在大多数情况下,这正是我所需要的!我需要稍微修改一下,但那是我的事。在我对图形的初始实现中,我将 UIView 子类化为覆盖 func drawRect(rect: CGRect)。我不需要为您的版本覆盖 drawRect 吗?另外 - 你能解释一下最后一行吗? (layerTwo.addAnimation) 我也将您的帖子编辑为 swift 2.3 语法。对我来说很好玩!
    • @SVGreg 使用了多个 Swift 版本,很高兴提及您在哪个版本中编写答案。
    • @Joe:drawRect 仅用于在视图内绘制自定义内容。答案是 - 不 - 你不需要重写 drawRect 来使用我的代码。 addAnimation 实际上是运行你需要的动画。您可以将其自定义为您喜欢的任何动画。
    • @Dravidian 代码很简单,不使用特定的语言指令/功能。但无论如何 - 好建议。
    • @SVGreg 感谢您的跟进。我让它顺利地满足了我的愿望。
    【解决方案2】:

    在您的代码中,我只看到您绘制了一次图形,为什么不先绘制灰色部分,然后再绘制蓝色部分。

    我认为在drawRect函数中实现动画效率不够。

    你可以看看Facebook的Shimmer Example,它模拟了iPhone解锁动画的效果。它使用遮罩层。这个想法也适用于您的示例。

    另外,Facebook 的pop framework 可以简化您的工作。

    【讨论】:

    • "在你的代码中,我只看到你画了一次图形,为什么不先画灰色部分,再画蓝色部分。" - 这就是计划,只要我想出一种动画方法,或者可能动画蓝色层的蒙版。感谢您对框架的建议,但我想保持这一切都是原生的,没有任何第三方。
    猜你喜欢
    • 2023-03-08
    • 2013-04-10
    • 1970-01-01
    • 2010-10-23
    • 2010-12-09
    • 1970-01-01
    • 2014-11-25
    相关资源
    最近更新 更多