我最近一直在使用Leaflet显示栅格图像。
我想为特定项目做的是能够放大图像,以使像素以清晰的方式在屏幕上放大,例如在Photoshop或喜欢。我还想在最大缩放比例之前将图像像素与屏幕像素之间保持1:1对应。
我尝试按照here和here的描述超越maxNativeZoom,但可以,但是插值会导致像素模糊。
我想到了一种替代方法,即使用“最近邻点”内插法将每个像素扩展到更大的正方形,从而使源图像更大:当放大到maxNativeZoom时,正方形看起来像被急剧放大的像素,即使不是。
问题是:
我曾考虑过使用两个图块集:第一个从原始图像到最大maxNativeZoom,然后是更大的“最近邻”插值图像,其后跟随this。
但是,这更加复杂,无法避免大图块数的问题,并且看起来不太优雅。
所以:
非常感谢
一种方法是利用image-rendering
CSS property。这可以暗示浏览器在image-rendering
元素(如Leaflet地图图块)上使用最近邻插值。
例如:
<img>
请参见img.leaflet-tile {
image-rendering: pixelated;
}
。当心working demo。
更复杂的方法(但可以在更多浏览器上使用的方法是利用incomplete browser support;特别是WebGL。
这涉及一些Leaflet.TileLayer.GL,最关键的是在每个图块渲染中将统一值设置为图块坐标...
internal changes to Leaflet.TileLayer.GL to support a per-tile uniform
...具有gl.uniform3f(this._uTileCoordsPosition, coords.x, coords.y, coords.z);
,用于“显示”未缩放的图块以显示缩放的图块坐标(而不是仅跳过不存在的图块)...
L.TileLayer
...加上片段着色器,该片段着色器在获取texel之前先四舍五入texel坐标(再加上依赖于tile坐标的模相关偏移),以实际执行最近邻居的过采样...
var hackishTilelayer = new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
'attribution': 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
maxNonPixelatedZoom: 3
});
hackishTilelayer.getTileUrl = function(coords) {
if (coords.z > this.options.maxNonPixelatedZoom) {
return this.getTileUrl({
x: Math.floor(coords.x / 2),
y: Math.floor(coords.y / 2),
z: coords.z - 1
});
}
// Skip L.TileLayer.prototype.getTileUrl.call(this, coords), instead
// apply the URL template directly to avoid maxNativeZoom shenanigans
var data = {
r: L.Browser.retina ? '@2x' : '',
s: this._getSubdomain(coords),
x: coords.x,
y: coords.y,
z: coords.z // *not* this._getZoomForUrl() !
};
var url = L.Util.template(this._url, L.Util.extend(data, this.options));
return url;
}
...在var fragmentShader = `
highp float factor = max(1., pow(2., uTileCoords.z - uPixelatedZoomLevel));
vec2 subtileOffset = mod(uTileCoords.xy, factor);
void main(void) {
vec2 texelCoord = floor(vTextureCoords.st * uTileSize / factor ) / uTileSize;
texelCoord.xy += subtileOffset / factor;
vec4 texelColour = texture2D(uTexture0, texelCoord);
// This would output the image colours "as is"
gl_FragColor = texelColour;
}
`;
的实例中全部绑在一起(它为周围的制服同步一些数字):
L.TileLayer.GL
您可以看到所有内容协同工作 var pixelated = L.tileLayer.gl({
fragmentShader: fragmentShader,
tileLayers: [hackishTilelayer],
uniforms: {
// The shader will need the zoom level as a uniform...
uPixelatedZoomLevel: hackishTilelayer.options.maxNonPixelatedZoom,
// ...as well as the tile size in pixels.
uTileSize: [hackishTilelayer.getTileSize().x, hackishTilelayer.getTileSize().y]
}
}).addTo(map);
。