OpenLayers-如果从文件系统或Web服务器上查看,地图比例会有所不同
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenLayers-如果从文件系统或Web服务器上查看,地图比例会有所不同相关的知识,希望对你有一定的参考价值。
我正在尝试将VectorLayer
添加到现有的TileLayer
,所以我可以将ol.geom.Point
标记为感兴趣的地方。
最初这是我想要的工作方式-兴趣点准确地在TileLayer
上绘制了它们的位置。
从那时起,我已经生成了更多的图块,但是我没有更改OpenLayers代码。在地图上应该只有更少的黑色空间,但是现在地图看起来似乎要加载缩小的地图,而我的点仍然绘制在同一位置。
OpenLayers缩放级别不成问题-它仍然始终加载缩小,并且在两种情况下,我都可以放大8倍。每种场景的缩放级别都使用相同的图块图像,但是由于我的地图总体上变大了,所以这些图块显得更小。
您能帮我弄清楚如何解决刻度差异吗?
这里是正确绘制时的外观。您可以看到Player ####
标记在地图的范围内-黑色区域都没有。
[here是我的托管副本
点的坐标是相同的,您可以在屏幕上看到这些点彼此之间的绝对距离相同,但是它们是从地图上的黑色区域绘制的,这与图块的比例有所不同或
[Here's OpenLayers代码
<script>
var layers =
dim0:
name: "Overworld",
attribution:
'<a href="https://github.com/mjungnickel18/papyruscs">PapyrusCS</a>',
minNativeZoom: 15,
minZoom: 15,
maxNativeZoom: 20,
maxZoom: 22,
noWrap: true,
tileSize: 512,
folder: "dim0",
fileExtension: "png"
;
var config =
factor: 1
;
layers = "dim0":"name":"Overworld","attribution":"Generated by <a href=\"https://github.com/mjungnickel18/papyruscs\">PapyrusCS</a>","minNativeZoom":12,"maxNativeZoom":20,"noWrap":true,"tileSize":512,"folder":"dim0","fileExtension":"png";
config = "factor":65536.0,"globalMinZoom":12,"globalMaxZoom":20,"tileSize":512,"blocksPerTile":32;
// ======
// For the extent sizes specified below, OpenLayers tries to fit
// the whole extents given in a space [0, 0] -> [2^8, 2^8] visually
// on screen at zoom level 0.
//
// This constant represents that internal tile size that OpenLayers
// will aim for, so that we can calculate zoom levels correctly later.
const openLayersInternalTileSize = Math.pow(2, 8); // 256
// The actual size of the tiles that we're using in Papyrus.
const tileSize = config.tileSize;
// The maximum positive extents of the whole map. The units for this
// value are "number of tiles at the most zoomed out level generated
// by Papyrus". That is, if Papyrus generates a minimum zoom level
// of 15, then the units for this extent size are the number of (Papyrus)
// zoom level 15 tiles to display at (OpenLayers) zoom level 0.
//
// The minimum zoom level that Papyrus is using is in config.globalMinZoom.
const maximumExtentSize = 10000;
// The minimum negative extents of the whole map. Uses the same units
// as maximumExtentSize.
const minimumExtentSize = -10000;
// Computes the resolutions array to use for OpenLayers. For each OpenLayers
// zoom level (0 through 42), this computes the ratio such that a single tile
// at OpenLayers zoom level 0 is a single tile at the minimum Papyrus zoom level.
const papyrusMinimumZoomScale = Math.pow(2, config.globalMinZoom);
const convertedFromTilesToPixelsUsingTileSize = papyrusMinimumZoomScale / tileSize;
const resolutions = new Array(43);
for (let z = 0; z < 43; ++z)
resolutions[z] = convertedFromTilesToPixelsUsingTileSize / Math.pow(2, z);
// When we calculate resolutions above, we've effectively saying that zoom level 0 is
// zoom level N, where N is the lowest zoom level. This zoom level N also becomes
// the range of [0, 0] -> [1, 1] in the coordinate system. We need to be able to translate
// coordinates in that "zoomed out" coordinate system, back down to the maximum zoom level
// where each tile represents 32x32 (depending on tilesize) Minecraft tiles.
const zoomRatioForMaximumZoom = 1 / Math.pow(2, config.globalMaxZoom - config.globalMinZoom);
const minecraftTilesAtMostZoomedInLevel = config.blocksPerTile;
// Use a projection where pixels have a 1:1 ratio with the screen at zoom level 0.
const projection = new ol.proj.Projection(
code: "ZOOMIFY",
units: "pixels",
extent: [
0,
0,
openLayersInternalTileSize / tileSize,
openLayersInternalTileSize / tileSize
]
);
// Construct the tile grid using the desired maximum and minimum extents listed above,
// set the origin to [0, 0] (the center of the map), and the calculated resolutions array.
const tilegrid = new ol.tilegrid.TileGrid(
extent: [
minimumExtentSize,
minimumExtentSize,
maximumExtentSize,
maximumExtentSize
],
origin: [0, 0],
resolutions: resolutions,
tileSize: [tileSize, tileSize]
);
let map;
let locationElement;
const tileLayers = Object.keys(layers)
.sort()
.map(function(layerKey, idx)
const layer = layers[layerKey];
const tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
tileUrlFunction: function(tileCoord, pixelRatio, projection)
const z = tileCoord[0];
const x = tileCoord[1];
const y = tileCoord[2];
return (
"./" +
layer.folder +
"/" +
z +
"/" +
x +
"/" +
y +
"." +
layer.fileExtension
);
,
projection: projection,
tileGrid: tilegrid,
attributions: layer.attribution
),
visible: idx == 0
);
tileLayer.metaLayerKey = layerKey;
return tileLayer;
);
const initialLayer = layers[Object.keys(layers).sort()[0]];
if (Object.keys(layers).sort()[0] == "dim0_stronghold")
document.getElementById("map").style.background = "#fff";
else
document.getElementById("map").style.background = "#202020";
const view = new ol.View(
projection: projection,
center: [0, 0],
zoom: 0,
minZoom: 0,
maxZoom: config.globalMaxZoom - config.globalMinZoom
);
const PapyrusControls = (function(Control)
function PapyrusControls(opt_options)
const options = opt_options || ;
const element = document.createElement("div");
element.className = "layer-select ol-unselectable";
const card = document.createElement("div");
card.className = "card";
element.appendChild(card);
const cardBody = document.createElement("div");
cardBody.className = "card-body p-3 px-3";
card.appendChild(cardBody);
const form = document.createElement("form");
cardBody.appendChild(form);
let currentSelectedLayer = Object.keys(layers).sort()[0];
let rememberedCenters = ;
let rememberedZoom = ;
Object.keys(layers)
.sort()
.forEach(function(layerKey, idx)
const layer = layers[layerKey];
const radioContainer = document.createElement("div");
radioContainer.className = "custom-control custom-radio";
const radioInput = document.createElement("input");
radioInput.type = "radio";
radioInput.id = layerKey;
radioInput.name = "layers";
radioInput.className = "custom-control-input";
radioInput.checked = idx == 0;
radioInput.value = layerKey;
radioContainer.appendChild(radioInput);
const radioLabel = document.createElement("label");
radioLabel.htmlFor = layerKey;
radioLabel.className = "custom-control-label";
radioLabel.innerText = layer.name;
radioContainer.appendChild(radioLabel);
const selectLayer = function(e)
if (layerKey == "dim0_stronghold")
document.getElementById("map").style.background = "#fff";
else
document.getElementById("map").style.background = "#202020";
if (currentSelectedLayer != layerKey)
const runtimeLayers = map.getLayers();
runtimeLayers.forEach(function(runtimeLayer)
runtimeLayer.setVisible(
runtimeLayer.metaLayerKey == layerKey
);
);
const oldFocusGroup = currentSelectedLayer.substr(0, 4);
const newFocusGroup = layerKey.substr(0, 4);
rememberedCenters[oldFocusGroup] = view.getCenter();
if (rememberedCenters[newFocusGroup] === undefined)
// refocus the map to 0, 0
view.setCenter([0, 0]);
else
// set back to where we were
view.setCenter(rememberedCenters[newFocusGroup]);
rememberedZoom[oldFocusGroup] = view.getZoom();
view.setMinZoom(layer.minNativeZoom - config.globalMinZoom);
view.setMaxZoom(layer.maxNativeZoom - config.globalMinZoom);
if (rememberedZoom[newFocusGroup] === undefined)
// rezoom the map to minimum zoom
view.setZoom(layer.minNativeZoom - config.globalMinZoom);
else
// set back to where we were
view.setZoom(rememberedZoom[newFocusGroup]);
const radios = $("input[name='layers']");
radios.each(function(idx, elem)
if (elem.value == layerKey)
elem.checked = true;
else
elem.checked = false;
);
currentSelectedLayer = layerKey;
;
radioInput.addEventListener(
"click",
selectLayer.bind(this),
false
);
form.appendChild(radioContainer);
);
const hr = document.createElement("hr");
form.appendChild(hr);
locationElement = document.createElement("div");
locationElement.innerText = "X: 0, Z: 0";
form.appendChild(locationElement);
Control.call(this,
element: element,
target: options.target
);
if (Control) PapyrusControls.__proto__ = Control;
PapyrusControls.prototype = Object.create(Control && Control.prototype);
PapyrusControls.prototype.constructor = PapyrusControls;
return PapyrusControls;
)(ol.control.Control);
map = new ol.Map(
target: "map",
layers: tileLayers,
view: view,
controls: [
new ol.control.Zoom(),
new ol.control.Attribution(),
new PapyrusControls()
]
);
map.on("pointermove", function(event)
var x = Math.floor(
(event.coordinate[0] / zoomRatioForMaximumZoom) *
minecraftTilesAtMostZoomedInLevel
);
var z = Math.floor(
(-event.coordinate[1] / zoomRatioForMaximumZoom) *
minecraftTilesAtMostZoomedInLevel
);
locationElement.innerText = "X: " + x + " Z: " + z;
);
if (typeof(playersData) !== "undefined")
var playerFeatures = [];
for (var playerIndex in playersData.players)
var player = playersData.players[playerIndex];
if (!player.visible)
continue;
if (player.dimensionId !== 0)
// TODO: Currently I'm only adding player markers who are in the Overworld
// We'll want to show players depending on which dimension is being viewed
// Maybe add a separate layer for players in each dimension
continue;
var style = new ol.style.Style(
text: new ol.style.Text(
text: player.name + "\n\uf041", // map-marker
font: "900 18px 'Font Awesome 5 Free'",
textBaseline: "bottom",
fill: new ol.style.Fill(color: player.color),
stroke: new ol.style.Stroke(color: "white", width: 2)
)
);
var playerFeature = new ol.Feature(
geometry: new ol.geom.Point([
(player.position[0] * zoomRatioForMaximumZoom) / minecraftTilesAtMostZoomedInLevel,
(-player.position[2] * zoomRatioForMaximumZoom) / minecraftTilesAtMostZoomedInLevel
])
);
playerFeature.setStyle(style);
playerFeatures.push(playerFeature);
var vectorSource = new ol.source.Vector(
features: playerFeatures
);
var vectorLayer = new ol.layer.Vector(
source: vectorSource
);
map.addLayer(vectorLayer);
</script>
好吧,这不是设备问题,这只是我的傻瓜。问题来自我不知道的默认配置。
在我的示例中,如果我将ol.geom.Point
中的X和Y值除以2,则得到了所需的内容。我会自行解决其余问题。
感谢@Mike帮助我朝正确的方向看
以上是关于OpenLayers-如果从文件系统或Web服务器上查看,地图比例会有所不同的主要内容,如果未能解决你的问题,请参考以下文章
如何从 openlayers 读取外部 GeoJSON 文件?
搭建简易Web GIS网站:使用GeoServer+PostgreSQL+PostGIS+OpenLayers3