Initial work, enough to get the map to display

This commit is contained in:
James Lyne 2021-08-22 17:11:17 +01:00
parent 93f65a894e
commit ecc026cd34
3 changed files with 406 additions and 479 deletions

View file

@ -112,29 +112,148 @@ var DynmapLayerControl = L.Control.Layers.extend({
var DynmapTileLayer = L.TileLayer.extend({ var DynmapTileLayer = L.TileLayer.extend({
_currentzoom: undefined, _namedTiles: {},
_cachedTileUrls: {},
_loadQueue: [],
_loadingTiles: [],
getTileUrl: function(coords) {
var tileName = this.getTileName(coords),
url = this._cachedTileUrls[tileName];
if (!url) {
this._cachedTileUrls[tileName] = url = this.options.dynmap.getTileUrl(tileName);
}
return url;
},
createTile: function(coords, done) {
var me = this,
tile = document.createElement('img');
if (this.options.crossOrigin || this.options.crossOrigin === '') {
tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
}
tile.alt = '';
tile.setAttribute('role', 'presentation');
//Dynmap - Tile names
tile.tileName = this.getTileName(coords);
this._namedTiles[tile.tileName] = tile;
tile.onload = function() {
me._tileOnLoad(done, tile);
//Dynmap - Update load queue
me._loadingTiles.splice(me._loadingTiles.indexOf(tile), 1);
me._tickLoadQueue();
};
tile.onerror = function() {
me._tileOnError(done, tile);
//Dynmap - Update load queue
me._loadingTiles.splice(me._loadingTiles.indexOf(tile), 1);
me._tickLoadQueue();
};
//Dynmap - Queue for loading
tile.url = this.getTileUrl(coords);
this._loadQueue.push(tile);
this._tickLoadQueue();
return tile;
},
_abortLoading: function() {
var tile;
for (var i in this._tiles) {
if (!Object.prototype.hasOwnProperty.call(this._tiles, i)) {
continue;
}
tile = this._tiles[i];
//Dynmap - remove namedTiles entry
if (tile.coords.z !== this._tileZoom) {
if (tile.loaded && tile.el && tile.el.tileName) {
delete this._namedTiles[tile.el.tileName];
}
if(this._loadQueue.indexOf(tile.el) > -1) {
this._loadQueue.splice(this._loadQueue.indexOf(tile.el), 1);
}
if(this._loadingTiles.indexOf(tile.el) > -1) {
this._loadingTiles.splice(this._loadingTiles.indexOf(tile.el), 1);
}
}
}
L.TileLayer.prototype._abortLoading.call(this);
},
_removeTile: function(key) {
var tile = this._tiles[key];
if (!tile) {
return;
}
//Dynmap - remove namedTiles entry
var tileName = tile.el.tileName;
if (tileName) {
delete this._namedTiles[tileName];
}
//Dynmap - remove from load queue
if(this._loadingTiles.indexOf(tile.el) > -1) {
this._loadingTiles.splice(this._loadingTiles.indexOf(tile.el), 1);
}
if(this._loadQueue.indexOf(tile.el) > -1) {
this._loadQueue.splice(this._loadQueue.indexOf(tile.el), 1);
}
tile.el.onerror = null;
tile.el.onload = null;
L.TileLayer.prototype._removeTile.call(this, key);
},
getProjection: function() { getProjection: function() {
return this.projection; return this.projection;
}, },
_tickLoadQueue: function() {
if (this._loadingTiles.length > 4) {
return;
}
var next = this._loadQueue.shift();
if (!next) {
return;
}
this._loadingTiles.push(next);
next.src = next.url;
},
onTileUpdated: function(tile, tileName) { onTileUpdated: function(tile, tileName) {
var src = this.dynmap.getTileUrl(tileName); var src = this.dynmap.getTileUrl(tileName);
tile.attr('src', src); tile.attr('src', src);
tile.show(); tile.show();
}, },
getTileName: function(tilePoint, zoom) { getTileName: function(coords) {
throw "getTileName not implemented"; throw "getTileName not implemented";
}, },
getTileUrl: function(tilePoint, zoom) {
var tileName = this.getTileName(tilePoint, zoom);
var url = this._cachedTileUrls[tileName];
if (!url) {
this._cachedTileUrls[tileName] = url = this.options.dynmap.getTileUrl(tileName);
}
return url;
},
updateNamedTile: function(name) { updateNamedTile: function(name) {
var tile = this._namedTiles[name]; var tile = this._namedTiles[name];
delete this._cachedTileUrls[name]; delete this._cachedTileUrls[name];
@ -146,195 +265,22 @@ var DynmapTileLayer = L.TileLayer.extend({
updateTile: function(tile) { updateTile: function(tile) {
this._loadTile(tile, tile.tilePoint, this._map.getZoom()); this._loadTile(tile, tile.tilePoint, this._map.getZoom());
}, },
// Override to fix loads completing after layer removed
_addTilesFromCenterOut: function(bounds) {
if(this._container == null) // Ignore if we've stopped being active layer
return;
var queue = [],
center = bounds.getCenter();
for (var j = bounds.min.y; j <= bounds.max.y; j++) {
for (var i = bounds.min.x; i <= bounds.max.x; i++) {
if ((i + ':' + j) in this._tiles) { continue; }
queue.push(new L.Point(i, j));
}
}
// load tiles in order of their distance to center
queue.sort(function(a, b) {
return a.distanceTo(center) - b.distanceTo(center);
});
var fragment = document.createDocumentFragment();
this._tilesToLoad = queue.length;
for (var k = 0, len = this._tilesToLoad; k < len; k++) {
this._addTile(queue[k], fragment);
}
this._container.appendChild(fragment);
},
//Copy and mod of Leaflet method - marked changes with Dynmap: to simplify reintegration
_addTile: function(tilePoint, container) {
var tilePos = this._getTilePos(tilePoint),
zoom = this._map.getZoom(),
key = tilePoint.x + ':' + tilePoint.y,
name = this.getTileName(tilePoint, zoom), //Dynmap
tileLimit = (1 << zoom);
// wrap tile coordinates
if (!this.options.continuousWorld) {
if (!this.options.noWrap) {
tilePoint.x = ((tilePoint.x % tileLimit) + tileLimit) % tileLimit;
} else if (tilePoint.x < 0 || tilePoint.x >= tileLimit) {
this._tilesToLoad--;
return;
}
if (tilePoint.y < 0 || tilePoint.y >= tileLimit) {
this._tilesToLoad--;
return;
}
}
// create tile
var tile = this._createTile();
tile.tileName = name; //Dynmap
tile.tilePoint = tilePoint; //Dynmap
L.DomUtil.setPosition(tile, tilePos);
this._tiles[key] = tile;
this._namedTiles[name] = tile; //Dynmap
if (this.options.scheme == 'tms') {
tilePoint.y = tileLimit - tilePoint.y - 1;
}
this._loadTile(tile, tilePoint, zoom);
container.appendChild(tile);
},
_loadTile: function(tile, tilePoint, zoom) {
var me = this;
tile._layer = this;
function done() {
me._loadingTiles.splice(me._loadingTiles.indexOf(tile), 1);
me._nextLoadTile();
}
tile.onload = function(e) {
me._tileOnLoad.apply(this, [e]);
done();
}
tile.onerror = function() {
me._tileOnError.apply(this);
done();
}
tile.loadSrc = function() {
me._loadingTiles.push(tile);
tile.src = me.getTileUrl(tilePoint, zoom);
};
this._loadQueue.push(tile);
this._nextLoadTile();
},
_nextLoadTile: function() {
if (this._loadingTiles.length > 4) { return; }
var next = this._loadQueue.shift();
if (!next) { return; }
next.loadSrc();
},
_removeOtherTiles: function(bounds) {
var kArr, x, y, key;
for (key in this._tiles) {
if (this._tiles.hasOwnProperty(key)) {
kArr = key.split(':');
x = parseInt(kArr[0], 10);
y = parseInt(kArr[1], 10);
// remove tile if it's out of bounds
if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
var tile = this._tiles[key];
if (tile.parentNode === this._container) {
this._container.removeChild(this._tiles[key]);
}
delete this._namedTiles[tile.tileName];
delete this._tiles[key];
}
}
}
},
_updateTileSize: function() {
var newzoom = this._map.getZoom();
if (this._currentzoom !== newzoom) {
var newTileSize = this.calculateTileSize(newzoom);
this._currentzoom = newzoom;
if (newTileSize !== this.options.tileSize) {
this.setTileSize(newTileSize);
}
}
},
_reset: function() {
this._updateTileSize();
this._tiles = {};
this._namedTiles = {};
this._loadQueue = [];
this._loadingTiles = [];
this._cachedTileUrls = {};
this._initContainer();
this._container.innerHTML = '';
},
_update: function() {
this._updateTileSize();
var bounds = this._map.getPixelBounds(),
tileSize = this.options.tileSize;
var nwTilePoint = new L.Point(
Math.floor(bounds.min.x / tileSize),
Math.floor(bounds.min.y / tileSize)),
seTilePoint = new L.Point(
Math.floor(bounds.max.x / tileSize),
Math.floor(bounds.max.y / tileSize)),
tileBounds = new L.Bounds(nwTilePoint, seTilePoint);
this._addTilesFromCenterOut(tileBounds);
if (this.options.unloadInvisibleTiles) {
this._removeOtherTiles(tileBounds);
}
},
/*calculateTileSize: function(zoom) {
return this.options.tileSize;
},*/
calculateTileSize: function(zoom) {
// zoomoutlevel: 0 when izoom > mapzoomin, else mapzoomin - izoom (which ranges from 0 till mapzoomin)
var izoom = this.options.maxZoom - zoom;
var zoominlevel = Math.max(0, this.options.mapzoomin - izoom);
return 128 << zoominlevel;
},
setTileSize: function(tileSize) {
this.options.tileSize = tileSize;
this._tiles = {};
this._createTileProto();
},
updateTileSize: function(zoom) {},
// Some helper functions. // Some helper functions.
zoomprefix: function(amount) { zoomprefix: function(amount) {
return 'zzzzzzzzzzzzzzzzzzzzzz'.substr(0, amount); return 'zzzzzzzzzzzzzzzzzzzzzz'.substr(0, amount);
}, },
getTileInfo: function(tilePoint, zoom) {
getTileInfo: function(coords) {
// zoom: max zoomed in = this.options.maxZoom, max zoomed out = 0 // zoom: max zoomed in = this.options.maxZoom, max zoomed out = 0
// izoom: max zoomed in = 0, max zoomed out = this.options.maxZoom // izoom: max zoomed in = 0, max zoomed out = this.options.maxZoom
// zoomoutlevel: izoom < mapzoomin -> 0, else -> izoom - mapzoomin (which ranges from 0 till mapzoomout) // zoomoutlevel: izoom < mapzoomin -> 0, else -> izoom - mapzoomin (which ranges from 0 till mapzoomout)
var izoom = this.options.maxZoom - zoom; var izoom = this._getZoomForUrl(),
var zoomoutlevel = Math.max(0, izoom - this.options.mapzoomin); zoomoutlevel = Math.max(0, izoom - this.options.mapzoomin),
var scale = 1 << zoomoutlevel; scale = 1 << zoomoutlevel,
var x = scale*tilePoint.x; x = scale * coords.x,
var y = scale*tilePoint.y; y = scale * coords.y;
return { return {
prefix: this.options.prefix, prefix: this.options.prefix,
nightday: (this.options.nightandday && this.options.dynmap.serverday) ? '_day' : '', nightday: (this.options.nightandday && this.options.dynmap.serverday) ? '_day' : '',

View file

@ -23,17 +23,20 @@ var HDMapType = DynmapTileLayer.extend({
projection: undefined, projection: undefined,
options: { options: {
minZoom: 0, minZoom: 0,
maxZoom: 0,
errorTileUrl: 'images/blank.png', errorTileUrl: 'images/blank.png',
continuousWorld: true tileSize: 128,
zoomReverse: true,
}, },
initialize: function(options) { initialize: function(options) {
options.maxZoom = options.mapzoomin + options.mapzoomout; options.maxZoom = options.mapzoomin + options.mapzoomout;
L.Util.setOptions(this, options); options.maxNativeZoom = options.mapzoomout;
this.projection = new HDProjection($.extend({map: this}, options)); this.projection = new HDProjection($.extend({map: this}, options));
L.Util.setOptions(this, options);
}, },
getTileName: function(tilePoint, zoom) { getTileName: function(coords) {
var info = this.getTileInfo(tilePoint, zoom); var info = this.getTileInfo(coords);
// Y is inverted for HD-map. // Y is inverted for HD-map.
info.y = -info.y; info.y = -info.y;
info.scaledy = info.y >> 5; info.scaledy = info.y >> 5;

View file

@ -177,34 +177,12 @@ DynMap.prototype = {
zoomAnimation: true, zoomAnimation: true,
zoomControl: !me.nogui, zoomControl: !me.nogui,
attributionControl: false, attributionControl: false,
crs: L.extend({}, L.CRS, { crs: L.CRS.Simple,
code: 'simple',
projection: {
project: function(latlng) {
// Direct translation of lat -> x, lng -> y.
return new L.Point(latlng.lat, latlng.lng);
},
unproject: function(point) {
// Direct translation of x -> lat, y -> lng.
return new L.LatLng(point.x, point.y);
}
},
// a = 1; b = 2; c = 1; d = 0
// x = a * x + b; y = c * y + d
// End result is 1:1 values during transformation.
transformation: new L.Transformation(1, 0, 1, 0),
scale: function(zoom) {
// Equivalent to 2 raised to the power of zoom, but faster.
return (1 << zoom);
}
}),
continuousWorld: true,
worldCopyJump: false worldCopyJump: false
}); });
window.map = map; // Placate Leaflet need for top-level 'map'.... window.map = map; // Placate Leaflet need for top-level 'map'....
map.on('zoomend', function() { map.on('zoomend', function() {
me.maptype.updateTileSize(me.map.getZoom());
$(me).trigger('zoomchanged'); $(me).trigger('zoomchanged');
}); });
@ -754,7 +732,7 @@ DynMap.prototype = {
} }
); );
}, },
getTileUrl: function(tileName, always) { getTileUrl: function(tileName) {
var me = this; var me = this;
var tile = me.registeredTiles[tileName]; var tile = me.registeredTiles[tileName];