OpenLayers 的核心組件是地图(old/Map)

2 篇文章 0 订阅

1.安装

npm i ol -S

2.介绍

OpenLayers 的核心组件是地图 ( ol/Map)。它被渲染到一个target容器(例如div网页上包含地图的元素)。所有地图属性都可以在构建时进行配置,也可以使用 setter 方法进行配置,例如setTarget().

地图不负责地图的中心、缩放级别和投影等事项。相反,这些是ol/View实例的属性。

为了获取层的远程数据,OpenLayers 使用ol/source/Source子类。这些可用于 OpenStreetMap 或 Bing 等免费和商业地图切片服务、WMS 或 WMTS 等 OGC 源,以及 GeoJSON 或 KML 等格式的矢量数据。

layer是来自source. OpenLayers 有四种基本类型的层:

  • ol/layer/Tile- 渲染在按特定分辨率的缩放级别组织的网格中提供平铺图像的源。
  • ol/layer/Image- 渲染以任意范围和分辨率提供地图图像的源。
  • ol/layer/Vector- 在客户端渲染矢量数据。
  • ol/layer/VectorTile- 渲染作为矢量图块提供的数据

3.使用 

 

        话不说多,直接贴代码,这里面使用了Vue3,Element UI

中国JSON数据:areaGeo参数【js/Map/china.json · 梦_阿飞/allStaticResources - Gitee.com

河南JSON数据:areaCity参数【js/Map/city.json · 梦_阿飞/allStaticResources - Gitee.com

渲染数据:polymerization 【js/Map/polymerization.json · 梦_阿飞/allStaticResources - Gitee.com】 

<template>
  <div class="MonitoringData">
    <div id="Map" ref="map"></div>
    <div id="popup" class="ol-popup">
      <div id="popup-closer" class="ol-popup-closer">X</div>
      <div id="popup-detail" class="ol-popup-detail">查看详情</div>
      <div id="popup-content" class="popup-content">
      </div>
    </div>
    <div class="map-left">
      <div class="text">(仅支持郑州,开封,尉氏..)</div>
      <div class="flexbox">
        <el-input v-model="form.input" placeholder="请输入城市名" clearable style="width:150px;margin-right:15px;" />
        <el-button type="primary" @click="look">查询</el-button>
      </div>
      <div class="list">
        <li v-for="(item,index) in form.list " :key='index'>
          <div class="fx-space-between-center li">
            <div>{{item.name}}</div>
            <div>{{item.record}}</div>
          </div>
          <div class="text-li">{{item.text}}</div>
        </li>
      </div>
    </div>
    <div class="model fx-center" v-show="modelSatus.status">
      <div class="">
        <div>我是无情的白色弹窗</div>
        <el-button type="primary" @click="modelSatus.status=false">关闭</el-button>
      </div>
    </div>
  </div>
</template>
<script>
import "ol/ol.css";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Cluster from "ol/source/Cluster";
import XYZ from "ol/source/XYZ";
import { Map, View, Feature, Overlay } from "ol";
import { Style, Stroke, Text, Fill, Circle } from "ol/style";
import { Polygon, MultiPolygon, Point } from "ol/geom";
import { defaults as defaultControls } from "ol/control";
import { fromLonLat } from "ol/proj";
import areaGeo from "@/utils/china.json";
import areaCity from "@/utils/city.json";
import polymerization from "@/utils/polymerization.json";
import { onMounted, reactive } from "vue";
export default {
  name: "MapData",
  setup() {
    let map = null;
    let areaLayer = null;
    let popupData = null;
    let modelSatus = reactive({
      status: false,
    });
    let form = reactive({
      input: "",
      list: polymerization.points,
    });
    const initMap = () => {
      map = new Map({
        target: "Map",
        controls: defaultControls({
          zoom: true,
        }).extend([]),
        layers: [
          new TileLayer(
            {
              source: new XYZ({
                url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}",
              }),
            },
            { zoomOffset: 1 }
          ),
        ],
        view: new View({
          // center: fromLonLat([108.522097, 37.272848]),
          center: fromLonLat([115.153576, 32.287459]),
          zoom: 7,
          maxZoom: 15,
          minZoom: 2,
        }),
      });
    };
    /**
     * Popup 弹窗
     */
    const addPopup = () => {
      // 使用变量存储弹窗所需的 DOM 对象
      var container = document.getElementById("popup");
      var closer = document.getElementById("popup-closer");
      var content = document.getElementById("popup-content");
      var detail = document.getElementById("popup-detail");
      // 创建一个弹窗 Overlay 对象
      const overlay = new Overlay({
        element: container, //绑定 Overlay 对象和 DOM 对象的
        autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
        autoPanAnimation: {
          duration: 250, //自动平移效果的动画时间 9毫秒
        },
      });
      // 将弹窗添加到 map 地图中
      map.addOverlay(overlay);
      /**
       * 添加单击响应函数来处理弹窗动作
       */
      map.on("click", function (evt) {
        var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
          return feature;
        });
        if (feature) {
          let value = feature.get("features");
          popupData = value[0].values_;
          if (value.length < 2) {
            content.innerHTML = `
                <p style="text-align: center;font-size:18px;font-weight:bold;">${popupData.name}-${popupData.value}</p>
                <div style="display:flex;justify-content:space-between;">
                  <div><span>攻击:</span>${popupData.attack}</div>
                  <div><span>法伤:</span>${popupData.magic}</div>
                </div>
                <div style="display:flex;justify-content:space-between;">
                  <div><span>暴击:</span>${popupData.crit}</div>
                  <div><span>战绩:</span>${popupData.record}</div>
                </div>
                <div>${popupData.text}</div>
               `;
            overlay.setPosition(evt.coordinate); //把 overlay 显示到指定的 x,y坐标
          } else {
            overlay.setPosition(undefined);
          }
        } else {
          overlay.setPosition(undefined);
        }
      });
      /**
       * 为弹窗添加一个响应关闭的函数
       */
      closer.onclick = function () {
        overlay.setPosition(undefined);
        closer.blur();
        return false;
      };
      detail.onclick = function () {
        modelSatus.status = true;
        overlay.setPosition(undefined);
      };
    };
    /**
     * 设置区域
     */
    const addArea = (geo = [], city = []) => {
      if (geo.length == 0) return false;
      let areaFeature = null; // 国家
      let provinceData = null; // 城市
      // 设置图层
      areaLayer = new VectorLayer({
        source: new VectorSource({
          features: [],
        }),
      });
      // 添加图层
      map.addLayer(areaLayer);
      //  ---国家
      geo.forEach((g) => {
        let lineData = g.features[0];
        if (lineData.geometry.type == "MultiPolygon") {
          areaFeature = new Feature({
            geometry: new MultiPolygon(lineData.geometry.coordinates).transform(
              "EPSG:4326",
              "EPSG:3857"
            ),
          });
        } else if (lineData.geometry.type == "Polygon") {
          areaFeature = new Feature({
            geometry: new Polygon(lineData.geometry.coordinates).transform(
              "EPSG:4326",
              "EPSG:3857"
            ),
          });
        }
      });
      // 渲染国家---
      areaFeature.setStyle(
        new Style({
          // fill: new Fill({ color: "#4e98f444" }),
          stroke: new Stroke({
            width: 3,
            color: [71, 137, 227, 1],
          }),
        })
      );
      areaLayer.getSource().addFeatures([areaFeature]);
      //  城市
      city[0].features.forEach((item) => {
        let lineData = item;
        provinceData = new Feature({
          geometry: new MultiPolygon(lineData.geometry.coordinates).transform(
            "EPSG:4326",
            "EPSG:3857"
          ),
        });
        provinceData.setStyle(
          new Style({
            stroke: new Stroke({
              width: 2,
              color: "blue",
            }),
          })
        );
        //需要s设置属性进去,然后在需要的时候才可以get到
        provinceData.set("name2", lineData.properties.name);
        areaLayer.getSource().addFeatures([provinceData]);
      });
      //
    };
    // 聚合
    const addCluster = (clusterData, points) => {
      let source = new VectorSource();
      let clusterSource = new Cluster({
        distance: parseInt(20, 10),
        source: source,
      });
      let layers = new VectorLayer({
        source: clusterSource,
        style: clusterStyle.call(this),
      });
      map.addLayer(layers);

      for (let index = 0; index < clusterData.length; index++) {
        const ele = clusterData[index];
        points.forEach((e) => {
          if (ele.name == e.name) {
            let point = fromLonLat(ele.center);
            var f = new Feature({
              geometry: new Point(point),
            });
            for (let key in e) {
              f.set(key, e[key]);
            }
            source.addFeature(f);
          }
        });
      }
    };
    const clusterStyle = () => {
      return (feature) => {
        var total = 0;
        var name = null;
        feature.get("features").forEach((value) => {
          total += value.get("value");
          name = value.get("name");
        });
        var size = feature.get("features").length;
        var style = new Style({
          image: new Circle({
            fill: new Fill({
              color: "red",
            }),
            stroke: new Stroke({
              color: "red",
              width: size != 1 ? Number(12.25) : Number(1),
            }),
            radius: size != 1 ? 10 : 5,
          }),
          text: new Text({
            text: size != 1 ? total.toString() : name, //lineData.properties.name
            fill: new Fill({
              color: size != 1 ? "#fff" : "#303133",
            }),
            font:
              size != 1
                ? "12px Microsoft YaHei bold"
                : "18px Microsoft YaHei bold",
            offsetY: size != 1 ? 0 : 20,
          }),
        });
        return style;
      };
    };
    const look = () => {
      //
      let conter = polymerization.clusterData.filter(
        (e) => e.name == form.input
      );
      if (form.input == "") {
        form.list = polymerization.points;
      } else {
        form.list = polymerization.points.filter((e) => e.name == form.input);
      }
      let view = map.getView();
      if (conter.length > 0) {
        view.setZoom(18);
        view.animate({
          center: fromLonLat(conter[0].center),
          duration: 3,
        });
      } else {
        view.setZoom(7);
        view.animate({
          center: fromLonLat([115.153576, 32.287459]),
          duration: 3,
        });
      }
    };
    onMounted(() => {
      initMap(); //初始化地图方法
      addArea(areaGeo, areaCity); //添加区域图层方法
      addCluster(polymerization.clusterData, polymerization.points); //数据聚合
      addPopup(); //弹窗
    });
    return {
      initMap,
      addArea,
      map,
      areaLayer,
      addCluster,
      clusterStyle,
      addPopup,
      popupData,
      modelSatus,
      look,
      form,
    };
  },
};
</script>
<style scoped lang="scss">
.MonitoringData {
  height: 100%;
  position: relative;
  .model {
    position: absolute;
    height: 100%;
    width: 100%;
    background: #fff;
    bottom: 0;
    left: 0;
    text-align: center;
  }
  .map-left {
    width: 300px;
    height: 70%;
    position: absolute;
    background: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    position: absolute;
    top: 20px;
    left: 20px;
    overflow: auto;
    padding: 10px;
    .text {
      font-size: 12px;
      color: #cccccc;
      padding-bottom: 10px;
    }
    .list {
      width: 100%;
      margin-top: 15px;
      li {
        border-bottom: 1px solid #e3e3e3;
        padding: 5px 0;
      }
      .li {
        width: 100%;
        font-size: 16px;
        color: #868585;
        padding-bottom: 5px;
      }
      .text-li {
        background: linear-gradient(red, green, blue);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
      }
    }
  }
}
#Map {
  width: 100%;
  height: 100%;

  .ol-popup {
    position: absolute;
    background-color: white;
    -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
    filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #cccccc;
    bottom: 12px;
    left: -50px;
  }
  .ol-popup:after,
  .ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
  }
  .ol-popup:after {
    border-top-color: white;
    border-width: 10px;
    left: 48px;
    margin-left: -10px;
  }
  .ol-popup:before {
    border-top-color: #cccccc;
    border-width: 11px;
    left: 48px;
    margin-left: -11px;
  }
  .ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
    cursor: pointer;
  }
  .ol-popup-detail {
    text-decoration: none;
    position: absolute;
    top: 4px;
    left: 8px;
    cursor: pointer;
  }
  .popup-content {
    width: 400px;
  }
}
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值