타이포 애니메이션을 하려고 한다.
그런데 ?! 한글은 영어와 다르게 초성, 중성, 종성이 있다.
영어처럼 한자씩 찍어내면 안된다는건 아닌데 ... 내가 하고싶은건 글자 만들어지는 과정,
즉 예를들어
'확실' 이란 글잘
이렇게 찍히는게 아니라
ㅎ 화 확 확ㅅ 확시 확실이렇게 찍고 싶다 ~ 이말이다.
그러려면 한글의 유니코드를 쪼개봐야한다.
가보자고.
관련 문서 : String and Characters - Swift.docs
decomposed
를 보면 각각 ㅎ, ㅏ, ㄴ에 해당하는 유니코드들을을 붙여서 써줘도 print
는 조합한 글자로 찍힌다.
아항 우린 일단 글자를 입력 받으면 초성, 중성, 종성에 해당하는 유니코드로 분해해줘야 한다.
유니코드에서 한글은 0xAC00 ~ 0xD7A3(44032 ~ 55203 : 10진수) 사이의 코드값을 갖는다.(총 11,172개)
유니코드 내 한글은 초/중/종성의 각 음소의 조합으로 표현된다.
즉 초성 19개, 중성 21개, 종성 28개를 조합하여 하나의 글자가 되는 것이다.
따라서 각 초,중,종성에 해당하는 한글자모의 위치값을 계산하여 최종적으로 만들어지는 글자의 코드를 생성할 수 있다.
이 때 들어가는 값은 위치값으로 '0 ~ (해당 음소의 개수) - 1'만큼의 인덱스를 의미한다.
( ( 초성 X 21 ) + 중성 ) X 28 + 종성 + 0xAC00 ▼
중성idx = ((문자코드 - 0xAC00) / 28) % 21
종성idx = (문자코드 - 0xAC00) % 28
index가 유니코드 값은 아니다. 각각 음소의 시작값으로부터 얼마나 떨어졌는지(=offset)이다.
중성의 유니코드 = 중성idx + 0x1161
종성의 유니코드 = 종성idx + 0x11A8 - 1
func diassembleUnicode(_ char: UInt32) -> [UnicodeScalar] {
let x = (char - 0xac00) / 28 / 21
let y = (char - 0xac00) / 28 % 21
let z = (char - 0xac00) % 28
let initial = UnicodeScalar(0x1100 + x)// 초성
let neuter = UnicodeScalar(0x1161 + y)// 중성
let final = UnicodeScalar(0x11a7 + z)// 종성
var arr = [initial, neuter, final].compactMap { $0 }
if final == UnicodeScalar(0x11A7) { //받침 없음
arr.removeLast()
}
return arr
}
받침이 없다면 ... array에서 지워줬다.
1 try
let string = 글자
for i in string {
if let unicodeVal = UnicodeScalar(String(i))?.value {
let arr = diassembleUnicode(unicodeVal)
arr.forEach{ char in
글자 += "\(char)"
self.letterLabel.text! = 글자
}
RunLoop.current.run(until: Date() + 0.04)
}
음... 이렇게 짜봤는데
띠용 ...
콘솔창엔 원하는대로 '음소'씩 찍히는데 UI가 한 '글자'씩 찍힌다?!
solution)
눈보다 빠르게 업데이트 되는것!
그러므로 RunLoop
를 Label
업데이트 할 때도 주자!
let string = 글자
for i in string {
if let unicodeVal = UnicodeScalar(String(i))?.value {
let arr = diassembleUnicode(unicodeVal)
arr.forEach{ char in
글자 += "\(char)"
RunLoop.current.run(until: Date() + 0.04)
self.letterLabel.text! = 글자
}
RunLoop.current.run(until: Date() + 0.4)
}
실행화면과 같은 Typo animation 만든 기록이다.
보다 자연스러운 시각 효과를 위한다면 RunLoop
의 시간 값은 적당한 범위 내에서 random으로 주면된다.
https://soooprmx.com/unicodescalar/?amp
https://zeddios.tistory.com/493
피드백 환영합니다.