In my application based in Java on the front end and using WildFly Keycloack on the backend, we are displying a PTV Vector map in one of the application views using the following libraries:
The issue is that the small label for street names is not displayed correctly. It looks as if the center/position it has for street names is different to the rest of elements in the map since they are displayed correctly.
For instance, the following image shows two examples of text labels, one being displayed as expected and the issue for which this thread has been created. Map text labels
As per my observations, the following block of code in our standard.json file will display both text labels mentioned above.
{
"id": "TSP_RoadLocal_Label",
"type": "symbol",
"source": "ptv",
"source-layer": "LayerTransport",
"minzoom": 13,
"filter": [
"all",
[
"==",
"$type",
"LineString"
],
[
"==",
"display_class",
5
]
],
"layout": {
"icon-rotation-alignment": "auto",
"symbol-placement": "line",
"text-font": [
"Noto Sans Regular"
],
"text-size": {
"stops": [
[
10,
8
],
[
20,
14
]
]
},
"text-letter-spacing": 0.1,
"text-field": "{street_name}"
},
"paint": {
"text-color": "#1B1C1F",
"text-opacity": {
"stops": [
[
13,
0
],
[
14,
1
]
]
},
"text-halo-color": "hsl(0, 0%, 100%)",
"text-halo-width": 2
}
}
What I would like to know is why some text labels are not displayed correctly and some others are displayed as expected.
Following is the HTML code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" charset='utf-8' />
<meta name="viewport"
content="width= 100, initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html {
height: 100%
}
body {
height: 100%;
margin: 0;
padding: 0
}
#map_canvas {
position:absolute; top:0; bottom:0; width:100%;
height: 100%
}
</style>
<script src="libraries/ol.js"></script>
<script src="libraries/olms.js"></script>
<script src="libraries/require.js"></script>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="map_canvas" style="height: 100%; width: 100%"></div>
<script>
var fromProjection;
var toProjection;
var zoom;
var apiUrl = 'https://api.myptv.com/maps/v1/vector-tiles/{z}/{x}/{y}?apiKey=';
var apiKey;
var urlTemplate = apiUrl + apiKey;
var jsonStyle;
var map;
function setApiKey(api) {
apiKey = api;
urlTemplate = apiUrl + apiKey;
}
function init() {
try {
if (map != null) {
return;
}
map = new ol.Map({
target: 'map_canvas',
view: new ol.View({ center: ol.proj.transform([8.7528, 50.377], 'EPSG:4326', 'EPSG:3857'), zoom: 18}),
controls:[]
});
const layer = new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
url:
urlTemplate,
maxZoom: 18,
}),
});
fetch('./libraries/standard.json')
.then((response) => response.json())
.then((json) => layer.setStyle(olms.stylefunction(layer,json, 'ptv')));
map.addLayer(layer);
} catch (e) {
console.log(e);
}
}
function getMap() {
init();
return map;
}
function getZoom() {
return zoom;
}
function setZoom(zoomLvl) {
zoom = zoomLvl;
getMap().getView().setZoom(zoom);
}
function getCenterLat() {
return ol.proj.transform(getMap().getView().getCenter(), 'EPSG:3857', 'EPSG:4326')[1];
}
function getCenterLng() {
return ol.proj.transform(getMap().getView().getCenter(), 'EPSG:3857', 'EPSG:4326')[0];
}
function setCenter(lat, lng) {
try {
getMap().getView().setCenter(ol.proj.transform([lng, lat], 'EPSG:4326', 'EPSG:3857'));
} catch (e) {
console.log(e)
}
}
</script>
</body>
</html>
Lastly, this is the renderer Java class:
import java.net.URL;
import java.util.Vector;
import javafx.application.Platform;
public class PTVDevVectorMapRenderer extends AbstractHtmlInteractiveMapRenderer {
private static final long serialVersionUID = 1L;
public String apiKey = KonstantenCache.getWertGCW("PTV_DEVELOPER", "PTV_API_KEY");
public PTVDevVectorMapRenderer() {
super();
initializeMap();
}
/**
* Initialize PTV Map
*/
public void initializeMap() {
final URL urlPTVMaps = getClass().getResource("PTVDevVectorMap.html");
htmlRenderer.setContent(urlPTVMaps.toExternalForm());
// Blocking call. Waits until WebEngine is loaded
refresh();
Platform.runLater(new Runnable() {
@Override
public void run() {
setApiKey();
String scriptInit = "init()";
htmlRenderer.execute(scriptInit);
}});
}
public void setApiKey() {
String apiKey = KonstantenCache.getWertGCW("PTV_DEVELOPER", "PTV_API_KEY");
String scriptApiKey = "setApiKey('" + apiKey + "')";
//String.format("setApiKey('%s')", apiKey);
htmlRenderer.execute(scriptApiKey);
}
@Override
public void setCenter(
double lat,
double lng) {
String scriptCenter = "setCenter(" + lat + "," + lng + ")";
htmlRenderer.execute(scriptCenter);
}
@Override
public double getCenterLat() {
double centerLat = (double) htmlRenderer.executeAndReturn("getCenterLat()");
return centerLat;
}
@Override
public double getCenterLng() {
double centerLng = (double) htmlRenderer.executeAndReturn("getCenterLng()");
return centerLng;
}
@Override
public int getZoom() {
Object obj = htmlRenderer.executeAndReturn("getZoom()");
if (obj instanceof String) {
// String is "undefined", thus the map is not completely loaded yet.
return 13;
}
return (int) obj;
}
@Override
public void setZoom(
int zoom) {
String script = "setZoom(" + zoom + ")";
htmlRenderer.execute(script);
}
@Override
public int getMaxZoomLvl() {
return 19;
}
@Override
public int getMinZoomLvl() {
return 3;
}
@Override
public double getDistance(
double[] objectPoint,
double[] objectPoint2) {
String script = "calcDistance(" + objectPoint[0] + "," + objectPoint[1] + "," + objectPoint2[0] + ","
+ objectPoint2[1] + ")";
double distance = (double) htmlRenderer.executeAndReturn(script);
return distance;
}
@Override
public void setRoute(
double[] objectPoint,
double[] objectPoint2) {
}
@Override
public Vector<?> getRoutePoints(
double[] objectPoint,
double[] objectPoint2) {
return null;
}
@Override
public Vector<double[]> getFahrtgebiet() {
return null;
}
@Override
public double[] getFahrtgebietPoint() {
return null;
}
}
Thanks a lot for your time and help!
here's some working example of the open layers driven Vector Map. Enter your API key and go for it...
<html lang="en">
<head>
<title>PTV Vector Map OpenLayers Tutorial</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.2.2/ol.css">
<link rel="icon" href="../../favicon.ico" />
<style>
body { margin:5px; padding:5px; }
#map { width:100%; height:100%; }
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src="https://unpkg.com/ol@7.2.2/dist/ol.js"></script>
<script type="text/javascript" src="https://unpkg.com/ol-mapbox-style@10.5.0/dist/olms.js"></script>
<script type="text/javascript">
const apiKey = '';
const map = new ol.Map({
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([8.4, 49]),
zoom: 13
})
});
olms.apply(map, `https://vectormaps-resources.myptv.com/styles/latest/standard.json`, {
transformRequest(url, type) {
if (type === 'Tiles') {
return new Request(
url + "?apiKey=" + apiKey
);
}
}
}).then((map) => {
// you will get ol.Map instance here
});
</script>
</body>
</html>