-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.js
More file actions
178 lines (160 loc) · 4.58 KB
/
camera.js
File metadata and controls
178 lines (160 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* 현재 바라보고 있는 위치를 나타낸다
*/
export class Camera {
/**
* 카메라 오브젝트를 생성
* @param {number} x - 카메라의 x좌표 초기값
* @param {number} y - 카메라의 y좌표 초기값
* @param {number} xZoom - 카메라의 확대율 초기값
* @param {number} yZoom - 카메라의 확대율 초기값
*/
constructor(x, y, xZoom, yZoom) {
this.x = x;
this.y = y;
this.xZoom = xZoom;
this.yZoom = yZoom;
this.dx = 0;
this.dy = 0;
this.onlyChild = [];
this.update = false;
}
updateOnlyChild(canvas) {
const sx = this.convertScreenToMapX(canvas, 0);
const sy = this.convertScreenToMapY(canvas, 0);
const ex = this.convertScreenToMapX(canvas, canvas.width);
const ey = this.convertScreenToMapY(canvas, canvas.height);
const original = JSON.stringify(this.onlyChild);
this.dx = 0;
this.dy = 0;
this.onlyChild.length = 0;
while (true) {
const size = Math.pow(0.5, this.onlyChild.length);
const half = size / 2;
if (
this.dx <= sx &&
ex < this.dx + half &&
this.dy <= sy &&
ey < this.dy + half
) {
this.onlyChild.push(0);
continue;
}
if (
this.dx + half <= sx &&
ex < this.dx + size &&
this.dy <= sy &&
ey < this.dy + half
) {
this.onlyChild.push(1);
this.dx += half;
continue;
}
if (
this.dx <= sx &&
ex < this.dx + half &&
this.dy + half <= sy &&
ey < this.dy + size
) {
this.onlyChild.push(2);
this.dy += half;
continue;
}
if (
this.dx + half <= sx &&
ex < this.dx + size &&
this.dy + half <= sy &&
ey < this.dy + size
) {
this.onlyChild.push(3);
this.dx += half;
this.dy += half;
continue;
}
break;
}
if (original !== JSON.stringify(this.onlyChild)) {
this.update = true;
}
}
/**
* 화면상의 좌표를 현재 투영중인 지도 상의 좌표로 변경
* 이때, 지도가 평면임을 가정한다.
* @param {canvas} canvas - 전체 화면
* @param {number} screenX - 화면상의 x좌표
* @return {number} - screenX가 나타내는 지도상의 x좌표
*/
convertScreenToMapX(canvas, screenX) {
return (screenX - canvas.width / 2) / this.xZoom + this.x;
}
/**
* 지도상의 좌표를 현재 투영중인 화면 상의 좌표로 변경
* 이때, 지도가 평면임을 가정한다.
* @param {canvas} canvas - 전체 화면
* @param {number} mapX - 지도상의 x좌표
* @return {number} - mapX가 나타내는 화면상의 x좌표
*/
convertMapToScreenX(canvas, mapX) {
return (mapX - this.x) * this.xZoom + canvas.width / 2;
}
/**
* 화면상의 좌표를 현재 투영중인 지도 상의 좌표로 변경
* 이때, 지도가 평면임을 가정한다.
* @param {canvas} canvas - 전체 화면
* @param {number} screenY - 화면상의 y좌표
* @return {number} - screenY가 나타내는 지도상의 y좌표
*/
convertScreenToMapY(canvas, screenY) {
return (screenY - canvas.height / 2) / this.yZoom + this.y;
}
/**
* 지도상의 좌표를 현재 투영중인 화면 상의 좌표로 변경
* 이때, 지도가 평면임을 가정한다.
* @param {canvas} canvas - 전체 화면
* @param {number} mapY - 지도상의 y좌표
* @return {number} - mape가 나타내는 화면상의 y좌표
*/
convertMapToScreenY(canvas, mapY) {
return (mapY - this.y) * this.yZoom + canvas.height / 2;
}
/**
* 카메라의 x좌표를 설정
*/
setX(x) {
this.x = ((x % 1) + 1) % 1;
return this;
}
/**
* 카메라의 x좌표를 설정
*/
setY(y) {
this.y = Math.min(Math.max(y, 0), 1);
return this;
}
/**
* 카메라의 표시 배율을 바꿈
* @param {number} zoom - 바꿀 카메라 표시 배율
* @returns {Camera}
*/
setXZoom(zoom) {
const original = this.xZoom;
this.xZoom = Math.max(Math.min(zoom, 2000000), 2);
this.update =
this.update ||
Math.floor(Math.log2(this.xZoom)) !== Math.floor(Math.log2(original));
return this;
}
/**
* 카메라의 표시 배율을 바꿈
* @param {number} zoom - 바꿀 카메라 표시 배율
* @returns {Camera}
*/
setYZoom(zoom) {
const original = this.yZoom;
this.yZoom = Math.max(Math.min(zoom, 1000000), 1);
this.update =
this.update ||
Math.floor(Math.log2(this.yZoom)) !== Math.floor(Math.log2(original));
return this;
}
}