Question

I want to make a offline map app in html. I'm using Openlayers 3

I can save tiles from Openstreetmap, thats not the problem.

My question:

When I have a square like: LonLat1, LonLat2

1------

-------2

How I can calculate which tiles I have to grab, on multiple zoomlevels

Caching all: '{z}/{x}/{y}.png' tiles

Later I use them offline with like this

var map = new ol.Map({
    target: 'map',
    layers: [new ol.layer.Tile({
            source: new ol.source.XYZ({
            url: '{z}/{x}/{y}.png'
        })
    })], ...
Was it helpful?

Solution

I solved the problem Tnx to John Barca's link!

Made a fiddle:

Fiddle

Fiddle Full Screen

includes ol3.js / ol3.css / jquery

html:

javascript:

var map;
var icons = [];
var selMarker;
var click = 0;
var tmpCoord;

map = new ol.Map({
    layers: [
    new ol.layer.Tile({source: new ol.source.OSM()}),
    new ol.layer.Vector({      
        source: new ol.source.Vector({features:icons})
    })],
    renderer: "canvas",
    target: 'map',
    view: new ol.View2D({
        zoom: 11
    })
});

map.getView().setCenter(transform(5, 52));

map.on("click", function(evt){
    var coordinate = evt.coordinate;
    if(click == 0) {
        tmpCoord = coordinate;
        click++;
    } else {
        addVierkant(tmpCoord, coordinate);
        click = 0;
        getAllTiles(tmpCoord, coordinate);
    }   
    addCircle(coordinate);
})

function transform(lng, lat) {
    return ol.proj.transform([lng, lat], 'EPSG:4326', 'EPSG:3857');
}

function transform2(lng, lat) {
    return ol.proj.transform([lng, lat], 'EPSG:3857', 'EPSG:4326');
}

function addCircle(c) {
    var source = map.getLayers().getAt(1).getSource();
    var iconFeature = new ol.Feature({
      geometry: new ol.geom.Circle(c, 300),
    });
    iconFeature.setStyle(getCircleStyle());
    icons[icons.length] = iconFeature;
    icons[icons.length - 1][0] = "circle";
    source.addFeature(iconFeature);
    return iconFeature;
}

function addVierkant(c1, c2) {
    var source = map.getLayers().getAt(1).getSource();
    p1 = c1;
    p2 = [c1[0], c2[1]];
    p3 = c2;
    p4 = [c2[0], c1[1]];
    var coords = [p1,p2,p3,p4,p1];
    var iconFeature = new ol.Feature({
      geometry: new ol.geom.LineString(coords),
    });
    iconFeature.setStyle(getVierkantStyle());
    icons[icons.length] = iconFeature;
    icons[icons.length - 1][0] = "vierkant";
    source.addFeature(iconFeature);
    return iconFeature;
}

function getCircleStyle() {
  var iconStyle = new ol.style.Style({
      stroke: new ol.style.Stroke({
          color: 'rgba(0,0,0,0.3)',
          width: 4
      }),
      fill: new ol.style.Fill({
          color: 'rgba(255,255,255,0.9)'
      })
    });
    return iconStyle;
}

function getVierkantStyle() {
  var iconStyle = new ol.style.Style({
      stroke: new ol.style.Stroke({
          color: 'rgba(255,255,255,0.9)',
          width: 2
      })
    });
    return iconStyle;
}

function getAllTiles(coord1, coord2) {
    out1 = getTileURL(coord1, 10);
    out2 = getTileURL(coord2, 10);

    $("#output").html("zoom ------ " + out1[0] + "<br>from " + out1[1] + " to " + out2[1] + "<br>from " + out1[2] + " to " + out2[2]);

}


function getTileURL(coord, zoom) {
        cor = transform2(coord[0], coord[1]);
        lon = cor[0];
        lat = cor[1];
        var out = [];
        var xtile = parseInt(Math.floor( (lon + 180) / 360 * (1<<zoom) ));
        var ytile = parseInt(Math.floor( (1 - Math.log(Math.tan(lat.toRad()) + 1 / Math.cos(lat.toRad())) / Math.PI) / 2 * (1<<zoom) ));
        log(">> " + zoom + "/" + xtile + "/" + ytile);
        out[0] = zoom;
        out[1] = xtile;
        out[2] = ytile;
        return out;
}


function log(text) {
    console.log(text);
}

if (typeof(Number.prototype.toRad) === "undefined") {
  Number.prototype.toRad = function() {
    return this * Math.PI / 180;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top