使用Openlayers ImageCanvas canvasFunction绘制其他来源的特征



我正在开发一些自定义绘图工具,这些工具将应用非常特定的样式,这些样式最容易创建并直接绘制到画布上。我很难弄清楚如何正确地将坐标与像素对齐并将其固定在地图上。

除了在前/后渲染中直接修改画布的变换外,我也不知道如何在-180之前(或者可能是>360(在ImageCanvas上绘制任何东西,但我也无法完全正确地完成这项工作。

在下面的fiddle中,我在矢量源中添加了两个线特征。一个从-180,0到0,0绘制,另一个从-400,0到-300,0绘制。

第一条线特征下方显示了一条红线,这条红线是由ImageCanvas绘制的,但它位于错误的位置,放大/缩小或平移/平移地图会导致它四处移动。红线应该覆盖蓝线。

第二行特征没有可见的红线。这似乎与转换有关,但我不确定。

我尝试过将范围添加到投影对象中,这似乎确实改变了事情,但不清楚在我的情况下应该添加什么。

小提琴:https://jsfiddle.net/jroetman/fqsh2z46/51/

const extent = [-400, -85, 400, 85]
const textent = ol.proj.transformExtent(    
extent,
"EPSG:4326",
"EPSG:3857"
)
const canvas = document.createElement("canvas");
const vsource = new ol.source.Vector({ wrapX: false });
const vlayer = new ol.layer.Vector({source: vsource})
const pixProj = new ol.proj.Projection({
code: "pixel-projection",
units: "pixels",
})
const points = [[extent[0],0], [extent[0] + 100,0]].map(p =>  ol.proj.transform(p, "EPSG:4326", "EPSG:3857"))
const points2 =  [[-180,0], [0,0]].map(p =>  ol.proj.transform(p, "EPSG:4326", "EPSG:3857"))
vsource.addFeature(new ol.Feature(new ol.geom.LineString(points)))
vsource.addFeature(new ol.Feature(new ol.geom.LineString(points2)))
var ic = new ol.source.ImageCanvas({
ratio: 1,
canvasFunction: (extent, resolution, pixelRatio, size, projection) => {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let f of vsource.getFeatures()) {        
const coords = f.getGeometry().getCoordinates();
const pixel1 = this.map.getPixelFromCoordinate(coords[0]);              
const pixel2 = this.map.getPixelFromCoordinate(coords[1]);
ctx.save();
ctx.beginPath();
ctx.moveTo(pixel1[0],pixel1[1]);                                   
ctx.lineTo(pixel2[0],pixel2[1]);                           
ctx.closePath();
ctx.strokeStyle = "red";
ctx.stroke() 
ctx.restore()

}
return canvas;
},
projection: pixProj
});

var imageLayer = new ol.layer.Image({
className: "annotate",
source: ic,
zIndex: 100
}); 
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vlayer,
imageLayer
],
view:  new ol.View({
projection: "EPSG:3857",
minZoom: 2.75,
center: [-50000,-300000],
zoom: 6,
extent:textent
}),
});

John Robinson创建的更新/工作版本。非常感谢。https://jsfiddle.net/8anhd2vb/


原始过账

好的,我解决了这个问题,并简化了一些事情。我仍然有兴趣了解如何更多地使用ImageCanvas,但目前。。。。

我能够直接在画布上绘制矢量层本身的";后渲染";使用vlayer.getRenderer().context

https://jsfiddle.net/jroetman/fqsh2z46/95/

const extent = [-400, -85, 400, 85]
const textent = ol.proj.transformExtent(    
extent,
"EPSG:4326",
"EPSG:3857"
)
const canvas = document.createElement("canvas");
const vsource = new ol.source.Vector({ wrapX: false });
const vlayer = new ol.layer.Vector({source: vsource})

const points = [[extent[0],0], [extent[0] + 100,0]].map(p =>  ol.proj.transform(p, "EPSG:4326", "EPSG:3857"))
const points2 =  [[-50,0], [0,0]].map(p =>  ol.proj.transform(p, "EPSG:4326", "EPSG:3857"))
vsource.addFeature(new ol.Feature(new ol.geom.LineString(points)))
vsource.addFeature(new ol.Feature(new ol.geom.LineString(points2)))
vlayer.on('postrender', (e) => {
var ctx = vlayer.getRenderer().context; 
for (let f of vsource.getFeatures()) {        
const coords = f.getGeometry().getCoordinates();       
const pixel1 = ol.render.getRenderPixel(e,map.getPixelFromCoordinate(coords[0]));           
const pixel2 = ol.render.getRenderPixel(e,map.getPixelFromCoordinate(coords[1]));
ctx.save();
ctx.beginPath();
ctx.moveTo(pixel1[0],pixel1[1] );                                   
ctx.lineTo(pixel2[0],pixel2[1]);                         
ctx.closePath();
ctx.strokeStyle = "red";
ctx.stroke() 
ctx.restore()      
}       
});

var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vlayer,
],
view:  new ol.View({
projection: "EPSG:3857",
minZoom: 2.75,
center: ol.proj.transform([-10,-5],"EPSG:4326","EPSG:3857"),
zoom: 5,
extent:textent
}),
});

相关内容

  • 没有找到相关文章

最新更新