美文网首页
openlayer 解决draw 双击结束后,地图自动放大

openlayer 解决draw 双击结束后,地图自动放大

作者: 冰落寞成 | 来源:发表于2023-01-29 16:19 被阅读0次

一、问题描述

在使用OpenLayer draw 绘制图形,使用双击事件结束绘制时,地图会放大。


1675066448279.png

二、直接解决办法

在创建map 时,直接禁止,但是会造成整个图层不能使用双击放大地图

import { defaults as defaultInteractions } from 'ol/interaction.js'
let map = new ol.Map({
    target: id,
    layers: options.mapLayers,
    view: view,
    controls: defaultControls({
      zoom: false,
      rotate: false,
      attribution: false
    }),
    interactions: defaultInteractions({ doubleClickZoom: false })
  })

三、使用动态函数,在需要的地方禁止掉

自定义绘制类,在绘制类里面禁止掉

import { Draw, Modify, DoubleClickZoom } from 'ol/interaction.js'
let doubleClickZoom = new DoubleClickZoom()
    let doubleClickZoomArr = this.map.getInteractions().array_.filter(
      item => {
        return item.constructor.name === doubleClickZoom.constructor.name
      }
    )
    this.map.removeInteraction(doubleClickZoomArr[0])

四、自定义绘制类


import * as ol from '../openLayer'
// import Draw from 'ol/interaction/Draw.js'
import { Draw, Modify, DoubleClickZoom } from 'ol/interaction.js'
import { getArea, getLength } from 'ol/sphere.js'
import { LineString, Point } from 'ol/geom.js'
import { drawDefaultConfig } from './config'
import { drawingLineStyle, drawEndLineStyle, pointTipStyle, setLabelStyle, setTipStyle, modifyStyle } from './style'
import { deepAssign } from '@/utils'
/**
 * 绘制图形shap 类,
 * 配置项参考config.js
 * 样式项参考style.js
 */
export default class OlDrawShap {
  constructor (_map, _config) {
    this.map = _map
    this.options = deepAssign(drawDefaultConfig, _config) //  配置项
    this.draw = null

    this.source = new ol.VectorSource()
    let doubleClickZoom = new DoubleClickZoom()
    let doubleClickZoomArr = this.map.getInteractions().array_.filter(
      item => {
        return item.constructor.name === doubleClickZoom.constructor.name
      }
    )
    this.map.removeInteraction(doubleClickZoomArr[0])

    const drawLayer = new ol.VectorLayer({
      source: this.source,
      className: 'DrawShapLayer',
      properties: this.options.layerProperties,
      style: (feature) => {
        return this.getDrawStyle(feature, this.options.shapConfig.type, true)
      }
    })
    this.map.addLayer(drawLayer)

    this.mouseTipModify = new Modify({ source: this.source, style: this.modifyStyle })
    this.mouseTip = this.options.mouseTipConfig.tipText
    this.onDrawShap()
  }

  onDrawShap () {
    let shapTypes = ['MultiLineString', 'MultiPolygon']
    // console.log('this.options.shapConfig.type', this.options.shapConfig.type)
    if (shapTypes.indexOf(this.options.shapConfig.type) > -1) {
      this.handleDraw()
    } else {
      // console.log('类型错误')
      alert('类型错误')
    }
  }

  /**
   * 更新配置
   */
  updateOlDrawShap (_map, _config) {
    // console.log('更新配置', this.source, this.draw)
    this.options = deepAssign(drawDefaultConfig, _config) //  配置项

    this.onDrawShap()
  }

  /**
 * 获取线段长度
 * @param {*} line
 * @returns
 */
  formatLength (line) {
    const length = getLength(line)
    let output
    if (length > 100) {
      output = Math.round((length / 1000) * 100) / 100 + ' km'
    } else {
      output = Math.round(length * 100) / 100 + ' m'
    }
    return output
  };

  /**
 * 计算区域面积
 * @param {*} polygon
 * @returns
 */
  formatArea (polygon) {
    const area = getArea(polygon)
    // console.log('area', area)
    let output
    if (area > 10000) {
      output = Math.round((area / 1000000) * 100) / 100 + ' km\xB2'
    } else {
      output = Math.round(area * 100000) / 100000 + ' m\xB2'
    }
    // console.log('output=', output)
    return output
  };

  /**
   * 获取当前绘制样式
   */
  getDrawStyle (feature, drawType = 'MultiPolygon', drawEndBool = false, tip) {
    let styles
    if (drawEndBool) {
      styles = [drawEndLineStyle(this.options)]
    } else {
      styles = [drawingLineStyle(this.options)]
    }
    const geometry = feature.getGeometry()
    const type = geometry.getType()
    let point, label, line, lines
    if (drawEndBool) {
      console.log('type', type, geometry)
    }
    //
    if (this.options.labelConfig.show) { // 显示点位提示
      if ((type === 'Polygon' || type === 'MultiPolygon')) { // 多边形求面积
        if (type === 'Polygon') {
          point = geometry.getInteriorPoint()
        } else if (type === 'MultiPolygon') {
          point = geometry.getInteriorPoints()
        }
        // console.log('point', point)
        line = new LineString(geometry.getCoordinates()[0])
        label = this.formatArea(geometry)
      } else if (type === 'LineString' || type === 'MultiLineString') {
        point = new Point(geometry.getLastCoordinate())

        label = this.formatLength(geometry)
        line = geometry
      }
      if (line) {
        let count = 0
        const pointTipStyles = [pointTipStyle(this.options, drawEndBool)]
        if (type === 'MultiLineString') {
          lines = geometry.getLineStrings()
          for (let i in lines) {
            // console.log('i=', i)
            lines[i].forEachSegment((a, b) => {
              const segment = new LineString([a, b])
              const label = this.formatLength(segment)
              if (pointTipStyles.length - 1 < count) {
                pointTipStyles.push(pointTipStyle(this.options, drawEndBool).clone())
              }
              const segmentPoint = new Point(segment.getCoordinateAt(0.5))
              pointTipStyles[count].setGeometry(segmentPoint)
              pointTipStyles[count].getText().setText(label)
              styles.push(pointTipStyles[count])
              count++
            })
          }
          if (drawEndBool) {
            console.log('point=', point, 'lines=', lines)
          }
        } else {
          line.forEachSegment((a, b) => {
            const segment = new LineString([a, b])
            const label = this.formatLength(segment)
            if (pointTipStyles.length - 1 < count) {
              pointTipStyles.push(pointTipStyle(this.options, drawEndBool).clone())
            }
            const segmentPoint = new Point(segment.getCoordinateAt(0.5))
            pointTipStyles[count].setGeometry(segmentPoint)
            pointTipStyles[count].getText().setText(label)
            styles.push(pointTipStyles[count])
            count++
          })
        }
      }
      // console.log('line=', line)
      if (label) {
        const labelStyle = setLabelStyle(this.options, drawEndBool)
        // console.log('labelStyle', labelStyle)
        labelStyle.setGeometry(point)
        labelStyle.getText().setText(label)
        styles.push(labelStyle)
      }
      if (this.options.mouseTipConfig.show) {
        let tipPoint
        const tipStyle = setTipStyle(this.options)
        if (tip && type === 'Point' && !this.mouseTipModify.getOverlay().getSource().getFeatures().length) {
          tipPoint = geometry
          tipStyle.getText().setText(tip)
          styles.push(tipStyle)
        }
      }
    }
    // console.log(styles)
    return styles
  }

  /**
   * 绘制
   */
  handleDraw () {
    if (!this.draw) {
      this.draw = new Draw({
        source: this.source,
        type: this.options.shapConfig.type,
        geometryName: this.options.layerProperties.id,
        style: (feature) => {
          // console.log('样式', this.getDrawStyle(feature, 'LineString', '测试'))
          return this.getDrawStyle(feature, this.options.shapConfig.type, false, this.mouseTip)
        }
      })
      this.draw.setActive(true)

      this.draw.on('drawstart', () => {
        if (!this.options.shapConfig.isMultipleBool && this.source) {
          this.source.clear()
        }
        this.mouseTipModify.setActive(false)
        this.mouseTip = this.options.mouseTipConfig.drawTipText
      })
      this.draw.on('drawend', (e) => {
        this.mouseTip = this.options.mouseTipConfig.tipText
        if (this.draw && !this.options.shapConfig.isMultipleBool) {
          this.draw.finishDrawing()
          e.stopPropagation()
          e.preventDefault()
          this.map.removeInteraction(this.draw)
          this.draw.setActive(false)
          this.draw = null
        }
      })
      this.mouseTipModify.setActive(true)
      this.map.addInteraction(this.draw)
    }
  }
}

四、默认配置


/**
 * 默认图形配置
 */
export const drawDefaultConfig = {
  type: 'DrawShapLayer',
  layerProperties: {
    id: 'DrawShapLayer',
    name: 'DrawShapLayer',
    geometryName: 'DrawShapLayer'
  },
  shapConfig: {
    type: 'MultiPolygon',
    isMultipleBool: false // 不允许多个存在 false-> 不允许,true -> 允许
  },
  labelConfig: {
    show: false,
    labelStyle: {
      drawingStyle: {
        textStyle: {
          font: '14px Calibri,sans-serif',
          fillColor: '#fff',
          backgroundFillColor: 'rgba(0, 0, 0, 0.7)',
          padding: [3, 3, 3, 3],
          textBaseline: 'bottom',
          offsetY: -15
        },
        imageStyle: {
          radius: 8,
          points: 3,
          angle: Math.PI,
          displacement: [0, 10],
          fillColor: 'rgba(0, 0, 0, 0.7)'
        }
      },
      drawEndStyle: {
        textStyle: {
          font: '14px Calibri,sans-serif',
          fillColor: '#606266',
          backgroundFillColor: 'rgba(255, 204, 51, 1)',
          padding: [3, 3, 3, 3],
          textBaseline: 'bottom',
          offsetY: -15
        },
        imageStyle: {
          radius: 8,
          points: 3,
          angle: Math.PI,
          displacement: [0, 10],
          fillColor: 'rgba(255, 204, 51, 1)'
        }
      }
    },
    pointTipStyle: { // 坐标点样式
      drawingStyle: {
        textStyle: {
          font: '12px Calibri,sans-serif',
          fillColor: '#fff',
          backgroundFillColor: 'rgba(0, 0, 0, 0.4)',
          padding: [2, 2, 2, 2],
          textBaseline: 'bottom',
          offsetY: -15
        },
        imageStyle: {
          radius: 6,
          points: 3,
          angle: Math.PI,
          displacement: [0, 8],
          fillColor: 'rgba(0, 0, 0, 0.4)'
        }
      },
      drawEndStyle: {
        textStyle: {
          font: '12px Calibri,sans-serif',
          fillColor: '#606266',
          backgroundFillColor: 'rgba(255, 204, 51,0.9)',
          padding: [2, 2, 2, 2],
          textBaseline: 'bottom',
          offsetY: -13
        },
        imageStyle: {
          radius: 6,
          points: 3,
          angle: Math.PI,
          displacement: [0, 8],
          fillColor: 'rgba(255, 204, 51,0.9)'
        }
      }
    }
  },
  paintBrushConfig: { // 画笔样式设置
    radius: 5,
    strokeColor: 'rgba(0, 0, 0, 0.7)',
    fillColor: 'rgba(255, 255, 255, 0.2)'
  },

  lineConfig: { // 线条样式设置
    drawingStyle: { // 绘制中样式设置
      fillColor: 'rgba(255, 255, 255, 0.2)',
      strokeColor: 'rgba(0, 0, 0, 0.5)',
      strokeLineDash: [10, 10],
      strokeWidth: 2

    },
    drawEndStyle: { //  绘制完成样式设置
      fillColor: 'rgba(255, 255, 255, 0.2)',
      strokeColor: '#ffcc33',
      strokeLineDash: [0, 0],
      strokeWidth: 2
    }
  },

  mouseTipConfig: {
    show: true,
    tipText: '点击开始绘制',
    drawTipText: '继续点击绘制线条,双击结束绘制',
    textStyle: {
      font: '12px Calibri,sans-serif',
      fillColor: 'rgba(255, 255, 255, 1)',
      backgroundFillColor: 'rgba(0, 0, 0, 0.4)',
      padding: [2, 2, 2, 2],
      textAlign: 'left',
      offsetX: 15
    }
  }
}

样式设置

import * as ol from '../openLayer'
/**
   * 绘制时线条、画笔 的样式
   */
export const drawingLineStyle = (options) => {
  return new ol.Style({ //  线条
    fill: new ol.Fill({
      color: options.lineConfig.drawingStyle.fillColor
    }),
    stroke: new ol.Stroke({
      color: options.lineConfig.drawingStyle.strokeColor,
      lineDash: options.lineConfig.drawingStyle.strokeLineDash,
      width: options.lineConfig.drawingStyle.strokeWidth
    }),
    image: new ol.CircleStyle({ // 画笔
      radius: options.paintBrushConfig.radius,
      stroke: new ol.Stroke({
        color: options.paintBrushConfig.strokeColor
      }),
      fill: new ol.Fill({
        color: options.paintBrushConfig.fillColor
      })
    })
  })
}
/**
   * 绘制结束时线条、画笔 的样式
   */
export const drawEndLineStyle = (options) => {
  return new ol.Style({ //  线条
    fill: new ol.Fill({
      color: options.lineConfig.drawEndStyle.fillColor
    }),
    stroke: new ol.Stroke({
      color: options.lineConfig.drawEndStyle.strokeColor,
      lineDash: options.lineConfig.drawEndStyle.strokeLineDash,
      width: options.lineConfig.drawEndStyle.strokeWidth
    }),
    image: new ol.CircleStyle({ // 画笔
      radius: options.paintBrushConfig.radius,
      stroke: new ol.Stroke({
        color: options.paintBrushConfig.strokeColor
      }),
      fill: new ol.Fill({
        color: options.paintBrushConfig.fillColor
      })
    })
  })
}

/**
* 坐标点提示样式
* @returns
*/
export const pointTipStyle = (options, bool = false) => {
  if (bool) {
    return new ol.Style({
      text: new ol.Text({
        font: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.font,
        fill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.fillColor
        }),
        backgroundFill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.backgroundFillColor
        }),
        padding: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.padding,
        textBaseline: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.textBaseline,
        offsetY: options.labelConfig.pointTipStyle.drawEndStyle.textStyle.offsetY
      }),
      image: new ol.RegularShape({
        radius: options.labelConfig.pointTipStyle.drawEndStyle.imageStyle.radius,
        points: options.labelConfig.pointTipStyle.drawEndStyle.imageStyle.points,
        angle: options.labelConfig.pointTipStyle.drawEndStyle.imageStyle.angle,
        displacement: options.labelConfig.pointTipStyle.drawEndStyle.imageStyle.displacement,
        fill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawEndStyle.imageStyle.fillColor
        })
      })
    })
  } else {
    return new ol.Style({
      text: new ol.Text({
        font: options.labelConfig.pointTipStyle.drawingStyle.textStyle.font,
        fill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawingStyle.textStyle.fillColor
        }),
        backgroundFill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawingStyle.textStyle.backgroundFillColor
        }),
        padding: options.labelConfig.pointTipStyle.drawingStyle.textStyle.padding,
        textBaseline: options.labelConfig.pointTipStyle.drawingStyle.textStyle.textBaseline,
        offsetY: options.labelConfig.pointTipStyle.drawingStyle.textStyle.offsetY
      }),
      image: new ol.RegularShape({
        radius: options.labelConfig.pointTipStyle.drawingStyle.imageStyle.radius,
        points: options.labelConfig.pointTipStyle.drawingStyle.imageStyle.points,
        angle: options.labelConfig.pointTipStyle.drawingStyle.imageStyle.angle,
        displacement: options.labelConfig.pointTipStyle.drawingStyle.imageStyle.displacement,
        fill: new ol.Fill({
          color: options.labelConfig.pointTipStyle.drawingStyle.imageStyle.fillColor
        })
      })
    })
  }
}

/**
* 终点坐标点提示样式
* @returns
*/
export const setLabelStyle = (options, bool = false) => {
  if (bool) {
    return new ol.Style({
      text: new ol.Text({
        font: options.labelConfig.labelStyle.drawEndStyle.textStyle.font,
        fill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawEndStyle.textStyle.fillColor
        }),
        backgroundFill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawEndStyle.textStyle.backgroundFillColor
        }),
        padding: options.labelConfig.labelStyle.drawEndStyle.textStyle.padding,
        textBaseline: options.labelConfig.labelStyle.drawEndStyle.textStyle.textBaseline,
        offsetY: options.labelConfig.labelStyle.drawEndStyle.textStyle.offsetY
      }),
      image: new ol.RegularShape({
        radius: options.labelConfig.labelStyle.drawEndStyle.imageStyle.radius,
        points: options.labelConfig.labelStyle.drawEndStyle.imageStyle.points,
        angle: options.labelConfig.labelStyle.drawEndStyle.imageStyle.angle,
        displacement: options.labelConfig.labelStyle.drawEndStyle.imageStyle.displacement,
        fill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawEndStyle.imageStyle.fillColor
        })
      })
    })
  } else {
    return new ol.Style({
      text: new ol.Text({
        font: options.labelConfig.labelStyle.drawingStyle.textStyle.font,
        fill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawingStyle.textStyle.fillColor
        }),
        backgroundFill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawingStyle.textStyle.backgroundFillColor
        }),
        padding: options.labelConfig.labelStyle.drawingStyle.textStyle.padding,
        textBaseline: options.labelConfig.labelStyle.drawingStyle.textStyle.textBaseline,
        offsetY: options.labelConfig.labelStyle.drawingStyle.textStyle.offsetY
      }),
      image: new ol.RegularShape({
        radius: options.labelConfig.labelStyle.drawingStyle.imageStyle.radius,
        points: options.labelConfig.labelStyle.drawingStyle.imageStyle.points,
        angle: options.labelConfig.labelStyle.drawingStyle.imageStyle.angle,
        displacement: options.labelConfig.labelStyle.drawingStyle.imageStyle.displacement,
        fill: new ol.Fill({
          color: options.labelConfig.labelStyle.drawingStyle.imageStyle.fillColor
        })
      })
    })
  }
}

/**
 * 鼠标提示样式
 * @returns
 */
export const setTipStyle = (options) => {
  return new ol.Style({
    text: new ol.Text({
      font: options.mouseTipConfig.textStyle.font,
      fill: new ol.Fill({
        color: options.mouseTipConfig.textStyle.fillColor
      }),
      backgroundFill: new ol.Fill({
        color: options.mouseTipConfig.textStyle.backgroundFillColor
      }),
      padding: options.mouseTipConfig.textStyle.padding,
      textAlign: options.mouseTipConfig.textStyle.textAlign,
      offsetX: options.mouseTipConfig.textStyle.offsetX
    })
  })
}

/**
 * 鼠标提示样式
 * @returns
 */
export const modifyStyle = (options) => {
  return new ol.Style({
    image: new ol.CircleStyle({
      radius: options.paintBrushConfig.radius,
      stroke: new ol.Stroke({
        color: options.paintBrushConfig.strokeColor
      }),
      fill: new ol.Fill({
        color: options.paintBrushConfig.fillColor
      })
    }),
    text: new ol.Text({
      font: options.mouseTipConfig.textStyle.font,
      fill: new ol.Fill({
        color: options.mouseTipConfig.textStyle.fillColor
      }),
      backgroundFill: new ol.Fill({
        color: options.mouseTipConfig.textStyle.backgroundFillColor
      }),
      padding: options.mouseTipConfig.textStyle.padding,
      textAlign: options.mouseTipConfig.textStyle.textAlign,
      offsetX: options.mouseTipConfig.textStyle.offsetX
    })
  })
}

相关文章

网友评论

      本文标题:openlayer 解决draw 双击结束后,地图自动放大

      本文链接:https://www.haomeiwen.com/subject/cejphdtx.html