I am trying to create a map for a web-based game with Openlayers. The game will have three zoom levels with different details. I made one using leaflet but it has a known issue. Now I am trying Opnelayers but I am running into multiple problems.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom Canvas Tiles</title>
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
*, body {
margin: unset;
}
.map {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/[email protected]/dist/elm-pep.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>
main.js
import Map from 'ol/Map';
import TileLayer from 'ol/layer/Tile';
import ImageLayer from 'ol/layer/image'
import Static from 'ol/source/ImageStatic';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ';
import Projection from 'ol/proj/Projection';
import { getCenter } from 'ol/extent';
const extentLayer = [0, 0, 1400, 800];
const extentView = [-28000000, -16000000, 28000000, 24000000];
const projectionView = new Projection({
code: 'pixel-map',
units: 'pixels',
extent: extentView,
});
const tileLayer = new TileLayer({
source: new XYZ({
url: '/tiles/{z}/{x}/{y}.png',
wrapX: false,
tileSize: [280, 400],
zoom: 0,
minZoom: 2,
maxZoom: 4,
}),
extentLayer,
});
const view = new View({
projectionView,
center: getCenter(extentView),
zoom: 0,
minZoom: 2,
maxZoom: 4,
extent: extentView
});
const map = new Map({
target: 'map',
layers: [
tileLayer,
],
view
});
For some reason, default zoom level starts with 2 even After setting it to 0. I confirmed it by looking at browser network requests. Another problem is that there is a small third zoom.
My base image is [1400, 800]. I have divided it into 10 tiles(5x2). On each next zoom level a tile is divided into four more detailed tiles (all tiles at any zoom level are [280, 400]). The last two tiles [4, 0] and [4, 1] are not requested by the map. Instead, it tries to load a third row of tiles which I don't even have. I think it must be an issue with the view extent.
I have read the docs multiple times but I am unable to resolve these issues. I tried to follow some examples (there aren't many) to make the view extent the same as the image but it did not work and I ended up with the big values and only they showed the tiles.
You need to specify the projection for the source
, and the same extent should be used for tile grid and projection
const extent = [0, 0, 1400, 800];
const projection = new Projection({
code: 'pixel-map',
units: 'pixels',
extent,
});
const tileLayer = new TileLayer({
source: new XYZ({
url: '/tiles/{z}/{x}/{y}.png',
tileSize: [280, 400],
projection,
maxZoom: 2,
maxResolution: 1,
}),
});
const view = new View({
projection,
center: getCenter(extent),
zoom: 0,
});
const map = new Map({
target: 'map',
layers: [
tileLayer,
],
view
});