添加 'test.js'
parent
76234f49af
commit
d6d3aeadff
@ -0,0 +1,234 @@
|
||||
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();
|
||||
|
||||
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 testtiles = new Array();
|
||||
// testtiles.push({ x: 0, y: 0 });
|
||||
// testtiles.push({ x: 0, y: 1 });
|
||||
// testtiles.push({ x: 1, y: 0 });
|
||||
// testtiles.push({ x: 1, y: 1 });
|
||||
// testtiles.forEach(et => {
|
||||
// let etsize = tilesize;
|
||||
// if (zoom_level != Math.floor(zoom_level)) {
|
||||
// etsize = tilesize * Math.pow(2, zoom_level - Math.floor(zoom_level + 1));
|
||||
// }
|
||||
// const tilev = mplat2viewport(et.x * etsize, et.y * etsize);
|
||||
// drawRect(tilev.x, tilev.y, etsize, etsize);
|
||||
// });
|
||||
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);
|
||||
//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;
|
||||
});
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue