텍스트 그라데이션 넣기 - kirseia/study GitHub Wiki

    func init() {
        engTestLabel.frame = CGRect(x: 50, y: 100, width: 300, height: 300)
        engTestLabel.text = "HELLO"
        engTestLabel.font = UIFont.systemFont(ofSize: 50)
        engTestLabel.backgroundColor = .black
        
        engTestLabel.sizeToFit()
        
        korTestLabel.frame = CGRect(x: 50, y: 300, width: 300, height: 300)
        korTestLabel.text = "안녕?"
        korTestLabel.font = UIFont.systemFont(ofSize: 50)
        korTestLabel.backgroundColor = .black
        
        korTestLabel.sizeToFit()
    } 

    private func makeGradientImage(bounds: CGRect, value: Float) -> UIImage? {
        let gradientLayer = CAGradientLayer()
        
        gradientLayer.colors = [
            UIColor.red.cgColor,
            UIColor.red.cgColor,
            UIColor.blue.cgColor,
            UIColor.blue.cgColor
        ]
        
        let location = NSNumber(value: value)
        gradientLayer.locations = [0, location, location, 1]
        gradientLayer.bounds = bounds
        
        UIGraphicsBeginImageContextWithOptions(gradientLayer.bounds.size, true, 0.0)
        
        guard let context = UIGraphicsGetCurrentContext() else {
            assertionFailure("Failed to make context")
            return nil
        }
        gradientLayer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return image ?? nil
    }
    
    
    @IBAction func moveSlider(_ sender: Any) {
        self.label.text = "\(self.slider.value)"
        
        if let image = makeGradientImage(bounds: self.engTestLabel.bounds, value: self.slider.value) {
            self.engTestLabel.textColor = UIColor(patternImage: image)
            
        }
        
        if let image = makeGradientImage(bounds: self.korTestLabel.bounds, value: self.slider.value) {
            self.korTestLabel.textColor = UIColor(patternImage: image)
        }
    }   

대충 이런 코드인데, 한글일 때 색상이 이상하게 적용되었음.

원인

한글인 경우에 textlabel.bounds 가 실제 text의 크기보다 작게 return 이 됨. 따라서, UIColor(patternImage: image)에서 실제보다 작은 크기로 패턴이 만들어져서 반복되어 적용되고 있음. 폰트가 클 수록 영향이 큼.

Ref. https://www.raizlabs.com/dev/2015/08/advanced-ios-typography/

Ref. http://www.cyrilchandelier.com/understanding-fonts-and-uifont

Ref. https://www.cocoanetics.com/2010/02/understanding-uifont/

위 이미지에서 lineHeight 로 해도 실제 UILabel 보다 작음.

해결

  • 한글일 경우에 실제 text 크기를 얻어올 방법이 없음. UILabel의 size가 sizeToFit()을 해도 실제 텍스트 크기랑은 다른 것으로 보임.

  • UILabel 에 직접 gradation 을 적용하지 않는 것으로 ...

  • https://medium.com/@kgellci/quickly-apply-gradient-colors-to-text-in-ios-299f7639b514 을 참고함.

  • Gradation 이미지를 뷰에 올린 다음에 Label 을 Mask 로 사용하는 방식으로 해결.

  • 다만, 이 방식은 실제 text 의 크기를 이용한게 아니기 때문에 눈에 보이는 텍스트의 비율과 다르게 gradation 이 들어갈 수 있으므로 50% 가 아니라면 적절하게 수정이 필요함.

참고

  • 폰트 찾다가 Kerning 수정하는 방법 찾아봄

https://stackoverflow.com/questions/7370013/how-to-set-kerning-in-iphone-uilabel