添加 'mayfinal.js'

main
alimu 2 years ago
parent 2858ede8f3
commit 4b438c7635

@ -0,0 +1,310 @@
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 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(coord.innerText);
}
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 etsize = calTileSize();
// if (zoom_level != Math.floor(zoom_level)) {
// console.log('resize', etsize, tilesize, lat, lng)
// lat = tile2lat(mlc.y / etsize * tilesize, Math.floor(zoom_level + 1));
// lng = tile2long(mlc.x / etsize * tilesize, Math.floor(zoom_level + 1));
// }
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))));
}
//=========
Loading…
Cancel
Save