parent
d2f59ebc42
commit
d4169af3ea
@ -1,32 +0,0 @@
|
|||||||
web:
|
|
||||||
image: nginx
|
|
||||||
ports:
|
|
||||||
- 1080:80
|
|
||||||
volumes:
|
|
||||||
- ./nginx_conf/nginx:/etc/nginx
|
|
||||||
- ./dist:/usr/share/nginx/html:ro
|
|
||||||
|
|
||||||
#include /etc/nginx/conf.d/*.conf;
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
#listen [::]:80;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /m {
|
|
||||||
rewrite .* /index.html permanent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#error_page 404 /404.html;
|
|
||||||
# redirect server error pages to the static page /50x.html
|
|
||||||
#
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,43 +1,51 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
<head>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<title>tilerendertest</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<style>
|
<title>tilerendertest</title>
|
||||||
*{
|
<style>
|
||||||
margin: 0;
|
* {
|
||||||
padding: 0;
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
.main{
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
.main {
|
||||||
align-items: center;
|
display: flex;
|
||||||
background-color: white;
|
justify-content: center;
|
||||||
width: 100vw;
|
align-items: center;
|
||||||
height: 100vh;
|
background-color: #ebebeb;
|
||||||
}
|
width: 100vw;
|
||||||
.container{
|
height: 100vh;
|
||||||
flex:1;
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
.container {
|
||||||
align-items: center;
|
flex: 1;
|
||||||
}
|
display: flex;
|
||||||
.map{
|
justify-content: center;
|
||||||
/* background-color: #ddd; */
|
align-items: center;
|
||||||
background-color: #4c2626;
|
}
|
||||||
width: 1600px;
|
|
||||||
height: 900px;
|
.map {
|
||||||
}
|
/* background-color: #ddd; */
|
||||||
</style>
|
background-color: #cdcdcd;
|
||||||
</head>
|
width: 100vw;
|
||||||
<body>
|
height: 100vh;
|
||||||
<div class="main">
|
/* width: 512px;
|
||||||
<div class="container">
|
height: 512px; */
|
||||||
<canvas class="map" id="map"></canvas>
|
}
|
||||||
</div>
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<div class="container">
|
||||||
|
<canvas class="map" id="map"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<script src="../ellipsode.js"></script>
|
</div>
|
||||||
</body>
|
<script src="./index.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import * as Basemap from './src/basemap.js'
|
||||||
|
document.addEventListener('contextmenu', function (event) {
|
||||||
|
event.preventDefault() // 阻止浏览器默认右键菜单的显示
|
||||||
|
})
|
||||||
|
|
||||||
|
Basemap.setDomById('map')
|
||||||
|
Basemap.setCanvasSize()
|
||||||
|
window.addEventListener('resize', Basemap.setCanvasSize)
|
||||||
|
|
||||||
|
// Basemap.setCenterByWgs84(22.54, 114.06, 18)
|
||||||
@ -1,333 +0,0 @@
|
|||||||
let map = document.getElementById('map');
|
|
||||||
let coord = document.getElementById('coord');
|
|
||||||
map.width = map.clientWidth;
|
|
||||||
map.height = map.clientHeight;
|
|
||||||
let ctx = map.getContext('2d');
|
|
||||||
|
|
||||||
const tilesize = 256;
|
|
||||||
const minlevel = 3;
|
|
||||||
const maxlevel = 18;
|
|
||||||
let zoom_level = 3; //默认
|
|
||||||
|
|
||||||
let viewport = {};
|
|
||||||
viewport.width = map.width; //默认已知
|
|
||||||
viewport.height = map.height; //默认已知
|
|
||||||
viewport.centerx = Math.pow(2, zoom_level) * 256 / 2; //默认
|
|
||||||
viewport.centery = Math.pow(2, zoom_level) * 256 / 2; //默认
|
|
||||||
|
|
||||||
viewport.xoffset = (viewport.width / 2 - viewport.centerx);
|
|
||||||
viewport.yoffset = (viewport.height / 2 - viewport.centery);
|
|
||||||
|
|
||||||
let needtiles = new Array();
|
|
||||||
let cache = new Array();
|
|
||||||
|
|
||||||
let alltilecount = 0;
|
|
||||||
let downtilecount = 0;
|
|
||||||
let drecord = new Array();
|
|
||||||
|
|
||||||
function calTileSize() {
|
|
||||||
let etsize = tilesize;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
etsize = tilesize * Math.pow(2, zoom_level - Math.floor(zoom_level + 1));
|
|
||||||
}
|
|
||||||
return etsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calTileNum(coord) {
|
|
||||||
return Math.floor(coord / calTileSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
function tilesfilter(tails) {
|
|
||||||
let news = new Array();
|
|
||||||
let max = Math.pow(2, zoom_level);
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
max = Math.pow(2, Math.floor(zoom_level + 1));
|
|
||||||
}
|
|
||||||
for (let i = 0; i < tails.length; i++) {
|
|
||||||
const e = tails[i];
|
|
||||||
if (e.x >= 0 && e.y >= 0 && e.x < max && e.y < max) {
|
|
||||||
news.push(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return news;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function clearcanvas() {
|
|
||||||
ctx.clearRect(0, 0, map.width, map.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawRect(x, y, width, height) {
|
|
||||||
ctx.strokeStyle = "white"
|
|
||||||
ctx.strokeRect(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawtext(text, x, y) {
|
|
||||||
ctx.fillStyle = "white"
|
|
||||||
ctx.font = "18px serif";
|
|
||||||
ctx.textAlign = "center";
|
|
||||||
ctx.textBaseline = "middle";
|
|
||||||
ctx.fillText(text, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mplat2viewport(mx, my) {
|
|
||||||
const vx = mx + viewport.xoffset;
|
|
||||||
const vy = my + viewport.yoffset;
|
|
||||||
return { x: vx, y: vy };
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewport2mplat(vx, vy) {
|
|
||||||
const mx = vx - viewport.xoffset;
|
|
||||||
const my = vy - viewport.yoffset;
|
|
||||||
return { x: mx, y: my };
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewport2wgs84(vx, vy) {
|
|
||||||
const mlc = viewport2mplat(vx, vy);
|
|
||||||
//数据超界处理, 这里对应缩放等级的地图的大小是
|
|
||||||
const limit = calTileSize() * Math.pow(2, zoom_level);
|
|
||||||
console.log(calTileSize());
|
|
||||||
if (vx <= 0 || vy <= 0 || vx >= limit || vy >= limit) {
|
|
||||||
throw "OutMapRange";
|
|
||||||
}
|
|
||||||
const lat = tile2lat(mlc.y / tilesize, zoom_level);
|
|
||||||
const lng = tile2long(mlc.x / tilesize, zoom_level);
|
|
||||||
return { lat: lat, lng: lng }
|
|
||||||
}
|
|
||||||
|
|
||||||
function wgs84toviewport(lat, lng) {
|
|
||||||
//数据超界处理 经度 -180 180
|
|
||||||
//85.0511287798066 (2*Math.atan(Math.pow(Math.E,Math.PI))-Math.PI/2)/Math.PI*180
|
|
||||||
const latlimit = 85.051128;
|
|
||||||
const lngp = lng - Math.floor((lng + 180) / 360) * 360;
|
|
||||||
if (lat < (0 - latlimit) || lat > latlimit) {
|
|
||||||
throw "OutMapRange";
|
|
||||||
}
|
|
||||||
const my = lat2y(lat, zoom_level) * tilesize;
|
|
||||||
const mx = lon2x(lngp, zoom_level) * tilesize;
|
|
||||||
const vp = mplat2viewport(mx, my);
|
|
||||||
return { x: vp.x, y: vp.y };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function updateviewporttest(scrollx, scrolly, oldz, newz) {
|
|
||||||
//计算出缩放后坐标系的偏移值
|
|
||||||
// xv = xm + offset ; offset = xv - xm
|
|
||||||
//const newz = zoom_level;
|
|
||||||
const scrollm = viewport2mplat(scrollx, scrolly);
|
|
||||||
//const basescale = 2 * Math.pow(2, newz) / Math.pow(2, Math.floor(newz) + 1);
|
|
||||||
console.log('zoomlevel : ', newz, oldz);
|
|
||||||
const basescale = Math.pow(2, newz - oldz);
|
|
||||||
console.log('basescale: ', basescale);
|
|
||||||
const newscrollm = { x: scrollm.x * basescale, y: scrollm.y * basescale };
|
|
||||||
console.log('缩放点新坐标 ', newscrollm);
|
|
||||||
viewport.xoffset = scrollx - newscrollm.x;
|
|
||||||
viewport.yoffset = scrolly - newscrollm.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
//test
|
|
||||||
function drawtest() {
|
|
||||||
ctx.clearRect(0, 0, map.width, map.height);
|
|
||||||
const viewport_left_top = viewport2mplat(0, 0);
|
|
||||||
const viewport_right_bottom = viewport2mplat(viewport.width, viewport.height);
|
|
||||||
const mixnum = calTileNum(viewport_left_top.x);
|
|
||||||
const miynum = calTileNum(viewport_left_top.y);
|
|
||||||
const maxnum = calTileNum(viewport_right_bottom.x);
|
|
||||||
const maynum = calTileNum(viewport_right_bottom.y);
|
|
||||||
const horicount = maxnum - mixnum + 1;
|
|
||||||
const verticount = maynum - miynum + 1;
|
|
||||||
|
|
||||||
clearcanvas();
|
|
||||||
let tails = new Array();
|
|
||||||
for (let i = 0; i < horicount; i++) {
|
|
||||||
for (let j = 0; j < verticount; j++) {
|
|
||||||
const x = mixnum + i;
|
|
||||||
const y = miynum + j;
|
|
||||||
tails.push({ x: x, y: y });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
needtiles = tilesfilter(tails);
|
|
||||||
alltilecount += needtiles.length;
|
|
||||||
//console.log(needtiles.length, needtiles);
|
|
||||||
needtiles.forEach(et => {
|
|
||||||
const etsize = calTileSize();
|
|
||||||
//const tilev = mplat2viewport(et.x * etsize, et.y * etsize);
|
|
||||||
//drawRect(tilev.x, tilev.y, etsize, etsize);
|
|
||||||
let z = zoom_level;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
z = Math.floor(zoom_level + 1);
|
|
||||||
}
|
|
||||||
const text = `${z}/${et.x}/${et.y}.png`;
|
|
||||||
console.log(text);
|
|
||||||
//drawtext(text, tilev.x + etsize / 2, tilev.y + etsize / 2);
|
|
||||||
drawTileImg(z, et.x, et.y);
|
|
||||||
});
|
|
||||||
debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
let moveflag = false;
|
|
||||||
let downpoing = { x: 0, y: 0 };
|
|
||||||
map.onmousedown = (e) => {
|
|
||||||
console.log('鼠标按下');
|
|
||||||
moveflag = true;
|
|
||||||
downpoing.x = e.offsetX;
|
|
||||||
downpoing.y = e.offsetY;
|
|
||||||
console.log(zoom_level, e.offsetX, e.offsetY);
|
|
||||||
const wgs84 = viewport2wgs84(e.offsetX, e.offsetY);
|
|
||||||
console.log(wgs84, 'check', wgs84toviewport(wgs84.lat, wgs84.lng));
|
|
||||||
}
|
|
||||||
map.onmouseup = (e) => {
|
|
||||||
console.log('鼠标松开');
|
|
||||||
moveflag = false;
|
|
||||||
}
|
|
||||||
map.onmousemove = (e) => {
|
|
||||||
//输出latlng
|
|
||||||
//const mlc = viewport2mplat(e.offsetX, e.offsetY);
|
|
||||||
//let lat = tile2lat(mlc.y / tilesize, zoom_level);
|
|
||||||
//let lng = tile2long(mlc.x / tilesize, zoom_level);
|
|
||||||
//const coordstr = `(${e.offsetX},${e.offsetY}) - (${mlc.x.toFixed(3)},${mlc.y.toFixed(3)}) - (${lat},${lng})`;
|
|
||||||
//coord.innerText = coordstr;
|
|
||||||
//console.log(e.offsetX, e.offsetY);
|
|
||||||
if (moveflag) {
|
|
||||||
console.log('有效位移');
|
|
||||||
const movex = downpoing.x - e.offsetX;
|
|
||||||
const movey = downpoing.y - e.offsetY;
|
|
||||||
//实现移动逻辑
|
|
||||||
viewport.xoffset -= movex;
|
|
||||||
viewport.yoffset -= movey;
|
|
||||||
|
|
||||||
drawtest();
|
|
||||||
downpoing.x = e.offsetX;
|
|
||||||
downpoing.y = e.offsetY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
map.onwheel = (e) => {
|
|
||||||
//console.log(e);
|
|
||||||
const ds = 0.25;
|
|
||||||
const zoomleveloffset = (e.deltaY > 0) ? 1 * ds : -1 * ds;
|
|
||||||
const oldz = zoom_level;
|
|
||||||
zoom_level = zoom_level - zoomleveloffset;
|
|
||||||
if (zoom_level < minlevel) {
|
|
||||||
zoom_level = minlevel;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zoom_level > maxlevel) {
|
|
||||||
zoom_level = maxlevel;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(zoom_level, e.offsetX, e.offsetY);
|
|
||||||
updateviewporttest(e.offsetX, e.offsetY, oldz, zoom_level);
|
|
||||||
drawtest();
|
|
||||||
}
|
|
||||||
|
|
||||||
drawtest();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Array.prototype.remove = function (val) {
|
|
||||||
const index = this.indexOf(val);
|
|
||||||
if (index > -1) {
|
|
||||||
return this.splice(index, 1);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add opeenstreetmap
|
|
||||||
function downloadimg(z, x, y) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
//const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
|
|
||||||
const url = 'http://webrd01.is.autonavi.com/' +
|
|
||||||
'appmaptile?lang=zh_cn&size=1&scale=1&style=8' +
|
|
||||||
`&x=${x}&y=${y}&z=${z}`;
|
|
||||||
//add downloadcheck
|
|
||||||
const obj = { z: z, x: x, y: y };
|
|
||||||
drecord.push(obj); //下载前加入记录
|
|
||||||
let img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
console.log('downloaded' + z + '/' + x + '/' + y + '.png');
|
|
||||||
cache.push({ img: img, z: z, x: x, y: y });
|
|
||||||
drecord.remove(obj); //下载完成后从记录中移除
|
|
||||||
downtilecount += 1;
|
|
||||||
resolve(img);
|
|
||||||
}
|
|
||||||
img.src = url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getImg(z, x, y) {
|
|
||||||
//先判断是否加入下载记录
|
|
||||||
const isdownloading = drecord.includes({ z: z, x: x, y: y });
|
|
||||||
if (isdownloading) {
|
|
||||||
//return getImg(z, x, y);
|
|
||||||
return setTimeout(() => {
|
|
||||||
getImg(z, x, y);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
const found = cache.find(e => (e.z == z && e.x == x && e.y == y));
|
|
||||||
if (found == undefined) {
|
|
||||||
let p = await downloadimg(z, x, y);
|
|
||||||
return p;
|
|
||||||
} else {
|
|
||||||
console.log('exist' + z + '/' + x + '/' + y + '.png');
|
|
||||||
return found.img;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawTileImg(z, x, y) {
|
|
||||||
const img = getImg(z, x, y);
|
|
||||||
img.then((e) => {
|
|
||||||
const etsize = calTileSize();
|
|
||||||
const tilev = mplat2viewport(x * etsize, y * etsize);
|
|
||||||
let fz = zoom_level;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
fz = Math.floor(zoom_level + 1);
|
|
||||||
}
|
|
||||||
if (needtiles.find(t => z == fz && t.x == x && t.y == y)) {
|
|
||||||
ctx.drawImage(e, tilev.x, tilev.y, etsize, etsize);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function debug() {
|
|
||||||
console.log('=============debug=================');
|
|
||||||
console.log('zoom_level', zoom_level);
|
|
||||||
console.log('alltilecount', alltilecount);
|
|
||||||
console.log('downtilecount', downtilecount);
|
|
||||||
console.log('cachecount', caches.length);
|
|
||||||
console.log('drecord count', drecord.length);
|
|
||||||
console.log('=============debug=================');
|
|
||||||
}
|
|
||||||
|
|
||||||
//=====coord about=====
|
|
||||||
function lon2tile(lon, z) {
|
|
||||||
return (Math.floor((lon + 180) / 360 * Math.pow(2, z)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function lat2tile(lat, z) {
|
|
||||||
return (Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) +
|
|
||||||
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) /
|
|
||||||
2 * Math.pow(2, z)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function lon2x(lon, z) {
|
|
||||||
return ((lon + 180) / 360 * Math.pow(2, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
function lat2y(lat, z) {
|
|
||||||
return ((1 - Math.log(Math.tan(lat * Math.PI / 180) +
|
|
||||||
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) /
|
|
||||||
2 * Math.pow(2, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
function tile2long(x, z) {
|
|
||||||
return (x / Math.pow(2, z) * 360 - 180);
|
|
||||||
}
|
|
||||||
|
|
||||||
function tile2lat(y, z) {
|
|
||||||
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
|
|
||||||
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========
|
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "formaptile",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://atsw.top:3000/alimu/formaptile.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
@ -0,0 +1,220 @@
|
|||||||
|
import {
|
||||||
|
viewport,
|
||||||
|
calTileNum,
|
||||||
|
calTileSize,
|
||||||
|
setViewportSize,
|
||||||
|
setViewportCenterByWgs84,
|
||||||
|
setViewportCenterByMap,
|
||||||
|
map2viewport,
|
||||||
|
viewport2map,
|
||||||
|
updateZoomLevel,
|
||||||
|
} from './viewport.js'
|
||||||
|
|
||||||
|
import * as Tiles from './tiles.js'
|
||||||
|
|
||||||
|
let map = undefined
|
||||||
|
|
||||||
|
export function setDomById(id) {
|
||||||
|
map = document.getElementById(id)
|
||||||
|
console.debug('底图挂载在', map)
|
||||||
|
//添加响应事件
|
||||||
|
// let moveflag = false
|
||||||
|
// let downpoing = { x: 0, y: 0 }
|
||||||
|
const minlevel = 3
|
||||||
|
const maxlevel = 18
|
||||||
|
map.onwheel = (e) => {
|
||||||
|
const ds = 0.25
|
||||||
|
const zoomleveloffset = e.deltaY > 0 ? 1 * ds : -1 * ds
|
||||||
|
let newz = viewport.zoom_level
|
||||||
|
newz = newz - zoomleveloffset
|
||||||
|
if (newz < minlevel) {
|
||||||
|
newz = minlevel
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newz > maxlevel) {
|
||||||
|
newz = maxlevel
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateZoomLevel(e.offsetX, e.offsetY, newz)
|
||||||
|
savePosInfo()
|
||||||
|
drawGrid()
|
||||||
|
}
|
||||||
|
|
||||||
|
let moveflag = false
|
||||||
|
let downpoing = { x: 0, y: 0 }
|
||||||
|
map.onmousedown = (e) => {
|
||||||
|
//console.log('鼠标按下')
|
||||||
|
moveflag = true
|
||||||
|
downpoing.x = e.offsetX
|
||||||
|
downpoing.y = e.offsetY
|
||||||
|
//console.log(viewport.zoom_level, e.offsetX, e.offsetY)
|
||||||
|
// try {
|
||||||
|
// const wgs84 = viewport2wgs84(e.offsetX, e.offsetY)
|
||||||
|
// console.log(
|
||||||
|
// 'check',
|
||||||
|
// { x: e.offsetX, y: e.offsetY },
|
||||||
|
// wgs84,
|
||||||
|
// wgs84toviewport(wgs84.lat, wgs84.lon)
|
||||||
|
// )
|
||||||
|
// } catch (error) {
|
||||||
|
// //console.log(error)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
map.onmouseup = (e) => {
|
||||||
|
//console.log('鼠标松开')
|
||||||
|
moveflag = false
|
||||||
|
}
|
||||||
|
map.onmousemove = (e) => {
|
||||||
|
//输出latlng
|
||||||
|
//const mlc = viewport2map(e.offsetX, e.offsetY)
|
||||||
|
// const wgs84 = viewport2wgs84(e.offsetX, e.offsetY)
|
||||||
|
// const coordstr = `(${e.offsetX},${e.offsetY})->(${mlc.x.toFixed(
|
||||||
|
// 3
|
||||||
|
// )},${mlc.y.toFixed(3)})->(${wgs84.lat},${wgs84.lon})`
|
||||||
|
// console.log(coordstr)
|
||||||
|
if (moveflag) {
|
||||||
|
//console.log('有效位移')
|
||||||
|
const movex = downpoing.x - e.offsetX
|
||||||
|
const movey = downpoing.y - e.offsetY
|
||||||
|
//实现移动逻辑
|
||||||
|
viewport.xoffset -= movex
|
||||||
|
viewport.yoffset -= movey
|
||||||
|
savePosInfo()
|
||||||
|
drawGrid()
|
||||||
|
downpoing.x = e.offsetX
|
||||||
|
downpoing.y = e.offsetY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function getContext() {
|
||||||
|
if (map) {
|
||||||
|
return map.getContext('2d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePosInfo() {
|
||||||
|
const mcenter = viewport2map(viewport.width / 2, viewport.height / 2)
|
||||||
|
let poseInfo = {
|
||||||
|
mx: mcenter.x,
|
||||||
|
my: mcenter.y,
|
||||||
|
zoom_level: viewport.zoom_level,
|
||||||
|
}
|
||||||
|
localStorage.setItem('poseInfo-nas22udfh12', JSON.stringify(poseInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCanvasSize() {
|
||||||
|
if (map) {
|
||||||
|
map.width = map.clientWidth
|
||||||
|
map.height = map.clientHeight
|
||||||
|
//console.debug('重新设置大小', map.width, map.height)
|
||||||
|
//init
|
||||||
|
setViewportSize(map.width, map.height)
|
||||||
|
//随机用一个标识
|
||||||
|
const poseInfoStr = localStorage.getItem('poseInfo-nas22udfh12')
|
||||||
|
const poseInfo = JSON.parse(poseInfoStr)
|
||||||
|
if (poseInfo) {
|
||||||
|
setViewportCenterByMap(
|
||||||
|
poseInfo.mx,
|
||||||
|
poseInfo.my,
|
||||||
|
poseInfo.zoom_level
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
setViewportCenterByWgs84(0, 0, 3)
|
||||||
|
}
|
||||||
|
//draw
|
||||||
|
drawGrid()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCenterByWgs84(lat, lon, z) {
|
||||||
|
setViewportCenterByWgs84(lat, lon, z)
|
||||||
|
drawGrid()
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawRect(x, y, width, height) {
|
||||||
|
const ctx = getContext()
|
||||||
|
ctx.strokeStyle = 'white'
|
||||||
|
ctx.strokeRect(x, y, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
const ctx = getContext()
|
||||||
|
ctx.clearRect(0, 0, map.width, map.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawtext(text, x, y) {
|
||||||
|
const ctx = getContext()
|
||||||
|
ctx.fillStyle = 'white'
|
||||||
|
ctx.font = '18px serif'
|
||||||
|
ctx.textAlign = 'center'
|
||||||
|
ctx.textBaseline = 'middle'
|
||||||
|
ctx.fillText(text, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTileImg(z, x, y) {
|
||||||
|
const img = Tiles.getImg(z, x, y)
|
||||||
|
img.then((e) => {
|
||||||
|
const etsize = calTileSize()
|
||||||
|
const tilev = map2viewport(x * etsize, y * etsize)
|
||||||
|
let fz = viewport.zoom_level
|
||||||
|
if (fz != Math.floor(fz)) {
|
||||||
|
fz = Math.floor(fz + 1)
|
||||||
|
}
|
||||||
|
if (needtiles.find((t) => z == fz && t.x == x && t.y == y)) {
|
||||||
|
const ctx = getContext()
|
||||||
|
ctx.drawImage(e, tilev.x, tilev.y, etsize, etsize)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function tilesfilter(tails) {
|
||||||
|
const zoom_level = viewport.zoom_level
|
||||||
|
let news = new Array()
|
||||||
|
let max = Math.pow(2, zoom_level)
|
||||||
|
if (zoom_level != Math.floor(zoom_level)) {
|
||||||
|
max = Math.pow(2, Math.floor(zoom_level + 1))
|
||||||
|
}
|
||||||
|
for (let i = 0; i < tails.length; i++) {
|
||||||
|
const e = tails[i]
|
||||||
|
if (e.x >= 0 && e.y >= 0 && e.x < max && e.y < max) {
|
||||||
|
news.push(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return news
|
||||||
|
}
|
||||||
|
|
||||||
|
let needtiles = new Array()
|
||||||
|
export function drawGrid() {
|
||||||
|
clear()
|
||||||
|
const viewport_left_top = viewport2map(0, 0)
|
||||||
|
const viewport_right_bottom = viewport2map(viewport.width, viewport.height)
|
||||||
|
const mixnum = calTileNum(viewport_left_top.x)
|
||||||
|
const miynum = calTileNum(viewport_left_top.y)
|
||||||
|
const maxnum = calTileNum(viewport_right_bottom.x)
|
||||||
|
const maynum = calTileNum(viewport_right_bottom.y)
|
||||||
|
const horicount = maxnum - mixnum + 1
|
||||||
|
const verticount = maynum - miynum + 1
|
||||||
|
let tails = new Array()
|
||||||
|
for (let i = 0; i < horicount; i++) {
|
||||||
|
for (let j = 0; j < verticount; j++) {
|
||||||
|
const x = mixnum + i
|
||||||
|
const y = miynum + j
|
||||||
|
tails.push({ x: x, y: y })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needtiles = tilesfilter(tails)
|
||||||
|
needtiles.forEach((et) => {
|
||||||
|
let z = viewport.zoom_level
|
||||||
|
if (z != Math.floor(z)) {
|
||||||
|
z = Math.floor(z + 1)
|
||||||
|
}
|
||||||
|
// const etsize = calTileSize()
|
||||||
|
// const tilev = map2viewport(et.x * etsize, et.y * etsize)
|
||||||
|
//drawRect(tilev.x, tilev.y, etsize, etsize)
|
||||||
|
//const text = `${z}/${et.x}/${et.y}.png`
|
||||||
|
//console.log(text)
|
||||||
|
//drawtext(text, tilev.x + etsize / 2, tilev.y + etsize / 2)
|
||||||
|
drawTileImg(z, et.x, et.y)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
Array.prototype.remove = function (val) {
|
||||||
|
const index = this.indexOf(val)
|
||||||
|
if (index > -1) {
|
||||||
|
return this.splice(index, 1)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
const cache = new Array()
|
||||||
|
const downloadingRecord = new Array()
|
||||||
|
|
||||||
|
//const tileserverUrl =
|
||||||
|
//openstreetmap
|
||||||
|
//const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
|
||||||
|
|
||||||
|
function downloadimg(z, x, y) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const url =
|
||||||
|
'https://webrd01.is.autonavi.com/' +
|
||||||
|
'appmaptile?lang=zh_cn&size=1&scale=1&style=8' +
|
||||||
|
`&x=${x}&y=${y}&z=${z}`
|
||||||
|
//add downloadcheck
|
||||||
|
const obj = { z: z, x: x, y: y }
|
||||||
|
downloadingRecord.push(obj) //下载前加入记录
|
||||||
|
let img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
cache.push({ img: img, z: z, x: x, y: y })
|
||||||
|
downloadingRecord.remove(obj) //下载完成后从记录中移除
|
||||||
|
resolve(img)
|
||||||
|
}
|
||||||
|
img.referrerPolicy = 'no-referrer'
|
||||||
|
img.src = url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getImg(z, x, y) {
|
||||||
|
//先判断是否加入下载记录
|
||||||
|
const isdownloading = downloadingRecord.includes({ z: z, x: x, y: y })
|
||||||
|
if (isdownloading) {
|
||||||
|
//return getImg(z, x, y);
|
||||||
|
return setTimeout(() => {
|
||||||
|
getImg(z, x, y)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
const found = cache.find((e) => e.z == z && e.x == x && e.y == y)
|
||||||
|
if (found == undefined) {
|
||||||
|
let p = await downloadimg(z, x, y)
|
||||||
|
return p
|
||||||
|
} else {
|
||||||
|
return found.img
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
//=====coord about=====
|
||||||
|
export function lon2tile(lon, z) {
|
||||||
|
return Math.floor(((lon + 180) / 360) * Math.pow(2, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lat2tile(lat, z) {
|
||||||
|
return Math.floor(
|
||||||
|
((1 -
|
||||||
|
Math.log(
|
||||||
|
Math.tan((lat * Math.PI) / 180) +
|
||||||
|
1 / Math.cos((lat * Math.PI) / 180)
|
||||||
|
) /
|
||||||
|
Math.PI) /
|
||||||
|
2) *
|
||||||
|
Math.pow(2, z)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lon2x(lon, z) {
|
||||||
|
return ((lon + 180) / 360) * Math.pow(2, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lat2y(lat, z) {
|
||||||
|
return (
|
||||||
|
((1 -
|
||||||
|
Math.log(
|
||||||
|
Math.tan((lat * Math.PI) / 180) +
|
||||||
|
1 / Math.cos((lat * Math.PI) / 180)
|
||||||
|
) /
|
||||||
|
Math.PI) /
|
||||||
|
2) *
|
||||||
|
Math.pow(2, z)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tile2long(x, z) {
|
||||||
|
return (x / Math.pow(2, z)) * 360 - 180
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tile2lat(y, z) {
|
||||||
|
var n = Math.PI - (2 * Math.PI * y) / Math.pow(2, z)
|
||||||
|
return (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========
|
||||||
@ -1,251 +0,0 @@
|
|||||||
let map = document.getElementById('map');
|
|
||||||
map.width = map.clientWidth;
|
|
||||||
map.height = map.clientHeight;
|
|
||||||
let ctx = map.getContext('2d');
|
|
||||||
|
|
||||||
const tilesize = 256;
|
|
||||||
const minlevel = 0;
|
|
||||||
const maxlevel = 19;
|
|
||||||
let zoom_level = 0; //默认
|
|
||||||
|
|
||||||
let viewport = {};
|
|
||||||
viewport.width = map.width; //默认已知
|
|
||||||
viewport.height = map.height; //默认已知
|
|
||||||
viewport.centerx = Math.pow(2, zoom_level) * 256 / 2; //默认
|
|
||||||
viewport.centery = Math.pow(2, zoom_level) * 256 / 2; //默认
|
|
||||||
|
|
||||||
viewport.xoffset = (viewport.width / 2 - viewport.centerx);
|
|
||||||
viewport.yoffset = (viewport.height / 2 - viewport.centery);
|
|
||||||
|
|
||||||
let needtiles = new Array();
|
|
||||||
let cache = new Array();
|
|
||||||
let xhrmanager = new Array();
|
|
||||||
|
|
||||||
function calTileSize() {
|
|
||||||
let etsize = tilesize;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
etsize = tilesize * Math.pow(2, zoom_level - Math.floor(zoom_level + 1));
|
|
||||||
}
|
|
||||||
return etsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calTileNum(coord) {
|
|
||||||
return Math.floor(coord / calTileSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
function tilesfilter(tails) {
|
|
||||||
let news = new Array();
|
|
||||||
let max = Math.pow(2, zoom_level);
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
max = Math.pow(2, Math.floor(zoom_level + 1));
|
|
||||||
}
|
|
||||||
for (let i = 0; i < tails.length; i++) {
|
|
||||||
const e = tails[i];
|
|
||||||
if (e.x >= 0 && e.y >= 0 && e.x < max && e.y < max) {
|
|
||||||
news.push(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return news;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function clearcanvas() {
|
|
||||||
ctx.clearRect(0, 0, map.width, map.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawRect(x, y, width, height) {
|
|
||||||
ctx.strokeStyle = "white"
|
|
||||||
ctx.strokeRect(x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawtext(text, x, y) {
|
|
||||||
ctx.fillStyle = "white"
|
|
||||||
ctx.font = "18px serif";
|
|
||||||
ctx.textAlign = "center";
|
|
||||||
ctx.textBaseline = "middle";
|
|
||||||
ctx.fillText(text, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mplat2viewport(mx, my) {
|
|
||||||
const vx = mx + viewport.xoffset;
|
|
||||||
const vy = my + viewport.yoffset;
|
|
||||||
return { x: vx, y: vy };
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewport2mplat(vx, vy) {
|
|
||||||
const mx = vx - viewport.xoffset;
|
|
||||||
const my = vy - viewport.yoffset;
|
|
||||||
return { x: mx, y: my };
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateviewporttest(scrollx, scrolly, oldz, newz) {
|
|
||||||
//计算出缩放后坐标系的偏移值
|
|
||||||
// xv = xm + offset ; offset = xv - xm
|
|
||||||
//const newz = zoom_level;
|
|
||||||
const scrollm = viewport2mplat(scrollx, scrolly);
|
|
||||||
//const basescale = 2 * Math.pow(2, newz) / Math.pow(2, Math.floor(newz) + 1);
|
|
||||||
console.log('zoomlevel : ', newz, oldz);
|
|
||||||
const basescale = Math.pow(2, newz - oldz);
|
|
||||||
console.log('basescale: ', basescale);
|
|
||||||
const newscrollm = { x: scrollm.x * basescale, y: scrollm.y * basescale };
|
|
||||||
console.log('缩放点新坐标 ', newscrollm);
|
|
||||||
viewport.xoffset = scrollx - newscrollm.x;
|
|
||||||
viewport.yoffset = scrolly - newscrollm.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
//test
|
|
||||||
function drawtest() {
|
|
||||||
ctx.clearRect(0, 0, map.width, map.height);
|
|
||||||
const viewport_left_top = viewport2mplat(0, 0);
|
|
||||||
const viewport_right_bottom = viewport2mplat(viewport.width, viewport.height);
|
|
||||||
const mixnum = calTileNum(viewport_left_top.x);
|
|
||||||
const miynum = calTileNum(viewport_left_top.y);
|
|
||||||
const maxnum = calTileNum(viewport_right_bottom.x);
|
|
||||||
const maynum = calTileNum(viewport_right_bottom.y);
|
|
||||||
const horicount = maxnum - mixnum + 1;
|
|
||||||
const verticount = maynum - miynum + 1;
|
|
||||||
|
|
||||||
clearcanvas();
|
|
||||||
xhrabort();
|
|
||||||
let tails = new Array();
|
|
||||||
for (let i = 0; i < horicount; i++) {
|
|
||||||
for (let j = 0; j < verticount; j++) {
|
|
||||||
const x = mixnum + i;
|
|
||||||
const y = miynum + j;
|
|
||||||
tails.push({ x: x, y: y });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
needtiles = tilesfilter(tails);
|
|
||||||
//console.log(needtiles.length, needtiles);
|
|
||||||
needtiles.forEach(et => {
|
|
||||||
const etsize = calTileSize();
|
|
||||||
const tilev = mplat2viewport(et.x * etsize, et.y * etsize);
|
|
||||||
//drawRect(tilev.x, tilev.y, etsize, etsize);
|
|
||||||
let z = zoom_level;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
z = Math.floor(zoom_level + 1);
|
|
||||||
}
|
|
||||||
const text = `${z}/${et.x}/${et.y}.png`;
|
|
||||||
console.log(text);
|
|
||||||
drawtext(text, tilev.x + etsize / 2, tilev.y + etsize / 2);
|
|
||||||
drawTileImg(z, et.x, et.y);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let moveflag = false;
|
|
||||||
let downpoing = { x: 0, y: 0 };
|
|
||||||
map.onmousedown = (e) => {
|
|
||||||
console.log('鼠标按下');
|
|
||||||
moveflag = true;
|
|
||||||
downpoing.x = e.offsetX;
|
|
||||||
downpoing.y = e.offsetY;
|
|
||||||
//console.log(viewport2mplat(e.offsetX, e.offsetY));
|
|
||||||
}
|
|
||||||
map.onmouseup = (e) => {
|
|
||||||
console.log('鼠标松开');
|
|
||||||
moveflag = false;
|
|
||||||
}
|
|
||||||
map.onmousemove = (e) => {
|
|
||||||
if (moveflag) {
|
|
||||||
console.log('有效位移');
|
|
||||||
const movex = downpoing.x - e.offsetX;
|
|
||||||
const movey = downpoing.y - e.offsetY;
|
|
||||||
//实现移动逻辑
|
|
||||||
viewport.xoffset -= movex;
|
|
||||||
viewport.yoffset -= movey;
|
|
||||||
|
|
||||||
drawtest();
|
|
||||||
downpoing.x = e.offsetX;
|
|
||||||
downpoing.y = e.offsetY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
map.onwheel = (e) => {
|
|
||||||
//console.log(e);
|
|
||||||
const ds = 0.25;
|
|
||||||
const zoomleveloffset = (e.deltaY > 0) ? 1 * ds : -1 * ds;
|
|
||||||
const oldz = zoom_level;
|
|
||||||
zoom_level = zoom_level - zoomleveloffset;
|
|
||||||
if (zoom_level < minlevel) {
|
|
||||||
zoom_level = minlevel;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zoom_level > maxlevel) {
|
|
||||||
zoom_level = maxlevel;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(zoom_level, e.offsetX, e.offsetY);
|
|
||||||
updateviewporttest(e.offsetX, e.offsetY, oldz, zoom_level);
|
|
||||||
drawtest();
|
|
||||||
}
|
|
||||||
|
|
||||||
drawtest();
|
|
||||||
|
|
||||||
//add opeenstreetmap
|
|
||||||
function downloadimg(z, x, y) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
|
|
||||||
let img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
console.log('downloaded' + z + '/' + x + '/' + y + '.png');
|
|
||||||
cache.push({ img: img, z: z, x: x, y: y });
|
|
||||||
resolve(img);
|
|
||||||
}
|
|
||||||
img.src = url;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//尝试优化图片下载机制
|
|
||||||
function xhrdownloadimg(z, x, y) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const url = `https://tile.openstreetmap.org/${z}/${x}/${y}.png`;
|
|
||||||
let imgxhr = new XMLHttpRequest();
|
|
||||||
imgxhr.open('GET', url, true);
|
|
||||||
//imgxhr.withCredentials = true;
|
|
||||||
imgxhr.responseType = 'blob';
|
|
||||||
imgxhr.onload = function (e) {
|
|
||||||
if (this.status === 200 && imgxhr.response) {
|
|
||||||
let blob = new Blob([imgxhr.response], { type: 'image/png' });
|
|
||||||
let img = createImageBitmap(blob);
|
|
||||||
cache.push({ img: img, z: z, x: x, y: y });
|
|
||||||
resolve(img);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhrmanager.push(imgxhr);
|
|
||||||
imgxhr.send(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function xhrabort() {
|
|
||||||
xhrmanager.forEach(element => {
|
|
||||||
element.abort();
|
|
||||||
});
|
|
||||||
xhrmanager = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getImg(z, x, y) {
|
|
||||||
const found = cache.find(e => (e.z == z && e.x == x && e.y == y));
|
|
||||||
if (found == undefined) {
|
|
||||||
let p = await xhrdownloadimg(z, x, y);
|
|
||||||
return p;
|
|
||||||
} else {
|
|
||||||
console.log('exist' + z + '/' + x + '/' + y + '.png');
|
|
||||||
return found.img;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawTileImg(z, x, y) {
|
|
||||||
const img = getImg(z, x, y);
|
|
||||||
img.then((e) => {
|
|
||||||
const etsize = calTileSize();
|
|
||||||
const tilev = mplat2viewport(x * etsize, y * etsize);
|
|
||||||
let fz = zoom_level;
|
|
||||||
if (zoom_level != Math.floor(zoom_level)) {
|
|
||||||
fz = Math.floor(zoom_level + 1);
|
|
||||||
}
|
|
||||||
if (needtiles.find(t => z == fz && t.x == x && t.y == y)) {
|
|
||||||
ctx.drawImage(e, tilev.x, tilev.y, etsize, etsize);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue