OpenLayers实现点、线、面以及流线效果

394 阅读3分钟

效果展示

GIF 2024-5-22 16-13-58.gif

openlayers引入天地图

使用openlayers加载天地图,并初始化地图

const projection = get('EPSG:4326');
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 2; z < 19; ++z) {
  resolutions[z] = size / Math.pow(2, z);
}

// 初始化创建地图
initMap(layerType) {
  const TIANDI_KEY = '使用自己的天地图tk';
  const layerTypeMap = {
    SL: ['vec', 'cva'], // [矢量底图, 矢量注记]
    YX: ['img', 'cia'], // [影像底图, 影像注记]
    DX: ['ter', 'cta'] // [地形晕渲, 地形注记]
  };
  // c: 经纬度投影 w: 球面墨卡托投影
  const matrixSet = 'c';
  // 底图
  const baseMap = new TileLayer({
    source: new WMTS({
      url: `http://t{0-6}.tianditu.com/${layerTypeMap[layerType][0]}_${matrixSet}/wmts?tk=${TIANDI_KEY}`,
      layer: layerTypeMap[layerType][0],
      matrixSet: matrixSet,
      style: 'default',
      crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
      format: 'tiles',
      wrapX: true,
      tileGrid: new WMTSTileGrid({
        origin: getTopLeft(projectionExtent),
        resolutions: resolutions,
        matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14']
      })
    })
  });
  // 标注
  const labelMap = new TileLayer({
    source: new WMTS({
      url: `http://t{0-6}.tianditu.com/${layerTypeMap[layerType][1]}_${matrixSet}/wmts?tk=${TIANDI_KEY}`,
      layer: layerTypeMap[layerType][1],
      matrixSet: matrixSet,
      style: 'default',
      crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
      format: 'tiles',
      wrapX: true,
      tileGrid: new WMTSTileGrid({
        origin: getTopLeft(projectionExtent),
        resolutions: resolutions,
        matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14']
      })
    })
  });
  // 视图
  const viewMap = new View({
    center: [111.85891, 31.70299],
    projection: projection,
    zoom: 8.5,
    maxZoom: 14,
    minZoom: 1
  });
  this.gisMap = new Map({
    target: this.$refs.map,
    layers: [baseMap, labelMap],
    view: viewMap
  });
  
  this.drawGCBoundary();
  this.drawCJ();
  this.drawSX();
  this.drawDJK();
  PointLonLat.forEach(item => {
    this.createPoint(item);
  });
}

openlayers绘制坐标点

// 绘制试验室坐标点
createPoint(value) {
  const { name, lonLat } = value;
  const style = new Style({
    image: new CircleStyle({
      radius: 8,
      fill: new Fill({ color: 'red' }),
      stroke: new Stroke({ color: 'white', width: 2 })
    }),
    text: new Text({
      text: name,
      overflow: true,
      offsetY: -25,
      fill: new Fill({ color: '#5d5d5c' }),
      stroke: new Stroke({ color: '#fff', width: 2 }),
      backgroundFill: new Fill({ color: '#dcf1f8' }),
      padding: [5, 5, 5, 5],
      font: '14px Calibri,sans-serif',
      textAlign: 'center',
      textBaseline: 'middle'
    })
  });
  const pointFeature = new Feature({
    geometry: new Point(lonLat)
  });

  const vectorSource = new VectorSource({
    features: [pointFeature]
  });
  const vectorLayer = new VectorLayer({
    source: vectorSource,
    zIndex: 1000,
    style
  });
  this.gisMap.addLayer(vectorLayer);
}

openlayers绘制线

createVectorSourcedrawVectorLayer可以通用于线、面绘制中将图层添加到地图上面。

// 创建矢量数据
createVectorSource(geojsonData) {
  const vectorSource = new VectorSource({
    features: new GeoJSON().readFeatures(geojsonData)
  });
  return vectorSource;
},
// 绘制矢量数据图层
drawVectorLayer(data, style) {
  const vectorLayer = new VectorLayer({
    source: this.createVectorSource(data),
    style
  });
  this.gisMap.addLayer(vectorLayer);
},
// 绘制工程边界
drawGCBoundary() {
  const style = new Style({
    stroke: new Stroke({ color: '#32a3f0', width: 2 })
  });
  this.drawVectorLayer(GCBoundary, style);
},

openlayers绘制面

// 绘制三峡水库图层
drawSX() {
  const style = new Style({
    fill: new Fill({ color: '#48e4e5' }),
    stroke: new Stroke({ color: '#48e4e5', width: 2 }),
    text: new Text({
      text: '三峡水库',
      overflow: true,
      offsetX: 15,
      offsetY: 20,
      fill: new Fill({ color: '#2068de' }),
      stroke: new Stroke({ color: '#fff', width: 2 }),
      font: '16px Calibri,sans-serif',
      textAlign: 'center',
      textBaseline: 'middle'
    })
  });
  this.drawVectorLayer(SX, style);
},
// 绘制丹江口水库图层
drawDJK() {
  const style = new Style({
    fill: new Fill({ color: '#e1bcf7' }),
    stroke: new Stroke({ color: '#6e6e6e', width: 2 }),
    text: new Text({
      text: '丹江口水库',
      overflow: true,
      placement: 'line',
      fill: new Fill({ color: '#2068de' }),
      stroke: new Stroke({ color: '#fff', width: 2 }),
      font: '14px Calibri,sans-serif',
      textAlign: 'center',
      textBaseline: 'middle'
    })
  });
  this.drawVectorLayer(DJK, style);
},
// 绘制长江干流图层
drawCJ() {
  const style = new Style({
    fill: new Fill({ color: '#1769e2' }),
    stroke: new Stroke({ color: '#1769e2', width: 2 }),
    text: new Text({
      text: '长江干流',
      overflow: true,
      placement: 'line',
      fill: new Fill({ color: '#000' }),
      stroke: new Stroke({ color: '#fff', width: 2 }),
      font: '14px Calibri,sans-serif',
      textAlign: 'center',
      textBaseline: 'middle'
    })
  });
  this.drawVectorLayer(CJ, style);
}

openlayers实现流线效果

绘制两个线,一个是底部的固定的线,一个是流动的管道线,再使用动画效果实现管道线偏移,实现流动的效果

drawYJBHLine() {
  const style = new Style({
    stroke: new Stroke({ color: '#349ef4', width: 8 }),
    text: new Text({
      text: '文本',
      overflow: true,
      rotation: -20,
      offsetX: 30,
      offsetY: -25,
      fill: new Fill({ color: '#fe2114' }),
      stroke: new Stroke({ color: '#fff', width: 2 }),
      font: '14px Calibri,sans-serif',
      textAlign: 'center',
      textBaseline: 'middle'
    })
  });
  this.drawVectorLayer(YJBH, style);
},
// 绘制流动线
drawFlowLine() {
  const vectorLayer = new VectorLayer({
    source: this.createVectorSource(YJBH),
    zIndex: 900,
    style: new Style({
      stroke: new Stroke({
        color: 'rgba(255,255,255,1)',
        width: 8,
        lineDash: [20, 30], // 虚线模式
        lineDashOffset: 0
      })
    })
  });
  this.gisMap.addLayer(vectorLayer);
  this.animationLine(vectorLayer);
},
// 线动画效果
animationLine(flowLineLayer) {
  const feature = flowLineLayer.getSource().getFeatures()[0];
  setInterval(() => {
    const style = feature.getStyle();
    if (!style) {
      feature.setStyle(
        new Style({
          stroke: new Stroke({
            color: 'rgba(255,255,255,1)',
            width: 8,
            lineDash: [20, 30], // 虚线模式
            lineDashOffset: 0
          })
        })
      );
    } else {
      const lineDashOffset = feature.getStyle().getStroke().getLineDashOffset();
      feature.setStyle(
        new Style({
          stroke: new Stroke({
            color: 'rgba(255,255,255,1)',
            width: 8,
            lineDash: [20, 30], // 虚线模式
            lineDashOffset: lineDashOffset - 0.2 // 可以控制移动的速度,(上负下正的方向移动)
          })
        })
      );
    }
  });
},