openlayers 行政区域下砖、地图联动、地图动画

803 阅读1分钟

效果展示

selectArar.gif

代码实现

  • 公共方法代码
import { Tile as TileLayer } from "ol/layer";
//高德瓦片图层
const gaodeMapLayer = new TileLayer({
  source: new XYZ({
    url: "http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
  }),
  name: "高德地图",
});
//地图定位动画
function bounce(t) {
  const s = 7.5625;
  const p = 2.75;
  let l;
  if (t < 1 / p) {
    l = s * t * t;
  } else {
    if (t < 2 / p) {
      t -= 1.5 / p;
      l = s * t * t + 0.75;
    } else {
      if (t < 2.5 / p) {
        t -= 2.25 / p;
        l = s * t * t + 0.9375;
      } else {
        t -= 2.625 / p;
        l = s * t * t + 0.984375;
      }
    }
  }
  return l;
}

  • 两个地图初始化
  mounted() {
      //用同一个View实例,实现地图同步联动
    let commonView = new View({
        center: transform([104.065759, 30.657416], "EPSG:4326", "EPSG:3857"),
        zoom: 11,
        minZoom: 1,
        maxZoom: 21,
        projection: "EPSG:4326",
        rotation: 0,
      }),
      commoninteractions = defaultInteractions({
        doubleClickZoom: false, // 取消双击放大功能交互
        // dragPan: false,
        //mouseWheelZoom: false, // 取消滚动鼠标中间的滑轮交互
        // shiftDragZoom: false, // 取消shift+wheel左键拖动交互
      });
    let map = new Map({
      // 设置地图图层
      layers: [],
      // 设置显示地图的视图
      view: commonView,
      // 让id为map的div作为地图的容器
      target: "areas",
      interactions: commoninteractions,
    });
    let godeMap = new Map({
      // 设置地图图层
      layers: [gaodeMapLayer],
      // 设置显示地图的视图
      view: commonView,
      // 让id为map的div作为地图的容器
      target: "map_",
      interactions: commoninteractions,
    });
  },
  • 行政区数据拉取
  mounted() {
    this.getF(
      "https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full",
      map,
      godeMap
    );
  },
  methods:{
     async getF(url, map, godeMap) {
      let res = await axios.get(url),
        geojsonData = res.data,
        commonGeom = new GeoJSON().readFeatures(geojsonData),
        layer = layer_(commonGeom, true, {}, 1, stylFn),
        mask = layer_(commonGeom, true, {}, 1, maskStyle);
      map.addLayer(layer);
      godeMap.addLayer(mask);
      godeMap.getView().fit(mask.getSource().getExtent());
      this.addEventListenerMAP(map, godeMap);
    }
  }
  • 地图ponitmove、singleclick事件监听
   addEventListenerMAP(map, godeMap) {
      let _this = this;
      map.on("pointermove", (evt) => {
        let _this = this,
          MapLayers = map.getLayers().getArray();
        if (MapLayers.length <= 0) {
          return;
        }
        let _showLayer = MapLayers.filter((_layer) => _layer.getVisible())[0],
          _curreutFeatures = _showLayer.getSource().getFeatures(),
          pixel = map.getEventPixel(evt.originalEvent),
          hit = map.hasFeatureAtPixel(pixel);
        map.getTargetElement().style.cursor = hit ? "pointer" : "";
        map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
          let properties = feature.getProperties();
          _curreutFeatures.forEach((_feature) => {
            let _properties = _feature.getProperties();
            if (properties.adcode === _properties.adcode) {
              _feature.setStyle(() => {
                return new Style({
                  stroke: null,
                  fill: new Fill({ color: 'rgba(103, 194, 58,0.3)' }),
                  text: new Text({
                    text: properties.name,
                    textAlign: "center",
                    font: "bolder 14px PingFangSC ",
                    padding: [0, 0, 0, 0],
                    overflow: true,
                    fill: new Fill({
                      color: "#000",
                    }),
                    backgroundFill: null,
                  }),
                });
              });
            } else {
              _feature.setStyle(null);
            }
          });
        });
      });
      map.on("singleclick", (evt) => {
        map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
          let properties = feature.getProperties(),
            { adcode, level } = properties;
          console.log(properties);
          if (level !== "district") {
            _this.getNex(adcode, map, godeMap);
          }
        });
      });
    },
  • layer显示和隐藏动画
methods:{
    async getNex(adcode, map, godeMap) {
      let res = await axios.get(
          `https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${adcode}_full`
        ),
        geoData = res.data,
        Geom = new GeoJSON().readFeatures(geoData),
        layer = layer_(Geom, true, {}, 0, stylFn),
        mask = layer_(Geom, true, {}, 0, maskStyle),
        _this = this;
      //获取suoce
      this.HideLayer(map, godeMap, () => {
        _this.showLayer(map, godeMap, layer, mask);
      });
    },
     HideLayer(map, godeMap, callBack) {
      let n = 1,
        timeID,
        layer = map.getLayers().getArray()[0],
        mask = godeMap.getLayers().getArray()[1];
      console.log(mask);
      timeID = setInterval(() => {
        n = n - 0.1;
        layer.setOpacity(n);
        mask.setOpacity(n);
        if (n <= 0) {
          clearInterval(timeID);
          map.removeLayer(layer);
          godeMap.removeLayer(mask);
          callBack && callBack();
        }
      }, 100);
    },
    showLayer(map, godeMap, layer, mask, callBack) {
      map.addLayer(layer);
      godeMap.addLayer(mask);
      map.getView().fit(layer.getSource().getExtent(), {
        easing: bounce,
        duration: 1000,
      });
      let n = 0,
        timeID;
      timeID = setInterval(() => {
        n = n + 0.1;
        layer.setOpacity(n);
        mask.setOpacity(n);
        if (n >= 1) {
          clearInterval(timeID);
          callBack && callBack();
        }
      }, 100);
    },
}

性能及优化思考

1653561589(1).png

  • map.addLayer/map.removeLayer 每次都要去删除和创建layer 可以优化的方案?
  • pointermove 监听都在循环当前layer的Features和当前feature进行对比,可以否不循环对比,减少循环对比次数

有优化建议希望大家共同探讨