2016-02-15 8 views
0

Я пытаюсь повернуть основной текст так, чтобы он был читабельным, несмотря на то, что он генерируется с помощью поворотного контекста.Вращение основного текста не вращается должным образом - Swift

Моя проблема заключается в том, что независимо от способа вращения полученный текст не является тем, что ожидается.

Вот рабочая площадка:

import Foundation 
import UIKit 
import XCPlayground 


class ClockFace: UIView { 

    func drawText(context: CGContextRef, text: NSString, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: CGFloat) -> CGSize { 
     CGContextTranslateCTM(context, 0, 0) 
     CGContextScaleCTM(context, 1, -1) 
     let font = attributes[NSFontAttributeName] as! UIFont 
     let attributedString = NSAttributedString(string: text as String, attributes: attributes) 

     let textSize = text.sizeWithAttributes(attributes) 

     let textPath = CGPathCreateWithRect(CGRect(x: -x, y: y + font.descender, width: ceil(textSize.width), height: ceil(textSize.height)), nil) 
     let frameSetter = CTFramesetterCreateWithAttributedString(attributedString) 
     let frame  = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), textPath, nil) 
     CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align * 43.0)) 
     CTFrameDraw(frame, context) 

     return textSize 
    } 

    override func drawRect(rect: CGRect) { 
     let ctx: CGContext? = UIGraphicsGetCurrentContext() 
     var nums: Int = 0 
     for i in 0..<60 { 
      CGContextSaveGState(ctx) 
      CGContextTranslateCTM(ctx, rect.width/2, rect.height/2) 
      CGContextRotateCTM(ctx, CGFloat(6.0 * Double(i) * M_PI/180)) 
      if (i % 5 == 0) { 
       nums++ 
       drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.blackColor().CGColor, NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI/180)) 
      } 
      CGContextRestoreGState(ctx) 
     } 

    } 
} 
let myView = ClockFace(frame: CGRectMake(0, 0, 150, 150)) 
myView.backgroundColor = .lightGrayColor() 
XCPShowView("", view: myView) 

Независимо от значения в CGAffineTransfomMakeRotation текст неразборчив.

Почему это? Правильно ли вернул текст?

С уважением, Брэндон

ответ

1

Рисует циферблат на основе ваших кодов, но пересмотренные немного.

В основном, что я сделал, это перевернуть и переместить целую циферблату за пределы цикла. Вы можете видеть, что я переехал CGContextTranslateCTM() и CGContextScaleCTM() от drawText() до drawRect(). Другими являются некоторые незначительные изменения в расчете вследствие вышеупомянутой модификации.

Что касается CGContextSetTextMatrix(), то поворот здесь затрагивает каждый символ, но не целую строку. Вы можете прокомментировать строку 19 & 20 и разорвать строку 21, чтобы иметь другой результат и посмотреть, что я имею в виду.

Также, если вы хотите получить файл детской площадки, вы можете скачать его с here.

import Foundation 
import UIKit 
import XCPlayground 


class ClockFace: UIView { 

    func drawText(context: CGContextRef, text: String, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: CGFloat) -> CGSize { 
     let font = attributes[NSFontAttributeName] as! UIFont 
     let attributedString = NSAttributedString(string: text, attributes: attributes) 
     let textSize = text.sizeWithAttributes(attributes) 

     let textPath = CGPathCreateWithRect(CGRect(x: x, y: y + font.descender, width: ceil(textSize.width), height: ceil(textSize.height)), nil) 
     let frameSetter = CTFramesetterCreateWithAttributedString(attributedString) 
     let frame  = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), textPath, nil) 

     var transform = CGAffineTransformMakeTranslation(x + 10, y + font.descender) 
     transform = CGAffineTransformRotate(transform, align) 
     //CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align)) 
     CGContextConcatCTM(context, transform); 
     CTFrameDraw(frame, context) 

     return textSize 
    } 

    override func drawRect(rect: CGRect) { 
     let ctx: CGContext? = UIGraphicsGetCurrentContext() 
     CGContextTranslateCTM(ctx, -45, rect.size.height + 5) 
     CGContextScaleCTM(ctx, 1, -1) 
     var nums: Int = 2 
     for i in 0..<60 { 
      CGContextSaveGState(ctx) 
      CGContextTranslateCTM(ctx, rect.width/2, rect.height/2) 
      CGContextRotateCTM(ctx, CGFloat(-6.0 * Double(i) * M_PI/180)) 
      if (i % 5 == 0) { 
       nums++ 
       nums = nums > 12 ? nums - 12 : nums 
       drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.whiteColor(), NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI/180)) 

      } 
      CGContextRestoreGState(ctx) 
     } 
    } 
} 

let view = ClockFace(frame: CGRectMake(0, 0, 150, 150)) 
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 
XCPlaygroundPage.currentPage.liveView = view 
+0

Работает, спасибо. Где вы получили значения для CGContextTranslateCTM (ctx, -45, rect.size.height + 5)? –

+0

@BrandonBradley На самом деле здесь нет магии, это просто компенсация геометрии x, y позиции '' drawText (: text: attributes: x: y: align:) ''. Цель заключается в том, чтобы в центре располагалась часовая сторона. – Allen