如何弯曲和扭曲UILabel或UIView

时间:2018-04-22 16:04:47

标签: swift uiview uilabel swift4

我是iOS开发人员,使用swift4。

我制作了圆形标签,但我希望将UILabel的每个文字都折成圆圈。

我知道在SpriteKit中,可以使用SKWarpGeometryGrid进行Warp转换。

由于我不打算制作游戏,我想要扭曲UILabel,这是UIView的子类,没有Sprite Kit。

目标

I want to do like this 代码:

你能告诉我如何只用UIKit弯曲UILabel或UIView吗?

import UIKit

//func centreArcPerpendicular() {
//    guard let context = UIGraphicsGetCurrentContext() else { return }
//    let string = text ?? ""
//    let size = bounds.size
//    context.translateBy(x: size.width / 2, y: size.height / 2)
//
//    let radius = getRadiusForLabel()
//    let count = string.count
//    let attributes: [NSAttributedStringKey: Any] =
//        [
//            .font: self.font!,
//            .kern: space
//    ]
//
//
//    let characters: [String] = string.map { String($0) }
//    var arcs: [CGFloat] = []
//    var totalArc: CGFloat = 0
//
//    for i in 0 ..< count {
//        arcs += [chordToArc(characters[i].size(withAttributes: attributes).width, radius: radius)]
//        totalArc += arcs[i]
//    }
//
//    let direction: CGFloat = clockwise ? -1 : 1
//    let slantCorrection = clockwise ? -CGFloat.pi / 2 : CGFloat.pi / 2
//
//    var thetaI = _angle - direction * totalArc / 2
//
//    for (i, arc) in arcs.enumerated() {
//        thetaI += direction * arc / 2
//        center(text: characters[i], context: context, radius: radius, angle: thetaI, slantAngle: thetaI + slantCorrection)
//        thetaI += direction * arc / 2
//    }
//}


class CircularLabel: UILabel {
    @IBInspectable var angle: CGFloat = 1.6
    @IBInspectable var DegMode: Bool = false
    @IBInspectable var clockwise: Bool = true
    @IBInspectable var radius:CGFloat=16
    @IBInspectable var space: CGFloat = 0

    private var _angle: CGFloat {
        return DegMode ? (angle * CGFloat.pi / 180.0) : angle
    }

    override func draw(_ rect: CGRect) {
        centerText()
    }

    func centerText() {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        let string = text ?? ""
        let size = bounds.size
        context.translateBy(x: size.width / 2, y: size.height / 2)
        let direction: CGFloat = clockwise ? -1 : 1
        let slantCorrection = clockwise ? -CGFloat.pi / 2 : CGFloat.pi / 2
        var thetaI = _angle


        string
            .map { String($0) }
            .forEach {
                center(text: $0, context: context, radius: radius, angle: thetaI, slantAngle: thetaI + slantCorrection)
                thetaI +=  direction*CGFloat.pi * 2 / CGFloat(string.count)
        }

    }


    func chordToArc(_ chord: CGFloat, radius: CGFloat) -> CGFloat {
        return 2 * asin(chord / (2 * radius))
    }

    func center(text str: String, context: CGContext, radius r: CGFloat, angle theta: CGFloat, slantAngle: CGFloat) {
        let attributes: [NSAttributedStringKey: Any] = [
                .foregroundColor: textColor!,
                .font: font!
        ]
        context.saveGState()
        context.translateBy(x: r * cos(theta), y: -(r * sin(theta)))
        context.rotate(by: -slantAngle)

//        print(CIFilter.filterNames(inCategory: kCICategoryDistortionEffect))


        let offset = str.size(withAttributes: attributes)
        context.translateBy(x: -offset.width / 2, y: -offset.height / 2)

        let label=UILabel()
        label.attributedText=NSAttributedString(string: str, attributes: attributes)




        label.drawText(in: CGRect(origin: CGPoint.zero, size: str.size(withAttributes: attributes)))
        context.restoreGState()
    }

    func getRadiusForLabel() -> CGFloat {
        let smallestWidthOrHeight = min(bounds.size.height, bounds.size.width)
        let heightOfFont = text?.size(withAttributes: [NSAttributedStringKey.font: self.font]).height ?? 0

        return (smallestWidthOrHeight / 2) - heightOfFont + 5
    }
}

0 个答案:

没有答案