在Swift for iOS中沿循循环径绘制文字

前端之家收集整理的这篇文章主要介绍了在Swift for iOS中沿循循环径绘制文字前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在寻找一些关于如何使用 Swift2 for iOS9在一个圆圈边缘绘制简单的单行字符串的最新帮助/提示.我看到很旧的例子涉及旧的ObjC片段,而且仅限于OS X.这是否可以在iOS中使用自定义UIView子类的drawRect()方法
我要说“你试了什么?”,但星期五下午我早点下班了,所以我借机翻译了我的旧ObjC代码.这里适合游乐场.把它放在你的UIView中应该是微不足道的.

斯威夫特2
请参阅下面的Swift 3更新…

  1. import UIKit
  2.  
  3. func centreArcPerpendicularText(str: String,context: CGContextRef,radius r: CGFloat,angle theta: CGFloat,colour c: UIColor,font: UIFont,clockwise: Bool){
  4. // *******************************************************
  5. // This draws the String str around an arc of radius r,// with the text centred at polar angle theta
  6. // *******************************************************
  7.  
  8. let l = str.characters.count
  9. let attributes = [NSFontAttributeName: font]
  10.  
  11. var characters: [String] = [] // This will be an array of single character strings,each character in str
  12. var arcs: [CGFloat] = [] // This will be the arcs subtended by each character
  13. var totalArc: CGFloat = 0 // ... and the total arc subtended by the string
  14.  
  15. // Calculate the arc subtended by each letter and their total
  16. for i in 0 ..< l {
  17. characters += [String(str[str.startIndex.advancedBy(i)])]
  18. arcs += [chordToArc(characters[i].sizeWithAttributes(attributes).width,radius: r)]
  19. totalArc += arcs[i]
  20. }
  21.  
  22. // Are we writing clockwise (right way up at 12 o'clock,upside down at 6 o'clock)
  23. // or anti-clockwise (right way up at 6 o'clock)?
  24. let direction: CGFloat = clockwise ? -1 : 1
  25. let slantCorrection = clockwise ? -CGFloat(M_PI_2) : CGFloat(M_PI_2)
  26.  
  27. // The centre of the first character will then be at
  28. // thetaI = theta - totalArc / 2 + arcs[0] / 2
  29. // But we add the last term inside the loop
  30. var thetaI = theta - direction * totalArc / 2
  31.  
  32. for i in 0 ..< l {
  33. thetaI += direction * arcs[i] / 2
  34. // Call centerText with each character in turn.
  35. // Remember to add +/-90º to the slantAngle otherwise
  36. // the characters will "stack" round the arc rather than "text flow"
  37. centreText(characters[i],context: context,radius: r,angle: thetaI,colour: c,font: font,slantAngle: thetaI + slantCorrection)
  38. // The centre of the next character will then be at
  39. // thetaI = thetaI + arcs[i] / 2 + arcs[i + 1] / 2
  40. // but again we leave the last term to the start of the next loop...
  41. thetaI += direction * arcs[i] / 2
  42. }
  43. }
  44.  
  45. func chordToArc(chord: CGFloat,radius: CGFloat) -> CGFloat {
  46. // *******************************************************
  47. // Simple geometry
  48. // *******************************************************
  49. return 2 * asin(chord / (2 * radius))
  50. }
  51.  
  52. func centreText(str: String,radius r:CGFloat,slantAngle: CGFloat) {
  53. // *******************************************************
  54. // This draws the String str centred at the position
  55. // specified by the polar coordinates (r,theta)
  56. // i.e. the x= r * cos(theta) y= r * sin(theta)
  57. // and rotated by the angle slantAngle
  58. // *******************************************************
  59.  
  60. // Set the text attributes
  61. let attributes = [NSForegroundColorAttributeName: c,NSFontAttributeName: font]
  62. // Save the context
  63. CGContextSaveGState(context)
  64. // Undo the inversion of the Y-axis (or the text goes backwards!)
  65. CGContextScaleCTM(context,1,-1)
  66. // Move the origin to the centre of the text (negating the y-axis manually)
  67. CGContextTranslateCTM(context,r * cos(theta),-(r * sin(theta)))
  68. // Rotate the coordinate system
  69. CGContextRotateCTM(context,-slantAngle)
  70. // Calculate the width of the text
  71. let offset = str.sizeWithAttributes(attributes)
  72. // Move the origin by half the size of the text
  73. CGContextTranslateCTM (context,-offset.width / 2,-offset.height / 2) // Move the origin to the centre of the text (negating the y-axis manually)
  74. // Draw the text
  75. str.drawAtPoint(CGPointZero,withAttributes: attributes)
  76. // Restore the context
  77. CGContextRestoreGState(context)
  78. }
  79.  
  80. // *******************************************************
  81. // Playground code to test
  82. // *******************************************************
  83. let size = CGSize(width: 256,height: 256)
  84.  
  85. UIGraphicsBeginImageContextWithOptions(size,true,0.0)
  86. let context = UIGraphicsGetCurrentContext()!
  87. // *******************************************************************
  88. // Scale & translate the context to have 0,0
  89. // at the centre of the screen maths convention
  90. // ObvIoUsly change your origin to suit...
  91. // *******************************************************************
  92. CGContextTranslateCTM (context,size.width / 2,size.height / 2)
  93. CGContextScaleCTM (context,-1)
  94.  
  95. centreArcPerpendicularText("Hello round world",radius: 100,angle: 0,colour: UIColor.redColor(),font: UIFont.systemFontOfSize(16),clockwise: true)
  96. centreArcPerpendicularText("Anticlockwise",angle: CGFloat(-M_PI_2),clockwise: false)
  97. centreText("Hello flat world",radius: 0,colour: UIColor.yellowColor(),slantAngle: CGFloat(M_PI_4))
  98.  
  99.  
  100. let image = UIGraphicsGetImageFromCurrentImageContext()
  101. UIGraphicsEndImageContext()

输出为:

更新
顺时针/逆时针方向直的例子

更新Swift 3

  1. func centreArcPerpendicular(text str: String,context: CGContext,// with the text centred at polar angle theta
  2. // *******************************************************
  3.  
  4. let l = str.characters.count
  5. let attributes = [NSFontAttributeName: font]
  6.  
  7. let characters: [String] = str.characters.map { String($0) } // An array of single character strings,each character in str
  8. var arcs: [CGFloat] = [] // This will be the arcs subtended by each character
  9. var totalArc: CGFloat = 0 // ... and the total arc subtended by the string
  10.  
  11. // Calculate the arc subtended by each letter and their total
  12. for i in 0 ..< l {
  13. arcs += [chordToArc(characters[i].size(attributes: attributes).width,upside down at 6 o'clock)
  14. // or anti-clockwise (right way up at 6 o'clock)?
  15. let direction: CGFloat = clockwise ? -1 : 1
  16. let slantCorrection = clockwise ? -CGFloat(M_PI_2) : CGFloat(M_PI_2)
  17.  
  18. // The centre of the first character will then be at
  19. // thetaI = theta - totalArc / 2 + arcs[0] / 2
  20. // But we add the last term inside the loop
  21. var thetaI = theta - direction * totalArc / 2
  22.  
  23. for i in 0 ..< l {
  24. thetaI += direction * arcs[i] / 2
  25. // Call centerText with each character in turn.
  26. // Remember to add +/-90º to the slantAngle otherwise
  27. // the characters will "stack" round the arc rather than "text flow"
  28. centre(text: characters[i],slantAngle: thetaI + slantCorrection)
  29. // The centre of the next character will then be at
  30. // thetaI = thetaI + arcs[i] / 2 + arcs[i + 1] / 2
  31. // but again we leave the last term to the start of the next loop...
  32. thetaI += direction * arcs[i] / 2
  33. }
  34. }
  35.  
  36. func chordToArc(_ chord: CGFloat,radius: CGFloat) -> CGFloat {
  37. // *******************************************************
  38. // Simple geometry
  39. // *******************************************************
  40. return 2 * asin(chord / (2 * radius))
  41. }
  42.  
  43. func centre(text str: String,NSFontAttributeName: font]
  44. // Save the context
  45. context.saveGState()
  46. // Undo the inversion of the Y-axis (or the text goes backwards!)
  47. context.scaleBy(x: 1,y: -1)
  48. // Move the origin to the centre of the text (negating the y-axis manually)
  49. context.translateBy(x: r * cos(theta),y: -(r * sin(theta)))
  50. // Rotate the coordinate system
  51. context.rotate(by: -slantAngle)
  52. // Calculate the width of the text
  53. let offset = str.size(attributes: attributes)
  54. // Move the origin by half the size of the text
  55. context.translateBy (x: -offset.width / 2,y: -offset.height / 2) // Move the origin to the centre of the text (negating the y-axis manually)
  56. // Draw the text
  57. str.draw(at: CGPoint(x: 0,y: 0),withAttributes: attributes)
  58. // Restore the context
  59. context.restoreGState()
  60. }
  61.  
  62. // *******************************************************
  63. // Playground code to test
  64. // *******************************************************
  65. let size = CGSize(width: 256,0
  66. // at the centre of the screen maths convention
  67. // ObvIoUsly change your origin to suit...
  68. // *******************************************************************
  69. context.translateBy (x: size.width / 2,y: size.height / 2)
  70. context.scaleBy (x: 1,y: -1)
  71.  
  72. centreArcPerpendicular(text: "Hello round world",colour: UIColor.red,font: UIFont.systemFont(ofSize: 16),clockwise: true)
  73. centreArcPerpendicular(text: "Anticlockwise",clockwise: false)
  74. centre(text: "Hello flat world",colour: UIColor.yellow,slantAngle: CGFloat(M_PI_4))
  75.  
  76.  
  77. let image = UIGraphicsGetImageFromCurrentImageContext()
  78. UIGraphicsEndImageContext()

更新以在UIView中显示使用

评论员@RitvikUpadhyaya询问如何在UIView中做到这一点 – 对老手来说显而易见,但不是初学者.诀窍是使用UIGraphicsGetCurrentContext获取正确的上下文,而无需调用UIGraphicsBeginImageContextWithOptions(将UIView的上下文替换为当前上下文) – 因此您的UIView应该如下所示:

  1. class MyView: UIView {
  2. override func draw(_ rect: CGRect) {
  3. guard let context = UIGraphicsGetCurrentContext() else { return }
  4. let size = self.bounds.size
  5.  
  6. context.translateBy (x: size.width / 2,y: size.height / 2)
  7. context.scaleBy (x: 1,y: -1)
  8.  
  9. centreArcPerpendicular(text: "Hello round world",clockwise: true)
  10. centreArcPerpendicular(text: "Anticlockwise",clockwise: false)
  11. centre(text: "Hello flat world",slantAngle: CGFloat(M_PI_4))
  12. }
  13. }

猜你在找的Swift相关文章