Skip to content

Commit 0513acf

Browse files
committed
[#234] Prototype ESMarker 설계
1 parent 4acf725 commit 0513acf

File tree

2 files changed

+167
-6
lines changed

2 files changed

+167
-6
lines changed

EATSSU/App/Sources/Presentation/Maps/ViewController/MapViewController.swift

+15-6
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ final class MapViewController: BaseViewController, NMFMapViewTouchDelegate {
2121
mapView = NMFMapView(frame: view.frame)
2222
view.addSubview(mapView)
2323

24-
let marker = NMFMarker()
25-
marker.position = NMGLatLng(lat: 37.4964, lng: 126.9575)
26-
marker.mapView = mapView
24+
// Sample marker at NAVER 1984 location
25+
let sampleMarker = ESMarker(
26+
position: NMGLatLng(lat: 37.3595704, lng: 127.105399),
27+
data: "Sample Data",
28+
leftText: "NAVER",
29+
rightText: "1984"
30+
)
31+
sampleMarker.marker.mapView = mapView
2732

2833
mapView.touchDelegate = self
2934
}
@@ -50,9 +55,13 @@ extension MapViewController {
5055
print("탭: \(latlng.lat), \(latlng.lng)")
5156
#endif
5257

53-
let marker = NMFMarker()
54-
marker.position = NMGLatLng(lat: latlng.lat, lng: latlng.lng)
55-
marker.mapView = mapView
58+
let marker = ESMarker(
59+
position: NMGLatLng(lat: latlng.lat, lng: latlng.lng),
60+
data: "Tapped Location",
61+
leftText: "Tapped",
62+
rightText: "Here"
63+
)
64+
marker.marker.mapView = mapView
5665
}
5766

5867
func mapView(_: NMFMapView, didLongTapMap latlng: NMGLatLng, point _: CGPoint) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//
2+
// ESMarker.swift
3+
// EATSSUDesign
4+
//
5+
// Created by JIWOONG CHOI on 1/31/25.
6+
//
7+
8+
import NMapsMap
9+
import UIKit
10+
11+
public final class ESMarker {
12+
// MARK: - Properties
13+
14+
public private(set) var marker: NMFMarker
15+
private var data: Any
16+
private var leftText: String
17+
private var rightText: String
18+
19+
// MARK: - Layout Constants
20+
21+
private enum Layout {
22+
static let horizontalPadding: CGFloat = 12
23+
static let verticalPadding: CGFloat = 12
24+
static let spacing: CGFloat = 10
25+
static let cornerRadius: CGFloat = 15
26+
static let tailHeight: CGFloat = 8
27+
static let leftBubblePadding: CGFloat = 20
28+
}
29+
30+
// MARK: - Initializer
31+
32+
public init(position: NMGLatLng, data: Any, leftText: String, rightText: String) {
33+
marker = NMFMarker()
34+
marker.position = position
35+
self.data = data
36+
self.leftText = leftText
37+
self.rightText = rightText
38+
updateImage()
39+
}
40+
41+
// MARK: - Methods
42+
43+
public func updatePosition(newPosition: NMGLatLng) {
44+
marker.position = newPosition
45+
}
46+
47+
public func updateLeftText(newLeftText: String) {
48+
leftText = newLeftText
49+
updateImage()
50+
}
51+
52+
public func updateRightText(newRightText: String) {
53+
rightText = newRightText
54+
updateImage()
55+
}
56+
57+
private func updateImage() {
58+
let image = ESMarker.createESMarkerImage(leftText: leftText, rightText: rightText)
59+
marker.iconImage = NMFOverlayImage(image: image)
60+
marker.width = image.size.width
61+
marker.height = image.size.height
62+
marker.anchor = CGPoint(x: 0.5, y: 1.0) // 🔼 꼬리가 마커 위치에 정확히 오도록 앵커 조정
63+
}
64+
65+
private static func createESMarkerImage(leftText: String, rightText: String) -> UIImage {
66+
// Font
67+
let font = EATSSUDesignFontFamily.Pretendard.regular.font(size: 12)
68+
69+
// Text Attributes
70+
let leftAttributes: [NSAttributedString.Key: Any] = [
71+
.font: font,
72+
.foregroundColor: UIColor.systemMint,
73+
]
74+
let rightAttributes: [NSAttributedString.Key: Any] = [
75+
.font: font,
76+
.foregroundColor: UIColor.black,
77+
]
78+
79+
// Text Size Calculation
80+
let leftTextSize = (leftText as NSString).size(withAttributes: leftAttributes)
81+
let rightTextSize = (rightText as NSString).size(withAttributes: rightAttributes)
82+
83+
// Bubble Dimensions
84+
let leftBubbleWidth = leftTextSize.width + Layout.horizontalPadding * 2
85+
let leftBubbleHeight = leftTextSize.height + Layout.verticalPadding * 2
86+
let rightBubbleWidth = rightTextSize.width + Layout.horizontalPadding * 2
87+
88+
let totalWidth = Layout.leftBubblePadding + leftBubbleWidth + Layout.spacing + rightBubbleWidth
89+
let bubbleHeight = max(leftBubbleHeight, rightTextSize.height + Layout.verticalPadding * 2)
90+
let totalHeight = bubbleHeight + Layout.tailHeight
91+
92+
// Image Rendering
93+
let renderer = UIGraphicsImageRenderer(size: CGSize(width: totalWidth, height: totalHeight))
94+
return renderer.image { _ in
95+
// 1. Background & Tail
96+
let backgroundRect = CGRect(x: 0, y: 0, width: totalWidth, height: bubbleHeight)
97+
let backgroundPath = UIBezierPath(roundedRect: backgroundRect, cornerRadius: Layout.cornerRadius)
98+
UIColor.white.setFill()
99+
backgroundPath.fill()
100+
101+
// Tail Drawing (Centered)
102+
let tailPath = UIBezierPath()
103+
let tailCenterX = totalWidth / 2
104+
tailPath.move(to: CGPoint(x: tailCenterX - 6, y: bubbleHeight))
105+
tailPath.addLine(to: CGPoint(x: tailCenterX, y: totalHeight))
106+
tailPath.addLine(to: CGPoint(x: tailCenterX + 6, y: bubbleHeight))
107+
tailPath.close()
108+
UIColor.white.setFill()
109+
tailPath.fill()
110+
111+
// 2. Left Bubble
112+
let leftBubbleRect = CGRect(
113+
x: Layout.leftBubblePadding,
114+
y: 0,
115+
width: leftBubbleWidth,
116+
height: bubbleHeight
117+
)
118+
let leftBubblePath = UIBezierPath(roundedRect: leftBubbleRect, cornerRadius: Layout.cornerRadius)
119+
UIColor.systemMint.withAlphaComponent(0.2).setFill()
120+
leftBubblePath.fill()
121+
122+
// Left Text Position
123+
(leftText as NSString).draw(
124+
at: CGPoint(
125+
x: Layout.leftBubblePadding + Layout.horizontalPadding,
126+
y: (bubbleHeight - leftTextSize.height) / 2
127+
),
128+
withAttributes: leftAttributes
129+
)
130+
131+
// 3. Right Bubble
132+
let rightBubbleRect = CGRect(
133+
x: Layout.leftBubblePadding + leftBubbleWidth + Layout.spacing,
134+
y: 0,
135+
width: rightBubbleWidth,
136+
height: bubbleHeight
137+
)
138+
let rightBubblePath = UIBezierPath(roundedRect: rightBubbleRect, cornerRadius: Layout.cornerRadius)
139+
UIColor.clear.setFill()
140+
rightBubblePath.fill()
141+
142+
// Right Text Position
143+
(rightText as NSString).draw(
144+
at: CGPoint(
145+
x: Layout.leftBubblePadding + leftBubbleWidth + Layout.spacing + Layout.horizontalPadding,
146+
y: (bubbleHeight - rightTextSize.height) / 2
147+
),
148+
withAttributes: rightAttributes
149+
)
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)