HIT해
[iOS/SceneKit] 3D 화면에 텍스트 출력하기 본문
이전 포스팅 영상을 본 사람이 있다면 궁금했을 수도 있다.
3D 펫말에 어떻게 텍스트를 집어넣지???
나도 어떻게 집어넣을까 많은 고민을 했다..
ZStack에 2D 텍스트를 기울여지게 띄워놓을까..?
-> 회전했을때 텍스트가 붕 뜨게 될 것이다.
찾아보니 SceneKit에 3D Text를 출력하는 기능이 있었다. ( 아니 이런건 왜 있는거야.. )
두가지 방법이 있었다.
- CATextLayer로 구현하기
- SCNText로 구현하기
SCNText가 더 최신 기술이고 메서드 사용도 더 용이해보여 SCNText로 해결해보기로 했다.
https://developer.apple.com/documentation/scenekit/scntext
SCNText | Apple Developer Documentation
A geometry based on a string of text, optionally extruded to create a three-dimensional object.
developer.apple.com
한번 사용해보자!
SCN 기능들은 대부분 비슷해서 별다른 공부없이도 바로 사용할 수 있었다.
코드를 보고 기능들을 살펴보자
let scnText = SCNText()
scnText.font = UIFont(name: "Helvetica Neue", size: 8)!
scnText.firstMaterial?.diffuse.contents = UIColor.black
scnText.containerFrame = CGRect(origin: .zero, size: CGSize(width: 70, height: 60))
scnText.string = ""
scnText.isWrapped = true
scnText.extrusionDepth = 1.2
// flatness : 텍스트의 부드러움을 결정함
scnText.flatness = CGFloat(1)
// SCNNode 생성
let textNode = SCNNode(geometry: scnText)
textNode.eulerAngles = SCNVector3(0, 0, 0) // 텍스트가 정면을 바라보도록
textNode.scale = SCNVector3Make(0.01, 0.01, 0.01)
textNode.name = "text"
return textNode
string 값이 표시할 텍스트 값이고
isWrapped는 줄바꿈을 하겠다는 뜻이고 이는
containerFrame 에 정의된 가로 길이를 넘어가면 줄을 바꾸게 된다.
flatness의 CGFlaot 값에 따라 부드러움을 정하고
extrusionDepth는 3D 텍스트이다보니 Z축 기준으로 얼마나 입체적이게 할지 그 크기를 정의하는 부분이다.
사실 간단한 코드지만 프로젝트에 적용하는데에는 어려움이 있었다...
containerFrame을 적용하면 텍스트의 크기가 컨테이너에 맞게 조정되는데 이때 추가 scale 조정이 없으면 화면에 아무런 텍스트가 표시되지않았다..
그래서 단순히 텍스트 표시 기능은 10분만에 구현했지만 이 줄바꿈 기능 때문애 몇시간이나 날렸고..
CATextLayer로 거의 다 구현을 마쳤다가 텍스트가 로드되는게 마음에 들지 않아 다시 SCNText로 돌아가고..
( 혹시 CATextLayer로 구현하고 싶은 사람은 포스팅 맨 아래의 코드를 사용하길 바란다... )
https://developer.apple.com/forums/thread/85368
이 링크의 답변 덕분에 추가적인 시간 낭비를 막을 수 있었다..
이렇게 하면 3D View에 텍스트가 추가되는데 가변적인 텍스트이기에 어디에서 값을 변경해야할 지 고민이 되었다.
makeView와 updateView중
makeView에서 생성을 하면 추가적인 로직이 없는이상 정의된 값을 바꿀 수 없었고,
updateView에서 생성을 하면 값을 변경할때마다 중복으로 노드가 생겨서 오류가 발생했다.
그래서 makeView에서 빈 문자열의 3DText를 생성하고 updateView에서 3D Text Node의 String에 접근해 값을 바꿔주었다.
func updateTextNode(_ textNode: SCNNode, newText: String) {
// 텍스트 노드에서 geometry를 SCNText로 변환
if let scnText = textNode.geometry as? SCNText {
// 텍스트 내용을 변경
scnText.string = newText
}
}
이렇게 받는 타입을 textNode라고 지정해야 String값을 변경할 수 있으니 참고하길 바란다.
updateTextNode(텍스트노드, newText: TCA바인딩값)
이렇게 하면 3D 줄바꿈 텍스트 기능이 완성된다...!
완성이다...!
TCA최신기술과 한물간 SCN기술의 콜라보....
너무 즐겁다. SCN 기술을 원하는 회사 어디 없으려나...
아래는 포스팅에서 말한 CATextLayer 코드다
func addTextNode(above parentNode: SCNNode, text: String) -> SCNNode {
// CATextLayer 생성
let textLayer = CATextLayer()
textLayer.string = text
textLayer.fontSize = 16
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.alignmentMode = .center
textLayer.isWrapped = true
// 텍스트 레이어의 크기 설정
let maxWidth: CGFloat = 100
let maxHeight: CGFloat = 50
textLayer.frame = CGRect(x: 0, y: 0, width: maxWidth, height: maxHeight)
// SCNPlane 생성
let plane = SCNPlane(width: maxWidth / 100, height: maxHeight / 100)
// SCNMaterial 생성 및 CATextLayer를 적용
let material = SCNMaterial()
material.diffuse.contents = textLayer
plane.firstMaterial = material
// 텍스트 노드 생성
let textNode = SCNNode(geometry: plane)
// 부모 노드의 위치 가져오기
let parentPosition = parentNode.position
// 텍스트 노드의 위치를 부모 노드의 위치로 설정
textNode.position = SCNVector3(parentPosition.x, parentPosition.y + 1.0, parentPosition.z) // 부모 노드 위쪽에 텍스트를 배치합니다.
// 부모 노드에 텍스트 노드 추가
parentNode.addChildNode(textNode)
return textNode
}
'Swift > UIKit 개발 노트' 카테고리의 다른 글
[Swift/TCA] TCA를 활용한 테스트코드 작성 (TCA ver 1.12.1) (0) | 2024.09.20 |
---|---|
[iOS/SwiftUI] TCA API 통신 구현하기 with AF ( TCA 1.12.1 ) (0) | 2024.09.05 |
[iOS/SceneKit] 특정 노드 액션 구현하기 (0) | 2024.09.03 |
[iOS/SwiftUI] TCA NavigationStack 개발하기 (1.12.1) (0) | 2024.09.02 |
[iOS/SceneKit] Blender hdri 불러와서 적용하기 (0) | 2024.08.30 |