Openlayers 3:在自定义静态图像上绘制具有预定义单位的网格线(经纬网)

时间:2016-08-22 22:23:49

标签: openlayers-3

我试图在静态图像上绘制自定义x-y轴网格线,即图像像素而不是纬度和经度。理想情况下,当我拖动/缩放/滚动图像时,应该动态地重绘网格线,就像Photoshop中的x-y标尺一样。

我遇到了以下代码示例,该示例提供了一个自定义投影函数,可直接将图像像素坐标映射到地图坐标。

http://openlayers.org/en/latest/examples/static-image.html

// Map views always need a projection.  Here we just want to map image
// coordinates directly to map coordinates, so we create a projection that uses
// the image extent in pixels.
var extent = [0, 0, 1024, 968];
var projection = new ol.proj.Projection({
        code: 'xkcd-image',
        units: 'pixels',
        extent: extent
      });

我尝试将以下代码附加到脚本中。但是,ol.Graticule类似乎与自定义ol.proj.Projection定义不兼容。

http://openlayers.org/en/latest/examples/graticule.html

// Create the graticule component
var graticule = new ol.Graticule({
// the style to use for the lines, optional.
strokeStyle: new ol.style.Stroke({
  color: 'rgba(255,120,0,0.9)',
  width: 2,
  lineDash: [0.5, 4]
  })
});
graticule.setMap(map);

上述代码有什么问题?

P.S。我知道Openseadragon API提供动态比例尺。但是,我希望坚持使用Openlayers API,因为我还在静态图像上的预定义位置有一个额外的锚点地图图层。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。为此,我创建了一个矢量图层(其中绘制了轴)。 要绘制轴,我需要听取View更改。

每当视图发生变化时,请计算视图的实际范围。

使用范围信息和图像的([width, height],然后可以绘制轴)



let listenerAxis = null,
    w = 0,
    h = 0

const xAxisStyle = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'red',
    width: 2
  })
})

const yAxisStyle = new ol.style.Style({
  stroke: new ol.style.Stroke({
    color: 'green',
    width: 2
  })
})


const ImageLayer = new ol.layer.Image()

const AxisLayer = new ol.layer.Vector({ source: new ol.source.Vector() })

AxisLayer.setStyle((feature, resolution) => {
  if(feature.getProperties().axis == 'x') {
    return xAxisStyle
  }
  return yAxisStyle
})

const renderer = new ol.Map({
  target: 'map',
  layers: [ImageLayer]
})

AxisLayer.setMap(renderer)

processFile('https://i2.wp.com/beebom.com/wp-content/uploads/2016/01/Reverse-Image-Search-Engines-Apps-And-Its-Uses-2016.jpg?resize=640%2C426')



function removeAxis() {
  AxisLayer.getSource().clear()
  ol.Observable.unByKey(listenerAxis)
  listenerAxis = null
}

function drawAxis() {
  function draw(){
    AxisLayer.getSource().clear()
    const extent = renderer.getView().calculateExtent()
    const [xmin, ymin, xmax, ymax] = extent
    // Eje X
    const axisX = new ol.geom.LineString([ [xmin, h / 2], [xmax, h / 2] ])
    const axisY = new ol.geom.LineString([ [w / 2, ymin], [w / 2, ymax] ])

    const featureX = new ol.Feature({ geometry: axisX, axis: 'x' })
    const featureY = new ol.Feature({ geometry: axisY, axis: 'y' })

    AxisLayer.getSource().addFeatures([featureX, featureY])
  }

  listenerAxis = renderer.getView().on('change', draw)
  draw()

}


async function processFile(path) {

  ImageLayer.setSource()
  removeAxis()

  if(!path) {
    return 
  }


  const [wi, hi] = await readImage(path)
  w = wi
  h = hi

  const source = getImageStatic(path, w, h)
  const view = getViewForImage(w, h)


  ImageLayer.setSource(source)
  renderer.setView(view)
  drawAxis()
}


// Some helpers
function readImage(localPath) {
  const img = document.createElement('img')
  return new Promise((res, rej) => {
    img.src = localPath
    img.addEventListener('load', (event) => {
      const { naturalWidth, naturalHeight } = img
      console.log('img', naturalWidth, naturalHeight)
      res([naturalWidth, naturalHeight])
    })
  })
}

function getViewForImage(w, h) {
  return new ol.View({
    center: [w / 2, h / 2],
    zoom: 2,
    projection: new ol.proj.Projection({
      extent: [0, 0, w, h],
      units: 'pixels'
    }),
    extent: [0, 0, w, h]
  })
}

function getImageStatic(path, w, h) {
  return new ol.source.ImageStatic({
    url: path,
    imageExtent: [0, 0, w, h]
  })
}

#map {
  width: 100%;
  height: 100%;
  background: grey;
}

<link href="https://openlayers.org/en/v4.6.5/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>

<div id="map"></div>
&#13;
&#13;
&#13;