美文网首页
iOS开发中利用PaintCode实现时钟动画

iOS开发中利用PaintCode实现时钟动画

作者: MambaYong | 来源:发表于2021-11-03 16:16 被阅读0次

    本文阅读时长30分钟,主要介绍PaintCodeiOS开发中的使用,利用PaintCode绘制简单的矢量图形,并生成相应的iOS代码,利用生成的图形代码引用到相应的工程中实现动画效果。

    PaintCode的介绍


    PaintCodeMac端很好用的一款矢量绘图软件,相较于Sketch不同的是可以生成基于Core GraphicsObjective-CSwift的图形代码,使用起来非常方便,软件是收费的,有钱的话可以支持正版!

    时钟主体绘制

    打开软件后如下图所示:


    右边的Canvas是属性检查器,用于调整画布的属性。将canvas命名为Stopwatch,将宽度和高度设为250,将Code Export 设置为StyleKit Drawing& Image Method

    画布左上角是主原点,所有图形的位置都是从这个像素点计算而来。

    在工具条的上方选择Oval


    在画布上画一个圆,并在右边的属性检查器上设置Oval的宽和高都为220xy方向的坐标为1530

    在右边的Fill选项中点击箭头选择Add new Color,并将新颜色的取名为Base Color并修改十六进制的值为#118DDA

    接着选择Rect矩形,绘制矩形并设置属性为:
    • X:114
    • Y:2
    • W:22
    • H:34

      再次如下图拖拽二个矩形,并设置大矩形的宽高为3020,小矩形的宽高都为20,位置先暂时拖到合适的位置,然后选中大矩形,在右侧属性面板中选中Transforms后设置Rotation-45进行旋转操作。

      拖拽小的正方形到合适的位置,并选择工具条上方的Union合并按钮进行合并,并设置合并后的xy坐标值为20025

      完成后如下图所示,按住Command-S保存为PaintCodeTest

    时钟指针绘制

    选中Stopwatch画布,然后在画布之外的空白地方右键会出现Add New Canvas,选中默认的(250×250) Size of Stopwatch创建一个尺寸大小与Stopwatch相同的画布,将新画布命名为Stopwatch_Hand并将高度设为220,选择Drawing Method模式并调整背景颜色为黑色。


    回到Stopwatch画布,绘制一个白色圆,其半径为30,并拖拽到时钟表盘的中心(Paintcode会有对齐指示,对齐后白色小圆的坐标值为(110,125)),绘制一个白色长条矩形,其宽和高分别为8115,并拖拽到合适位置。

    在合并之前需要调整合并后的中心点以便指针可以绕着表盘的中心进行旋转,按住Shift选中白色小圆形和白色长条矩形,并在右侧属性面板下展开Transforns使得二者的相对原点可见。

    只选中白色小圆,用鼠标拖动绿色相对原点到表盘中心,可以看到Transforms下的Offset都为-15,同时白色小圆的坐标值为(125,140)

    同时选中白色小圆和长条矩形执行合并操作,可以看到相对原点在左上方。

    拖动绿色的相对原点直到更改合并后的坐标值为上一步小圆点的坐标值也即(125,140),这里不要用手动输入。

    选中合并后的指针按住Command-X然后Command-VStopwatch_Hand上,由于Stopwatch_Hand画布的高为220Stopwatch250小了30,所以调整Stopwatch_Hand指针的坐标值为(125,110)

    点击左边栏的Variables选择Angle添加变量,并将起始角度值设为0度。

    按住Crtl键点击变量右侧的空心圆圈拖动到Stopwatch_Hand画布右侧属性面板下Transforms下的Rotation处。

    导出为StyleKit

    选择StyleKit标签会展示Colors,Gradients, Shadows,Images, 和 Drawing Methods以供导出!


    点击Add Color选择Base Color添加颜色到StyleKit Colors中以便导出代码后能修改图形的颜色。

    修改右侧StyleKit相关的信息后点击硕大的Export导出按钮即可得到相应图形的swift文件。

    PaintCodeTest.swift中的自动生成的部分图形代码如下所示:
    @objc dynamic public class func drawStopwatch(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 250, height: 250), resizing: ResizingBehavior = .aspectFit) {
            //// General Declarations
            let context = UIGraphicsGetCurrentContext()!        
            //// Resize to Target Frame
            context.saveGState()
            let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 250, height: 250), target: targetFrame)
            context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
            context.scaleBy(x: resizedFrame.width / 250, y: resizedFrame.height / 250)
            //// Oval Drawing
            let ovalPath = UIBezierPath(ovalIn: CGRect(x: 15, y: 30, width: 220, height: 220))
            PaintCodeTest1.color.setFill()
            ovalPath.fill()
            //// Rectangle Drawing
            let rectanglePath = UIBezierPath(rect: CGRect(x: 114, y: 2, width: 22, height: 34))
            PaintCodeTest1.color.setFill()
            rectanglePath.fill()
            //// Bezier Drawing
            let bezierPath = UIBezierPath()
            bezierPath.move(to: CGPoint(x: 214.14, y: 25))
            bezierPath.addLine(to: CGPoint(x: 235.36, y: 46.21))
            bezierPath.addLine(to: CGPoint(x: 221.21, y: 60.35))
            bezierPath.addCurve(to: CGPoint(x: 218.21, y: 57.35), controlPoint1: CGPoint(x: 221.21, y: 60.35), controlPoint2: CGPoint(x: 220.03, y: 59.17))
            bezierPath.addLine(to: CGPoint(x: 203, y: 57.35))
            bezierPath.addCurve(to: CGPoint(x: 203, y: 42.14), controlPoint1: CGPoint(x: 203, y: 57.35), controlPoint2: CGPoint(x: 203, y: 48.06))
            bezierPath.addCurve(to: CGPoint(x: 200, y: 39.14), controlPoint1: CGPoint(x: 201.19, y: 40.33), controlPoint2: CGPoint(x: 200, y: 39.14))
            bezierPath.addLine(to: CGPoint(x: 214.14, y: 25))
            bezierPath.close()
            PaintCodeTest1.color.setFill()
            bezierPath.fill()      
            context.restoreGState()
        }
    

    引入图形文件到Xcode

    直接将生成的PaintCodeTest.swift文件引入到工程中,并新建名为Stopwatch.swiftStopwatchHand.swift的文件,在二个文件中分别添加如下代码:

    Stopwatch.swift

    import UIKit
    import Foundation
    @IBDesignable
    class Stopwatch: UIView {
        override func draw(_ rect: CGRect) {
            PaintCodeTest1.drawStopwatch()
        }
    }
    

    StopwatchHand.swift

    import UIKit
    import Foundation
    @IBDesignable
    class StopwatchHand: UIView {
        private var _angle:CGFloat = 0.0;
        override func draw(_ rect: CGRect) {
            PaintCodeTest1.drawStopwatch_Hand(frame: CGRect(x: 0, y: 0, width: bounds.size.width, height: bounds.size.height), resizing: .aspectFit, angle: angleHand)
        }
        var angleHand:CGFloat {
            set (newAngleHand) {
               _angle = newAngleHand
                setNeedsDisplay()
            }
            get {
                return _angle
            }
        }
    }
    

    打开Main.storyboard快速添加个一个UIView并设置相关约束如下:

    • Width Equals:250
    • Height Equals:250
    • Align Center X to:Superview
    • Top Space to:Top Layout Guide

    关联此UIViewStopwatch上,因为类声明为了@IBDesignable所以此时可以适时的预览。


    同样的方法添加一个UIViewStopwatch的上面,设置二者约束为大小位置都相等,设置background colorclear color并关联到StopwatchHand

    ViewController中利用定时器使时钟走起来。

    import UIKit
    class ViewController: UIViewController {
        @IBOutlet var stopWatchHandView: StopwatchHand!
        private  var myTime:Timer?;
        override func viewDidLoad() {
            super.viewDidLoad()
            stopWatchHandView.angleHand = 0.0;
        }
        override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          rotateStopWatchHand()
        }
        func rotateStopWatchHand() {
            myTime = Timer(timeInterval: 1, repeats: true, block: { [weak self](Timer) in
                self?.stopWatchHandView.angleHand = (self?.stopWatchHandView.angleHand)! - 6;
                if ((self?.stopWatchHandView.angleHand)! < -360){
                    self?.stopWatchHandView.angleHand = 0;
                }
            })
            RunLoop.current.add(myTime!, forMode: .common)
            myTime?.fire()
        }
    }
    

    总结

    利用Paintcode生成的图形代码可以大大的提高实际开发的效率,无需为复杂的图形绘制花费太多的时间,同时利用Paintcode的变量能很方便的做出复杂的动画,达到事半功倍的效果,且Paintcode使用起来非常简单,同时还支持Sketch的导入,本文在此不做过多的介绍。

    相关文章

      网友评论

          本文标题:iOS开发中利用PaintCode实现时钟动画

          本文链接:https://www.haomeiwen.com/subject/oayxzltx.html