ol
Version:
OpenLayers mapping library
134 lines (121 loc) • 4.6 kB
JavaScript
/**
* @module ol/source/TileDebug
*/
import {createCanvasContext2D} from '../dom.js';
import EventType from '../events/EventType.js';
import {get as getProjection} from '../proj.js';
import {toSize} from '../size.js';
import {renderXYZTemplate} from '../uri.js';
import DataTile from './DataTile.js';
import ImageTile from './ImageTile.js';
/**
* @typedef {Object} Options
* @property {import("../proj.js").ProjectionLike} [projection='EPSG:3857'] Optional projection.
* @property {import("../tilegrid/TileGrid.js").default} [tileGrid] Tile grid.
* @property {boolean} [wrapX=true] Whether to wrap the world horizontally.
* @property {number|import("../array.js").NearestDirectionFunction} [zDirection=0]
* Set to `1` when debugging `VectorTile` sources with a default configuration.
* Choose whether to use tiles with a higher or lower zoom level when between integer
* zoom levels. See {@link module:ol/tilegrid/TileGrid~TileGrid#getZForResolution}.
* @property {import("./Tile.js").default} [source] Tile source.
* This allows `projection`, `tileGrid`, `wrapX` and `zDirection` to be copied from another source.
* If both `source` and individual options are specified the individual options will have precedence.
* @property {string} [template='z:{z} x:{x} y:{y}'] Template for labeling the tiles.
* Should include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.
* @property {string} [color='grey'] CSS color to fill text and stroke grid lines of each tile.
*/
/**
* @classdesc
* A pseudo tile source, which does not fetch tiles from a server, but renders
* a grid outline for the tile grid/projection along with the coordinates for
* each tile. See examples/canvas-tiles for an example.
* @api
*/
class TileDebug extends ImageTile {
/**
* @param {Options} [options] Debug tile options.
*/
constructor(options) {
/**
* @type {Options}
*/
options = options || {};
const template = options.template || 'z:{z} x:{x} y:{y}';
const source = options.source;
const color = options.color || 'grey';
super({
transition: 0,
wrapX:
options.wrapX !== undefined
? options.wrapX
: source !== undefined
? source.getWrapX()
: undefined,
});
const setReady = () => {
this.projection =
options.projection !== undefined
? getProjection(options.projection)
: source !== undefined
? source.getProjection()
: this.projection;
this.tileGrid =
options.tileGrid !== undefined
? options.tileGrid
: source !== undefined
? source.getTileGrid()
: this.tileGrid;
this.zDirection =
options.zDirection !== undefined
? options.zDirection
: source !== undefined
? source.zDirection
: this.zDirection;
if (source instanceof DataTile) {
this.transformMatrix = source.transformMatrix?.slice() || null;
}
const tileGrid = this.tileGrid;
if (tileGrid) {
this.setTileSizes(
tileGrid
.getResolutions()
.map((r, i) =>
toSize(tileGrid.getTileSize(i)).map((s) =>
Math.max(Math.floor(s), 1),
),
),
);
}
this.setLoader((z, x, y, loaderOptions) => {
const text = renderXYZTemplate(template, z, x, y, loaderOptions.maxY);
const [width, height] = this.getTileSize(z);
const context = createCanvasContext2D(width, height);
context.strokeStyle = color;
context.strokeRect(0.5, 0.5, width + 0.5, height + 0.5);
context.fillStyle = color;
context.strokeStyle = 'white';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.font = '24px sans-serif';
context.lineWidth = 4;
context.strokeText(text, width / 2, height / 2, width);
context.fillText(text, width / 2, height / 2, width);
// make the loader aysnc, so it behaves like other sources that fetch data from a remote server
return Promise.resolve(context.canvas);
});
this.setState('ready');
};
if (source === undefined || source.getState() === 'ready') {
setReady();
} else {
const handler = () => {
if (source.getState() === 'ready') {
source.removeEventListener(EventType.CHANGE, handler);
setReady();
}
};
source.addEventListener(EventType.CHANGE, handler);
}
}
}
export default TileDebug;