CoreGraphic框架解析 (八)—— 基于CoreGraphic的一個(gè)簡(jiǎn)單繪制示例 (四)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.10.22 星期一

前言

quartz是一個(gè)通用的術(shù)語醉拓,用于描述在iOSMAC OS X 中整個(gè)媒體層用到的多種技術(shù) 包括圖形蕾总、動(dòng)畫囤屹、音頻笑跛、適配付魔。Quart 2D 是一組二維繪圖和渲染APICore Graphic會(huì)使用到這組API飞蹂,Quartz Core專指Core Animation用到的動(dòng)畫相關(guān)的庫几苍、API和類。CoreGraphicsUIKit下的主要繪圖系統(tǒng)陈哑,頻繁的用于繪制自定義視圖妻坝。Core Graphics是高度集成于UIView和其他UIKit部分的。Core Graphics數(shù)據(jù)結(jié)構(gòu)和函數(shù)可以通過前綴CG來識(shí)別惊窖。在app中很多時(shí)候繪圖等操作我們要利用CoreGraphic框架刽宪,它能繪制字符串、圖形爬坑、漸變色等等纠屋,是一個(gè)很強(qiáng)大的工具。感興趣的可以看我另外幾篇盾计。
1. CoreGraphic框架解析(一)—— 基本概覽
2. CoreGraphic框架解析(二)—— 基本使用
3. CoreGraphic框架解析(三)—— 類波浪線的實(shí)現(xiàn)
4. CoreGraphic框架解析(四)—— 基本架構(gòu)補(bǔ)充
5. CoreGraphic框架解析 (五)—— 基于CoreGraphic的一個(gè)簡(jiǎn)單繪制示例 (一)
6. CoreGraphic框架解析 (六)—— 基于CoreGraphic的一個(gè)簡(jiǎn)單繪制示例 (二)
7. CoreGraphic框架解析 (七)—— 基于CoreGraphic的一個(gè)簡(jiǎn)單繪制示例 (三)

源碼

1. Swift

該教程最大的特點(diǎn)就是界面完全是用代碼繪制的售担,asset里面沒有任何東西赁遗,是一個(gè)完全由CoreGraphic進(jìn)行繪制的小示例。

首先看一下項(xiàng)目組織結(jié)構(gòu)族铆。

接著看一下sb中的內(nèi)容

下面就是源碼了

1. ViewController.swift
import UIKit

class ViewController: UIViewController {
  
  //Counter outlets
  @IBOutlet weak var counterView: CounterView!
  @IBOutlet weak var counterLabel: UILabel!
  
  @IBOutlet weak var containerView: UIView!
  @IBOutlet weak var graphView: GraphView!
  
  //Label outlets
  @IBOutlet weak var averageWaterDrunk: UILabel!
  @IBOutlet weak var maxLabel: UILabel!
  @IBOutlet weak var stackView: UIStackView!
  
  @IBOutlet weak var medalView: MedalView!
  
  var isGraphViewShowing = false
  
  @IBAction func pushButtonPressed(_ button: PushButton) {
    if button.isAddButton {
      counterView.counter += 1
    } else {
      if counterView.counter > 0 {
        counterView.counter -= 1
      }
    }
    counterLabel.text = String(counterView.counter)
    
    if isGraphViewShowing {
      counterViewTap(nil)
    }
    checkTotal()
  }
  
  @IBAction func counterViewTap(_ gesture:UITapGestureRecognizer?) {
    if (isGraphViewShowing) {
      //hide Graph
      UIView.transition(from: graphView,
                        to: counterView,
                        duration: 1.0,
                        options: [.transitionFlipFromLeft, .showHideTransitionViews],
                        completion:nil)
    } else {
      //show Graph
      setupGraphDisplay()
      UIView.transition(from: counterView,
                        to: graphView,
                        duration: 1.0,
                        options: [.transitionFlipFromRight, .showHideTransitionViews],
                        completion: nil)
    }
    isGraphViewShowing = !isGraphViewShowing
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    counterLabel.text = String(counterView.counter)
    checkTotal()
  }
  
  func setupGraphDisplay() {
    
    let maxDayIndex = stackView.arrangedSubviews.count - 1
    
    //1 - replace last day with today's actual data
    graphView.graphPoints[graphView.graphPoints.count-1] = counterView.counter
    //2 - indicate that the graph needs to be redrawn
    graphView.setNeedsDisplay()
    maxLabel.text = "\(graphView.graphPoints.max()!)"
    
    //3 - calculate average from graphPoints
    let average = graphView.graphPoints.reduce(0, +) / graphView.graphPoints.count
    averageWaterDrunk.text = "\(average)"
    
    //4 - setup date formatter and calendar
    let today = Date()
    let calendar = Calendar.current
    
    let formatter = DateFormatter()
    formatter.setLocalizedDateFormatFromTemplate("EEEEE")
    
    //5 - set up the day name labels with correct day
    for i in (0...maxDayIndex) {
      if let date = calendar.date(byAdding: .day, value: -i, to: today),
        let label = stackView.arrangedSubviews[maxDayIndex - i] as? UILabel {
        label.text = formatter.string(from: date)
      }
    }
  }
  
  func checkTotal() {
    if counterView.counter >= 8 {
      medalView.showMedal(show: true)
    } else {
      medalView.showMedal(show: false)
    }
  }
  
}
2. PushButton.swift
import UIKit

@IBDesignable
class PushButton: UIButton {
  
  private struct Constants {
    static let plusLineWidth: CGFloat = 3.0
    static let plusButtonScale: CGFloat = 0.6
    static let halfPointShift: CGFloat = 0.5
  }
  
  private var halfWidth: CGFloat {
    return bounds.width / 2
  }
  
  private var halfHight: CGFloat {
    return bounds.height / 2
  }
  
  @IBInspectable var fillColor: UIColor = UIColor.green
  @IBInspectable var isAddButton: Bool = true
  
  override func draw(_ rect: CGRect) {
    let path = UIBezierPath(ovalIn: rect)
    fillColor.setFill()
    path.fill()
    
    //set up the width and height variables
    //for the horizontal stroke
    let plusWidth: CGFloat = min(bounds.width, bounds.height) * Constants.plusButtonScale
    let halfPlusWidth = plusWidth / 2
    
    //create the path
    let plusPath = UIBezierPath()
    
    //set the path's line width to the height of the stroke
    plusPath.lineWidth = Constants.plusLineWidth
    
    //move the initial point of the path
    //to the start of the horizontal stroke
    plusPath.move(to: CGPoint(
      x: halfWidth - halfPlusWidth + Constants.halfPointShift,
      y: halfHight + Constants.halfPointShift))
    
    //add a point to the path at the end of the stroke
    plusPath.addLine(to: CGPoint(
      x: halfWidth + halfPlusWidth + Constants.halfPointShift,
      y: halfHight + Constants.halfPointShift))
    
    //Vertical Line
    
    if isAddButton {
      plusPath.move(to: CGPoint(
        x: halfWidth + Constants.halfPointShift,
        y: halfHight - halfPlusWidth + Constants.halfPointShift))
      
      plusPath.addLine(to: CGPoint(
        x: halfWidth + Constants.halfPointShift,
        y: halfHight + halfPlusWidth + Constants.halfPointShift))
    }
    //existing code
    //set the stroke color
    UIColor.white.setStroke()
    plusPath.stroke()
  }
  
}
3. CounterView.swift
import UIKit

@IBDesignable class CounterView: UIView {
  
  private struct Constants {
    static let numberOfGlasses = 8
    static let lineWidth: CGFloat = 5.0
    static let arcWidth: CGFloat = 76
    
    static var halfOfLineWidth: CGFloat {
      return lineWidth / 2
    }
  }
  
  @IBInspectable var counter: Int = 5 {
    didSet {
      if counter <=  Constants.numberOfGlasses {
        //the view needs to be refreshed
        setNeedsDisplay()
      }
    }
  }
  @IBInspectable var outlineColor: UIColor = UIColor.blue
  @IBInspectable var counterColor: UIColor = UIColor.orange
  
  override func draw(_ rect: CGRect) {
    // 1
    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    
    // 2
    let radius: CGFloat = max(bounds.width, bounds.height)
    
    // 3
    let startAngle: CGFloat = 3 * .pi / 4
    let endAngle: CGFloat = .pi / 4
    
    // 4
    let path = UIBezierPath(arcCenter: center,
                            radius: radius/2 - Constants.arcWidth/2,
                            startAngle: startAngle,
                            endAngle: endAngle,
                            clockwise: true)
    
    // 5
    path.lineWidth = Constants.arcWidth
    counterColor.setStroke()
    path.stroke()
    
    
    //Draw the outline
    
    //1 - first calculate the difference between the two angles
    //ensuring it is positive
    let angleDifference: CGFloat = 2 * .pi - startAngle + endAngle
    //then calculate the arc for each single glass
    let arcLengthPerGlass = angleDifference / CGFloat(Constants.numberOfGlasses)
    //then multiply out by the actual glasses drunk
    let outlineEndAngle = arcLengthPerGlass * CGFloat(counter) + startAngle
    
    //2 - draw the outer arc
    let outlinePath = UIBezierPath(arcCenter: center,
                                   radius: bounds.width/2 - Constants.halfOfLineWidth,
                                   startAngle: startAngle,
                                   endAngle: outlineEndAngle,
                                   clockwise: true)
    
    //3 - draw the inner arc
    outlinePath.addArc(withCenter: center,
                       radius: bounds.width/2 - Constants.arcWidth + Constants.halfOfLineWidth,
                       startAngle: outlineEndAngle,
                       endAngle: startAngle,
                       clockwise: false)
    
    //4 - close the path
    outlinePath.close()
    
    outlineColor.setStroke()
    outlinePath.lineWidth = Constants.lineWidth
    outlinePath.stroke()
    
    //Counter View markers
    let context = UIGraphicsGetCurrentContext()
    
    //1 - save original state
    context?.saveGState()
    outlineColor.setFill()
    
    let markerWidth: CGFloat = 5.0
    let markerSize: CGFloat = 10.0
    
    //2 - the marker rectangle positioned at the top left
    let markerPath = UIBezierPath(rect: CGRect(x: -markerWidth/2, y: 0, width: markerWidth, height: markerSize))
    
    //3 - move top left of context to the previous center position
    context?.translateBy(x: rect.width/2, y: rect.height/2)
    
    for i in 1...Constants.numberOfGlasses {
      //4 - save the centred context
      context?.saveGState()
      //5 - calculate the rotation angle
      let angle = arcLengthPerGlass * CGFloat(i) + startAngle - .pi/2
      //rotate and translate
      context?.rotate(by: angle)
      context?.translateBy(x: 0, y: rect.height/2 - markerSize)
      
      //6 - fill the marker rectangle
      markerPath.fill()
      //7 - restore the centred context for the next rotate
      context?.restoreGState()
    }
    
    //8 - restore the original state in case of more painting
    context?.restoreGState()
  }
}
4. GraphView.swift
import UIKit

@IBDesignable class GraphView: UIView {
  
  private struct Constants {
    static let cornerRadiusSize = CGSize(width: 8.0, height: 8.0)
    static let margin: CGFloat = 20.0
    static let topBorder: CGFloat = 60
    static let bottomBorder: CGFloat = 50
    static let colorAlpha: CGFloat = 0.3
    static let circleDiameter: CGFloat = 5.0
  }
  
  //1 - the properties for the gradient
  @IBInspectable var startColor: UIColor = .red
  @IBInspectable var endColor: UIColor = .green
  
  //Weekly sample data
  var graphPoints: [Int] = [4, 2, 6, 4, 5, 8, 3]
  
  override func draw(_ rect: CGRect) {
    
    let width = rect.width
    let height = rect.height
    
    let path = UIBezierPath(roundedRect: rect,
                            byRoundingCorners: UIRectCorner.allCorners,
                            cornerRadii: Constants.cornerRadiusSize)
    path.addClip()
    
    //2 - get the current context
    let context = UIGraphicsGetCurrentContext()!
    let colors = [startColor.cgColor, endColor.cgColor]
    
    //3 - set up the color space
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    
    //4 - set up the color stops
    let colorLocations: [CGFloat] = [0.0, 1.0]
    
    //5 - create the gradient
    let gradient = CGGradient(colorsSpace: colorSpace,
                              colors: colors as CFArray,
                              locations: colorLocations)!
    
    //6 - draw the gradient
    var startPoint = CGPoint.zero
    var endPoint = CGPoint(x: 0, y: self.bounds.height)
    context.drawLinearGradient(gradient,
                               start: startPoint,
                               end: endPoint,
                               options: CGGradientDrawingOptions(rawValue: 0))
    
    //calculate the x point
    let margin = Constants.margin
    let columnXPoint = { (column:Int) -> CGFloat in
      //Calculate gap between points
      let spacer = (width - margin * 2 - 4) / CGFloat((self.graphPoints.count - 1))
      var x: CGFloat = CGFloat(column) * spacer
      x += margin + 2
      return x
    }
    
    // calculate the y point
    let topBorder: CGFloat = Constants.topBorder
    let bottomBorder: CGFloat = Constants.bottomBorder
    let graphHeight = height - topBorder - bottomBorder
    let maxValue = graphPoints.max()!
    let columnYPoint = { (graphPoint:Int) -> CGFloat in
      var y:CGFloat = CGFloat(graphPoint) / CGFloat(maxValue) * graphHeight
      y = graphHeight + topBorder - y // Flip the graph
      return y
    }
    
    // draw the line graph
    UIColor.white.setFill()
    UIColor.white.setStroke()
    
    //set up the points line
    let graphPath = UIBezierPath()
    //go to start of line
    graphPath.move(to: CGPoint(x:columnXPoint(0), y:columnYPoint(graphPoints[0])))
    
    //add points for each item in the graphPoints array
    //at the correct (x, y) for the point
    for i in 1..<graphPoints.count {
      let nextPoint = CGPoint(x:columnXPoint(i), y:columnYPoint(graphPoints[i]))
      graphPath.addLine(to: nextPoint)
    }
    
    //Create the clipping path for the graph gradient
    
    //1 - save the state of the context (commented out for now)
    context.saveGState()
    
    //2 - make a copy of the path
    let clippingPath = graphPath.copy() as! UIBezierPath
    
    //3 - add lines to the copied path to complete the clip area
    clippingPath.addLine(to: CGPoint(x: columnXPoint(graphPoints.count - 1), y:height))
    clippingPath.addLine(to: CGPoint(x:columnXPoint(0), y:height))
    clippingPath.close()
    
    //4 - add the clipping path to the context
    clippingPath.addClip()
    
    let highestYPoint = columnYPoint(maxValue)
    startPoint = CGPoint(x:margin, y: highestYPoint)
    endPoint = CGPoint(x:margin, y:self.bounds.height)
    
    context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: CGGradientDrawingOptions(rawValue: 0))
    context.restoreGState()
    
    //draw the line on top of the clipped gradient
    graphPath.lineWidth = 2.0
    graphPath.stroke()
    
    //Draw the circles on top of graph stroke
    for i in 0..<graphPoints.count {
      var point = CGPoint(x:columnXPoint(i), y:columnYPoint(graphPoints[i]))
      point.x -= Constants.circleDiameter / 2
      point.y -= Constants.circleDiameter / 2
      
      let circle = UIBezierPath(ovalIn: CGRect(origin: point, size: CGSize(width: Constants.circleDiameter, height: Constants.circleDiameter)))
      circle.fill()
    }
    
    //Draw horizontal graph lines on the top of everything
    let linePath = UIBezierPath()
    
    //top line
    linePath.move(to: CGPoint(x:margin, y: topBorder))
    linePath.addLine(to: CGPoint(x: width - margin, y:topBorder))
    
    //center line
    linePath.move(to: CGPoint(x:margin, y: graphHeight/2 + topBorder))
    linePath.addLine(to: CGPoint(x:width - margin, y:graphHeight/2 + topBorder))
    
    //bottom line
    linePath.move(to: CGPoint(x:margin, y:height - bottomBorder))
    linePath.addLine(to: CGPoint(x:width - margin, y:height - bottomBorder))
    let color = UIColor(white: 1.0, alpha: Constants.colorAlpha)
    color.setStroke()
    
    linePath.lineWidth = 1.0
    linePath.stroke()
  }
}
5. BackgroundView.swift
import UIKit

@IBDesignable
class BackgroundView: UIView {
  
  //1
  @IBInspectable var lightColor: UIColor = UIColor.orange
  @IBInspectable var darkColor: UIColor = UIColor.yellow
  @IBInspectable var patternSize: CGFloat = 200
  
  override func draw(_ rect: CGRect) {
    //2
    let context = UIGraphicsGetCurrentContext()!
    
    //3
    context.setFillColor(darkColor.cgColor)
    
    //4
    context.fill(rect)
    
    
    let drawSize = CGSize(width: patternSize, height: patternSize)
    
    UIGraphicsBeginImageContextWithOptions(drawSize, true, 0.0)
    let drawingContext = UIGraphicsGetCurrentContext()!
    
    //set the fill color for the new context
    darkColor.setFill()
    drawingContext.fill(CGRect(x: 0, y: 0, width: drawSize.width, height: drawSize.height))
    
    let trianglePath = UIBezierPath()
    //1
    trianglePath.move(to: CGPoint(x: drawSize.width/2, y: 0))
    //2
    trianglePath.addLine(to: CGPoint(x: 0, y: drawSize.height/2))
    //3
    trianglePath.addLine(to: CGPoint(x: drawSize.width, y: drawSize.height/2))
    
    //4
    trianglePath.move(to: CGPoint(x: 0,y: drawSize.height/2))
    //5
    trianglePath.addLine(to: CGPoint(x: drawSize.width/2, y: drawSize.height))
    //6
    trianglePath.addLine(to: CGPoint(x: 0, y: drawSize.height))
    
    //7
    trianglePath.move(to: CGPoint(x: drawSize.width, y: drawSize.height/2))
    //8
    trianglePath.addLine(to: CGPoint(x: drawSize.width/2, y: drawSize.height))
    //9
    trianglePath.addLine(to: CGPoint(x: drawSize.width, y: drawSize.height))
    
    lightColor.setFill()
    trianglePath.fill()
    
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    
    UIColor(patternImage: image).setFill()
    context.fill(rect)
  }
}
6. MedalView.swift
import UIKit

class MedalView: UIImageView {
  
  lazy var medalImage: UIImage = self.createMedalImage()
  
  func createMedalImage() -> UIImage {
    debugPrint("creating Medal Image")
    let size = CGSize(width: 120, height: 200)
    
    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
    let context = UIGraphicsGetCurrentContext()!
    
    
    //Gold colors
    let darkGoldColor = UIColor(red: 0.6, green: 0.5, blue: 0.15, alpha: 1.0)
    let midGoldColor = UIColor(red: 0.86, green: 0.73, blue: 0.3, alpha: 1.0)
    let lightGoldColor = UIColor(red: 1.0, green: 0.98, blue: 0.9, alpha: 1.0)
    
    //Add Shadow
    let shadow:UIColor = UIColor.black.withAlphaComponent(0.80)
    let shadowOffset = CGSize(width: 2.0, height: 2.0)
    let shadowBlurRadius: CGFloat = 5
    
    context.setShadow(offset: shadowOffset, blur: shadowBlurRadius, color: shadow.cgColor)
    
    context.beginTransparencyLayer(auxiliaryInfo: nil)
    
    //Lower Ribbon
    let lowerRibbonPath = UIBezierPath()
    lowerRibbonPath.move(to: CGPoint(x: 0, y: 0))
    lowerRibbonPath.addLine(to: CGPoint(x: 40, y: 0))
    lowerRibbonPath.addLine(to: CGPoint(x: 78, y: 70))
    lowerRibbonPath.addLine(to: CGPoint(x: 38, y: 70))
    lowerRibbonPath.close()
    UIColor.red.setFill()
    lowerRibbonPath.fill()
    
    //Clasp
    let claspPath = UIBezierPath(roundedRect: CGRect(x: 36, y: 62, width: 43, height: 20), cornerRadius: 5)
    claspPath.lineWidth = 5
    darkGoldColor.setStroke()
    claspPath.stroke()
    
    //Medallion
    let medallionPath = UIBezierPath(ovalIn: CGRect(x: 8, y: 72, width: 100, height: 100))
    context.saveGState()
    medallionPath.addClip()
    
    let colors = [darkGoldColor.cgColor, midGoldColor.cgColor, lightGoldColor.cgColor] as CFArray
    let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors, locations: [0, 0.51, 1])!
    context.drawLinearGradient(gradient, start: CGPoint(x: 40, y: 40), end: CGPoint(x: 100, y: 160), options: [])
    context.restoreGState()
    
    //Create a transform
    //Scale it, and translate it right and down
    var transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
    transform = transform.translatedBy(x: 15, y: 30)
    medallionPath.lineWidth = 2.0
    
    //apply the transform to the path
    medallionPath.apply(transform)
    medallionPath.stroke()
    
    //Upper Ribbon
    let upperRibbonPath = UIBezierPath()
    upperRibbonPath.move(to: CGPoint(x: 68, y: 0))
    upperRibbonPath.addLine(to: CGPoint(x: 108, y: 0))
    upperRibbonPath.addLine(to: CGPoint(x: 78, y: 70))
    upperRibbonPath.addLine(to: CGPoint(x: 38, y: 70))
    upperRibbonPath.close()
    
    UIColor.blue.setFill()
    upperRibbonPath.fill()
    
    //Number One
    
    //Must be NSString to be able to use draw(in:)
    let numberOne = "1" as NSString
    let numberOneRect = CGRect(x: 47, y: 100, width: 50, height: 50)
    let font = UIFont(name: "Academy Engraved LET", size: 60)!
    let numberOneAttributes = [
      NSAttributedStringKey.font: font,
      NSAttributedStringKey.foregroundColor: darkGoldColor
    ]
    numberOne.draw(in: numberOneRect, withAttributes: numberOneAttributes)
    
    context.endTransparencyLayer()
    
    //This code must always be at the end of the playground
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return image!
  }
  
  func showMedal(show:Bool) {
    image = show == true ? medalImage : nil
  }
  
}
7. MedalDrawing.playground
import UIKit

let size = CGSize(width: 120, height: 200)

UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let context = UIGraphicsGetCurrentContext()!


//Gold colors
let darkGoldColor = UIColor(red: 0.6, green: 0.5, blue: 0.15, alpha: 1.0)
let midGoldColor = UIColor(red: 0.86, green: 0.73, blue: 0.3, alpha: 1.0)
let lightGoldColor = UIColor(red: 1.0, green: 0.98, blue: 0.9, alpha: 1.0)

//Add Shadow
let shadow:UIColor = UIColor.black.withAlphaComponent(0.80)
let shadowOffset = CGSize(width: 2.0, height: 2.0)
let shadowBlurRadius: CGFloat = 5

context.setShadow(offset: shadowOffset, blur: shadowBlurRadius, color: shadow.cgColor)

context.beginTransparencyLayer(auxiliaryInfo: nil)

//Lower Ribbon
let lowerRibbonPath = UIBezierPath()
lowerRibbonPath.move(to: CGPoint(x: 0, y: 0))
lowerRibbonPath.addLine(to: CGPoint(x: 40, y: 0))
lowerRibbonPath.addLine(to: CGPoint(x: 78, y: 70))
lowerRibbonPath.addLine(to: CGPoint(x: 38, y: 70))
lowerRibbonPath.close()
UIColor.red.setFill()
lowerRibbonPath.fill()

//Clasp
let claspPath = UIBezierPath(roundedRect: CGRect(x: 36, y: 62, width: 43, height: 20), cornerRadius: 5)
claspPath.lineWidth = 5
darkGoldColor.setStroke()
claspPath.stroke()

//Medallion
let medallionPath = UIBezierPath(ovalIn: CGRect(x: 8, y: 72, width: 100, height: 100))
context.saveGState()
medallionPath.addClip()

let colors = [darkGoldColor.cgColor, midGoldColor.cgColor, lightGoldColor.cgColor] as CFArray
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors, locations: [0, 0.51, 1])!
context.drawLinearGradient(gradient, start: CGPoint(x: 40, y: 40), end: CGPoint(x: 100, y: 160), options: [])
context.restoreGState()

//Create a transform
//Scale it, and translate it right and down
var transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
transform = transform.translatedBy(x: 15, y: 30)
medallionPath.lineWidth = 2.0

//apply the transform to the path
medallionPath.apply(transform)
medallionPath.stroke()

//Upper Ribbon
let upperRibbonPath = UIBezierPath()
upperRibbonPath.move(to: CGPoint(x: 68, y: 0))
upperRibbonPath.addLine(to: CGPoint(x: 108, y: 0))
upperRibbonPath.addLine(to: CGPoint(x: 78, y: 70))
upperRibbonPath.addLine(to: CGPoint(x: 38, y: 70))
upperRibbonPath.close()

UIColor.blue.setFill()
upperRibbonPath.fill()

//Number One

//Must be NSString to be able to use draw(in:)
let numberOne = "1" as NSString
let numberOneRect = CGRect(x: 47, y: 100, width: 50, height: 50)
let font = UIFont(name: "Academy Engraved LET", size: 60)!
let numberOneAttributes = [
  NSAttributedStringKey.font: font,
  NSAttributedStringKey.foregroundColor: darkGoldColor
]
numberOne.draw(in: numberOneRect, withAttributes: numberOneAttributes)

context.endTransparencyLayer()

//This code must always be at the end of the playground
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()

后記

本篇主要講述了基于CoreGraphic的一個(gè)簡(jiǎn)單繪制示例岩四,感興趣的給個(gè)贊或者關(guān)注~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哥攘,隨后出現(xiàn)的幾起案子剖煌,更是在濱河造成了極大的恐慌,老刑警劉巖逝淹,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕姊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡栅葡,警方通過查閱死者的電腦和手機(jī)茉兰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欣簇,“玉大人规脸,你說我怎么就攤上這事⌒苎剩” “怎么了莫鸭?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)横殴。 經(jīng)常有香客問我被因,道長(zhǎng),這世上最難降的妖魔是什么衫仑? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任氏身,我火速辦了婚禮,結(jié)果婚禮上惑畴,老公的妹妹穿的比我還像新娘。我一直安慰自己航徙,他們只是感情好如贷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著到踏,像睡著了一般杠袱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窝稿,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天楣富,我揣著相機(jī)與錄音,去河邊找鬼伴榔。 笑死纹蝴,一個(gè)胖子當(dāng)著我的面吹牛庄萎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播塘安,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼糠涛,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了兼犯?” 一聲冷哼從身側(cè)響起忍捡,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎切黔,沒想到半個(gè)月后砸脊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纬霞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年凌埂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片险领。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侨舆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绢陌,到底是詐尸還是另有隱情挨下,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布脐湾,位于F島的核電站臭笆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秤掌。R本人自食惡果不足惜愁铺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闻鉴。 院中可真熱鬧茵乱,春花似錦、人聲如沸孟岛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渠羞。三九已至斤贰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間次询,已是汗流浹背荧恍。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屯吊,地道東北人送巡。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓摹菠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親授艰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辨嗽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容