openlayers 框选后获取图像信息

590 阅读2分钟

​ 需求:在右图map中框选一部分区域,通过接口搜索相似图像 1777-e2350dded9fb.png  

  1. 创建map实例

mounted() {
    this.initMap()
  },
methods:{
  
    initMap() {

      this.raster = new TileLayer({
        source:new OSM(),
        preload: Infinity
      })
      
       
      this.vectorLayer = new VectorLayer({
        source: new VectorSource({ wrapX: false })
      })  

      let view = new View({
        resolutions: rasterSource.getTileGrid().getResolutions(),
        center: [this.imageDetail.width / 4, -this.imageDetail.height / 4],
        zoom: 3,
        zoomFactor: 2 // 这个会影响像素坐标的计算, 使点坐标变得非常小
      })
   
      let map = new Map({
        target: this.$refs.openlayersMap,
        layers: [
          this.raster,
          this.vectorLayer
        ],
        view: view
      })
      this.map = map            
      this.doDraw()
    },
 }
  1. 创建draw 实例,并监听 绘制结束事件(drawend),获取 矢量数据(imageGeometry)
doDraw() {
      var extent = []
      let source = this.vectorLayer.getSource()
      let toolConfig = { value: 'Circle', freehand: false, geometryFunction:                 createBox(), title: '矩形测量', icon: 'icon-juxing' }
      let draw = new Draw({
        source: source,
        type: toolConfig.value,
        freehand: toolConfig.freehand,
        maxPoints: toolConfig.maxPoints,
        geometryFunction: toolConfig.geometryFunction,
        style: new Style({         
          stroke: new Stroke({
            color: 'rgba(0, 0, 0, 0.5)',
            lineDash: [10, 10],
            width: 2
          })
        }),
        // 在标注完成的时候会自动单击,这里需要防止select操作发生导致的选中被取消
        stopClick: true
      })
      draw.on('drawend', e => {
        this.imageGeometry = e.feature.getGeometry()
      })

      draw.on('drawstart', evt => {   
         source.clear()
      })
      this.raster.on('postrender', this.doClipLayer1)
      this.map.addInteraction(draw)
    },
  1. 图层渲染之后进行图像信息的获取,一定要是渲染之后(postrender),不然获取到的图像信息为0
  • 获取矢量数据的四至(extent),通过自带的方法: getTopLeft 获取 左上角的像素距离 、宽:getWidth、高:getHeight()。注意:getWidth、getHeight获取的是地理坐标宽高,要转成像素宽度需要除以分辨率进行转换
  • 这样就可以通过 getImageData,来获取图像数据,再通过创建canvas=>填入图像信息putImageData=>转换成base64图像信息toDataURL  
//渲染之后,获取框选区域图像信息
    doClipLayer(event) {
      if (!this.imageGeometry) return
      let ctx = event.context
      let canvas = ctx.canvas
      let extent = this.imageGeometry.getExtent()
      //左上角 的像素距离
      let [x, y] = this.map.getPixelFromCoordinate(getTopLeft(extent))
      this.currentPixelZoom = this.map.getView().getZoom()
      this.resolution1 = this.map.getView().getResolutionForZoom(this.currentPixelZoom)
      //getWidth、getHeight获取的是地理坐标宽高,要转成像素宽度需要除以分辨率进行转换
      let w = getWidth(extent) / this.resolution1 
      let h = getHeight(extent) / this.resolution1
      let imageData = ctx.getImageData(x, y, w, h)
      let newCanvas = document.createElement('canvas')
      newCanvas.width = w
      newCanvas.height = h
      let newCtx = newCanvas.getContext('2d')
      newCtx.putImageData(imageData, 0, 0)
      this.urlBase64 = newCanvas.toDataURL()
    },
  1. 最后监听 urlBase64 的改变,调用接口获取相似图像列表
watch: {
    urlBase64(val) {
      if (!val) return
      this.startPicSearch({ file: this.dataURLtoFile(val) })
      //imageGeometry置为空,不然 postrender 事件会一直更新urlBase64
      this.imageGeometry = null
    }
  },
  
  methods:{
    startPicSearch({ file }) {
      let formData = new FormData()
      formData.append('image', file)
      this.picData = formData
      this.picSearch()
    },
    //将base64 转为file对象
    dataURLtoFile(dataurl) {
      const arr = dataurl.split(',')
      let mime = arr[0].match(/:(.*?);/)[1]
      let bstr = atob(arr[1])
      let n = bstr.length
      let u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new Blob([u8arr], { type: mime })
    },
  }