]> git.r.bdr.sh - rbdr/map/blob - Map/Presentation/Base Components/MapRender/MapVertices.swift
74cac6d6ccb4b171e426cc4b93dae740dae034d5
[rbdr/map] / Map / Presentation / Base Components / MapRender / MapVertices.swift
1 import SwiftUI
2
3 struct MapVertices: View {
4
5 let mapSize: CGSize
6 let vertexSize: CGSize
7 let vertices: [Vertex]
8 let padding = CGFloat(5.0)
9
10 var body: some View {
11 ZStack(alignment: .topLeading) {
12 ForEach(vertices, id: \.id) { vertex in
13 getVertexShape(vertex).fill(Color.map.vertexColor)
14 Text(vertex.label.replacingOccurrences(of: "\\n", with: "\n")).font(.theme.vertexLabel)
15 .foregroundColor(.map.labelColor)
16 .shadow(color: .white, radius: 0, x: -0.5, y: -0.5)
17 .shadow(color: .white, radius: 0, x: 0.5, y: 0.5)
18 .offset(
19 CGSize(
20 width: w(vertex.position.x) + vertexSize.width + padding,
21 height: h(vertex.position.y) + 7.0))
22 }
23 }
24 }
25
26 func h(_ dimension: CGFloat) -> CGFloat {
27 max(0.0, min(mapSize.height, dimension * mapSize.height / 100.0))
28 }
29
30 func w(_ dimension: CGFloat) -> CGFloat {
31 max(0.0, min(mapSize.width, dimension * mapSize.width / 100.0))
32 }
33
34 func getVertexShape(_ vertex: Vertex) -> Path {
35 switch vertex.shape {
36 case .circle:
37 return Path { path in
38 path.addEllipse(
39 in: CGRect(
40 origin: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y)), size: vertexSize
41 ))
42 }
43 case .square:
44 return Path { path in
45 path.addRect(
46 CGRect(
47 x: w(vertex.position.x), y: h(vertex.position.y), width: vertexSize.width,
48 height: vertexSize.height
49 ))
50 }
51 case .triangle:
52 return Path { path in
53 path.move(to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y) + vertexSize.height))
54 path.addLine(
55 to: CGPoint(
56 x: w(vertex.position.x) + vertexSize.width, y: h(vertex.position.y) + vertexSize.height)
57 )
58 path.addLine(
59 to: CGPoint(x: w(vertex.position.x) + vertexSize.width / 2.0, y: h(vertex.position.y)))
60 path.addLine(
61 to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y) + vertexSize.height))
62 path.closeSubpath()
63 }
64 case .x:
65 return Path { path in
66 path.move(to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y)))
67 path.addLine(
68 to: CGPoint(
69 x: w(vertex.position.x) + vertexSize.width, y: h(vertex.position.y) + vertexSize.height)
70 )
71 path.closeSubpath()
72 path.move(to: CGPoint(x: w(vertex.position.x) + vertexSize.width, y: h(vertex.position.y)))
73 path.addLine(
74 to: CGPoint(x: w(vertex.position.x), y: h(vertex.position.y) + vertexSize.height))
75 path.closeSubpath()
76 }.strokedPath(StrokeStyle(lineWidth: 2.0, lineCap: .butt))
77 }
78 }
79 }
80
81 struct MapVertices_Previews: PreviewProvider {
82 static var previews: some View {
83 MapVertices(
84 mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0),
85 vertices: [
86 Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)),
87 Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square),
88 Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle),
89 Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x),
90 ])
91 }
92 }