forked from lyqandy/THREE_MAP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
269 lines (238 loc) · 8.82 KB
/
index.html
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<style>
html,body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
#main {
background-color: #ddd;
}
</style>
</head>
<body>
<div id="main"></div>
</body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script>
var div = document.getElementById("main");
var width = window.innerWidth
, height = window.innerHeight;
div.style.width = width + "px";
div.style.height = height + "px";
var fov = 70
, ratio = width / height;
console.log("div", width, height);
var scene, camera, cameraControls, renderer;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(fov,ratio,1,1000);
camera.position.x = 0;
camera.position.y = -150;
camera.position.z = 300;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer({
antialias: true//抗锯齿
});
renderer.setSize(width, height);
renderer.setClearColor(0x000000);
cameraControls = new THREE.OrbitControls(camera,renderer.domElement);
cameraControls.target.set(0, 0, 0);
cameraControls.maxDistance = 400;
cameraControls.minDistance = 10;
cameraControls.update();
div.appendChild(renderer.domElement);
//创建坐标轴并加入到scene
var axes = new THREE.AxisHelper(50);
scene.add(axes);
var render = function() {
cameraControls.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
initListener();
function initListener() {
var onmousedown = function(event) {
div.style.cursor = "move";
//div.addEventListener("mousemove",onmousemove);
};
var onmouseup = function(event) {
div.style.cursor = "default";
//div.removeEventListener("mousemove",onmousemove)
};
div.addEventListener("mousedown", onmousedown);
div.addEventListener("mouseup", onmouseup);
}
/*******************************************************************/
//切图在scene中的大小
var tileSize = 50;
//地图切片服务地址
var serverURL = "http://c.tile.osm.org/";
//设置中心经纬度
var centerLng = 0, centerLat = 0;
//WGS84转Web墨卡托
//参考:http://www.opengsc.com/archives/137
function LonLat2WebMercator(lng, lat) {
var x = (lng / 180.0) * 20037508.3427892;
var y;
if (lat > 85.05112) {
lat = 85.05112;
}
if (lat < -85.05112) {
lat = -85.05112;
}
y = (Math.PI / 180.0) * lat;
var tmp = Math.PI / 4.0 + y / 2.0;
y = 20037508.3427892 * Math.log(Math.tan(tmp)) / Math.PI;
var result = {
x: x,
y: y
};
return result;
}
//Web墨卡托转成tile上的像素坐标,返回像素坐标,以及tile编号,在所在tile上的偏移
function WebMercator2Tileimage(x,y){
//对于第18级地图, 对于我国而言
var level = 18;
var r = 20037508.3427892;
y = r - y;
x = r + x;
var size = Math.pow(2, level) * 256;
var imgx = x * size / (r * 2);
var imgy = y * size / (r * 2);
//当前位置在全球切片编号
var col = Math.floor(imgx / 256);
var row = Math.floor(imgy / 256);
console.log("col", col, "row", row);
//当前位置对应于tile图像中的位置
var imgdx = imgx % 256;
var imgdy = imgy % 256;
//像素坐标
var position = {x:imgx,y:imgy};
//tile编号
var tileinfo = {x:col,y:row,level:18};
//在所在tile上的偏移
var offset = {x:imgdx,y:imgdy};
var result = {position:position,tileinfo:tileinfo,offset:offset};
return result;
}
//经纬度到tile,再到WebGL坐标
function LonLat2WebGL(lng,lat){
var webMercator = LonLat2WebMercator(lng,lat);
var tilePos = WebMercator2Tileimage(webMercator.x,webMercator.y).position;
var centerWM = LonLat2WebMercator(centerLng,centerLat);
var centerTP = WebMercator2Tileimage(centerWM.x,centerWM.y);
//相对偏移修正(以centerLng,centerLat所在点tile中心点为原点,导致的偏移)
var x = (tilePos.x - centerTP.position.x + (centerTP.offset.x - 256/2) )*tileSize/256;
var y = (tilePos.y - centerTP.position.y + (-centerTP.offset.y + 256/2))*tileSize/256;
var result = {
x: x,
y: y
};
return result;
}
/**
* 加载一个切图
* @param {Object} xno tile编号x
* @param {Object} yno tile编号y
* @param {Object} callback
*/
function loadImageTile(xno, yno, callback) {
var level = 18;
var url = serverURL + level + "/" + xno + "/" + yno + ".png";
var loader = new THREE.TextureLoader();
//跨域加载图片
loader.crossOrigin = true;
loader.load(url, function(texture) {
console.log("loaded tile");
var geometry = new THREE.PlaneGeometry(tileSize,tileSize,1);
var material = new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
side: THREE.DoubleSide//双面显示
});
var mesh = new THREE.Mesh(geometry,material);
callback(mesh);
});
}
/**
* 将加载的切图放到scene
* @param {Object} mesh
* @param {Object} x坐标 WebGL坐标
* @param {Object} y坐标
*/
function addTileToScene(mesh, x, y) {
//mesh的中心位置
mesh.position.x = x;
mesh.position.y = y;
scene.add(mesh);
}
/**
* 辅助函数,用于计算tile应该放在何处
* @param {Object} dx tile间相对位置,也就是编号差
* @param {Object} dy
*/
function addTileToSceneHelper(dx, dy) {
var x = tileSize * dx ;
var y = -tileSize * dy ;
return function(mesh) {
addTileToScene(mesh, x, y)
}
;
}
/**
* 加载地图
* @param {Object} centerX 地图中间的切图编号
* @param {Object} centerY 地图中间的切图编号
*/
function loadMap(centerX, centerY) {
var radius = 5;
for (var i = centerX - radius; i <= centerX + radius; i++) {
for (var j = centerY - radius; j <= centerY + radius; j++) {
//console.log("try to load",i,j,i-centerX,j-centerY);
console.log("try to load");
loadImageTile(i, j, addTileToSceneHelper(i - centerX, j - centerY));
}
}
}
/**
* 标记出当前位置
* @param {Object} x webGL坐标
* @param {Object} y
*/
function markCurrentPosition(x, y) {
var geometry = new THREE.SphereGeometry(10,30,30);
var material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
var mesh = new THREE.Mesh(geometry,material);
mesh.position.x = x;
mesh.position.y = y;
scene.add(mesh);
}
function main() {
navigator.geolocation.getCurrentPosition(function(position) {
var lng = position.coords.longitude;
var lat = position.coords.latitude;
console.log("current position in world", lat, lng);
centerLat = lat;
centerLng = lng;
var webMercator = LonLat2WebMercator(lng, lat);
var tilePos = WebMercator2Tileimage(webMercator.x,webMercator.y);
//以centerLng所在点tile中心点为中心,加载tile
loadMap(tilePos.tileinfo.x, tilePos.tileinfo.y);
//标记当前位置
var currentWebGLPos = LonLat2WebGL(lng,lat);
markCurrentPosition(currentWebGLPos.x,currentWebGLPos.y);
});
}
main();
</script>
</html>