一、安装

1、官网

(1)官网文档

        OpenLayers - Welcome

(2)参考文档

        http://linwei.xyz/ol3-primer/ch01/index.html

(3)参考示例

        http://develop.smaryun.com:81/API/JS/OL3InterfaceDemo/index.htm

2、安装openlayers
// 安装最新版本
npm i ol

// 安装指定版本,例如7.0.0
npm i ol@7.0.0

// 注意:如果npm无法正常安装,使用cnpm安装

// 安装最新版本
cnpm i ol

// 安装指定版本,例如7.0.0
cnpm i ol@7.0.0

二、配置

1、模块引入

        创建一个名为ol.js的文件,引入ol中需要使用的模块

// ----------------<<CSS文件>>----------------
import "ol/ol.css";

// ----------------<<常用模块>>----------------
import Map from "ol/Map.js";
// import { XYZ } from "ol/source.js";
import XYZ from "ol/source/XYZ";
import View from "ol/View.js";
import Fill from 'ol/style/Fill.js'
import Point from 'ol/geom/Point.js';
import Style from 'ol/style/Style.js';
import Circle from 'ol/style/Circle.js';
import Stroke from 'ol/style/Stroke.js';
import Feature from 'ol/Feature.js';
import TileLayer from "ol/layer/Tile.js";
import LineString from 'ol/geom/LineString.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import { DoubleClickZoom } from 'ol/interaction.js';

// ----------------<<其他模块>>----------------
import OSM from "ol/source/OSM.js";
import WFS from 'ol/format/WFS.js';
import Icon from 'ol/style/Icon.js';
import Tile from 'ol/layer/Tile.js';
import WMTS from 'ol/source/WMTS.js';
import Image from 'ol/layer/Image.js';
import { buffer } from 'ol/extent.js';
import Overlay from 'ol/Overlay.js';
import GeoJSON from 'ol/format/GeoJSON.js';
import TileWMS from 'ol/source/TileWMS.js';
import ImageWMS from 'ol/source/ImageWMS.js';
import ImageStyle from 'ol/style/Image.js';
import ZoomToExtent from 'ol/control/ZoomToExtent.js';
import { transform, fromLonLat, toLonLat } from 'ol/proj.js'


const ols = {
  Map: Map,
  XYZ: XYZ,
  View: View,
  OSM: OSM,
  WFS: WFS,
  Icon: Icon,
  Tile: Tile,
  WMTS: WMTS,
  Fill: Fill,
  Point: Point,
  Style: Style,
  Image: Image,
  buffer: buffer,
  Circle: Circle,
  Stroke: Stroke,
  Feature: Feature,
  Overlay: Overlay,
  GeoJSON: GeoJSON,
  TileWMS: TileWMS,
  ImageWMS: ImageWMS,
  toLonLat: toLonLat,
  TileLayer: TileLayer,
  transform: transform,
  fromLonLat: fromLonLat,
  ImageStyle: ImageStyle,
  LineString: LineString,
  VectorLayer: VectorLayer,
  VectorSource: VectorSource,
  ZoomToExtent: ZoomToExtent,
  DoubleClickZoom: DoubleClickZoom,
}

export default ols

三、地图渲染 & 模型添加

1、初始化地图
<template>
  <div id="openLayers">
    <!-- map -->
    <div id="openLayerContainer"></div>
  </div>
</template>

<script>
// 引入模块文件
import ols from "../js/ol";

export default {
  name: "",
  components: {},
  props: {},
  data() {
    return {
    // 点位ID
    pointId:0,
    // 所有点位坐标集合
    pointCoord:[],
    // 所有点位图层集合-清除使用
    pointVector:[],
    // 线条ID
    lineId:0,
    // 所有线条图层集合-清除使用
    lineVector:[],
    }
  },
  computed: {},
  created() {},
  mounted() {
    this.initMap();
  },
  methods: {
    // 初始化地图
    initMap() {
      const tileMap = new ols.TileLayer({
        source: new ols.XYZ({
          // 官网在线地图(可以添加在线和离线地图)
          url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
        }),
      });

      // 初始化地图
      window.openLayers = new ols.Map({
        layers: [tileMap], // 直接在配置上加载
        target: "openLayerContainer", // 地图容器
        view: new ols.View({
          projection: "EPSG:4326", // 坐标系
          center: [110, 30], // 地图中心点
          zoom: 6, // 默认缩放比例
          minZoom: 2, // 缩放最小级别 2
          maxZoom: 20, // 缩放最大级别 20
        }),
      });

      // 清除默认的左键双击缩放
      const dblClickInteraction = openLayers
        .getInteractions()
        .getArray()
        .find((interaction) => {
          return interaction instanceof ols.DoubleClickZoom;
        });
      openLayers.removeInteraction(dblClickInteraction);

      // 左键双击
      openLayers.on("dblclick", (e) => {
        // 添加点位
        this.addPoint(e.coordinate);

        // 保存点位坐标位置
        this.pointCoord.push(e.coordinate);
      });
    },
  },
};
</script>

<style lang="less" scoped>
#openLayers {
  width: 100%;
  height: 100vh;

  #openLayerContainer {
    width: 100%;
    height: 100%;
  }
}
</style>

2、添加模型
(1)官网示例

        每一个点位和线条都会创建一个图层

        ① 添加、清除点位
// 添加点位
addPoint(coordinate) {
  // 创建点位
  const point = new ols.Feature({
    geometry: new ols.Point([coordinate[0], coordinate[1]]),
  });

  // 设置点位id
  point.setId(this.pointId);

  // 设置点位样式
  point.setStyle(
    new ols.Style({
      // 形状
      image: new ols.Circle({
        radius: 3,
        fill: new ols.Fill({
          color: "rgba(255,0,0,1)",
        }),
      }),
    })
  );

  //实例化一个矢量图层Vector作为绘制层
  const source = new ols.VectorSource({
    features: [point],
  });

  //创建一个图层
  const vector = new ols.VectorLayer({
    source: source,
  });

  //将绘制层添加到地图容器中
  openLayers.addLayer(vector);

  // 图层中添加点
  vector.getSource().addFeature(point);

  //存储图层
  this.pointVector.push(vector);

  // 点位id加1,下次创建点位使用
  this.pointId++;
},


// 清除点位
clearPoint() {
  // 移除点位
  this.pointCoord.forEach((item) => {
    item
      .getSource()
      .getFeatures()
      .forEach((feature) => {
        item.getSource().removeFeature(feature);
      });

    // 从地图容器重删除绘制层
    openLayers.removeLayer(item);
  });

  // 点位ID
  this.pointId = 0;
  // 所有点位坐标集合
  this.pointCoord = [];
  // 所有点位图层集合-清除使用
  this.pointVector = [];
},

        ② 添加、清除线条
// 添加线条
addLine() {
  if (!this.pointCoord || this.pointCoord.length < 2) {
    this.$message.warning("至少需要2个点");
  } else {
    // 创建线条
    const line = new ols.Feature({
      geometry: new ols.LineString(this.pointCoord),
    });

    // 设置线条id
    line.setId(this.lineId);

    // 设置线条样式
    line.setStyle(
      new ols.Style({
        // 边线
        stroke: new ols.Stroke({
          color: "#ffffff",
          width: 2,
        }),
      })
    );

    // 实例化一个矢量图层Vector作为绘制层
    const source = new ols.VectorSource({
      features: [line],
    });

    // 创建一个图层
    const vector = new ols.VectorLayer({
      source: source,
    });

    // 将绘制图层添加到地图容器中
    openLayers.addLayer(vector);

    // 图层中添加线
    vector.getSource().addFeature(line);

    // 存储图层
    this.lineVector.push(vector);

    // 线条id加1,下次创建线条使用
    this.lineId++;
  }
},


// 清除线条
clearLine() {
  // 移除线条
  this.lineVector.forEach((item) => {
    item
      .getSource()
      .getFeatures()
      .forEach((feature) => {
        item.getSource().removeFeature(feature);
      });

    // 从地图容器重删除绘制层
    openLayers.removeLayer(item);
  });

  // 线条ID
  this.lineId = 0;
  // 所有线条图层集合-清除使用
  this.lineVector = [];
},

(2)个人示例

        点位和线条各一个图层

        ① 添加、清除点位
// 添加点位
addPoint(coordinate) {
  if (!this.pointVector) {
    //实例化一个矢量图层Vector作为绘制层
    const source = new ols.VectorSource();
    this.pointVector = new ols.VectorLayer({
      source: source,
    });
  }

  // 创建点位
  const point = new ols.Feature({
    geometry: new ols.Point([coordinate[0], coordinate[1]]),
  });

  // 设置点位id
  point.setId(this.pointId);

  // 设置点位样式
  point.setStyle(
    new ols.Style({
      // 形状
      image: new ols.Circle({
        radius: 3,
        fill: new ols.Fill({
          color: "rgba(255,0,0,1)",
        }),
      }),
    })
  );

  //将绘制层从地图容器中移除
  openLayers.removeLayer(this.pointVector);
  //将绘制层添加到地图容器中
  openLayers.addLayer(this.pointVector);
  //更新地图
  openLayers.updateSize();

  // 图层中添加点位
  this.pointVector.getSource().addFeature(point);

  // 存储点位
  this.pointArr.push(point);

  // 点位id加1,下次创建点位使用
  this.pointId++;
},


// 清除点位
clearPoint() {
  // 移除点位
  this.pointArr.forEach((item) => {
    this.pointVector.getSource().removeFeature(item);
  });

  // 从地图容器中删除绘制层
  openLayers.removeLayer(this.pointVector);

  // 点位ID
  (this.pointId = 0),
    // 所有点位坐标集合
    (this.pointCoord = []);
  // 所有点位图层集合-清除使用
  this.pointVector = [];
},

        ② 添加、清除线条
// 添加线条
addLine() {
  if (!this.pointCoord || this.pointCoord.length < 2) {
    this.$message.warning("至少需要2个点");
  } else {
    //实例化一个矢量图层Vector作为绘制层
    if (!this.lineVector) {
      const source = new ols.VectorSource();
      this.lineVector = new ols.VectorLayer({
        source: source,
      });
    }

    // 创建线条
    const line = new ols.Feature({
      geometry: new ols.LineString(this.pointCoord),
    });

    // 设置线条id
    line.setId(this.lineId);

    // 设置线条样式
    line.setStyle(
      new ols.Style({
        // 边线
        stroke: new ols.Stroke({
          color: "#ffffff",
          width: 2,
        }),
      })
    );

    //将绘制层从地图容器中移除
    openLayers.removeLayer(this.lineVector);
    //将绘制层添加到地图容器中
    openLayers.addLayer(this.lineVector);
    //更新地图
    openLayers.updateSize();

    // 图层中添加线
    this.lineVector.getSource().addFeature(line);

    // 存储线条
    this.lineArr.push(line);

    // 线条id加1,下次创建线条使用
    this.lineId++;
  }
},


// 清除线条
clearLine() {
  // 移除线条
  this.lineArr.forEach((item) => {
    this.lineVector.getSource().removeFeature(item);
  });

  // 从地图容器中删除绘制层
  openLayers.removeLayer(this.lineVector);

  // 线条ID
  this.lineId = 0;
  // 所有线条图层集合-清除使用
  this.lineVector = [];
},

四、其他操作

1、鼠标事件
// 清除默认的左键双击缩放
const dblClickInteraction = openLayers
  .getInteractions()
  .getArray()
  .find((interaction) => {
    return interaction instanceof ols.DoubleClickZoom;
  });
openLayers.removeInteraction(dblClickInteraction);

//左键单击
openLayers.on("singleclick", (e) => {
  console.log("左键单击", e);
});

// 左键双击
openLayers.on("dblclick", (e) => {
	console.log("左键双击", e);
});

// 单击(左右键)
openLayers.on("click", (e) => {
  console.log("单击", e);
});

// 鼠标移动
openLayers.on("pointermove", (e) => {
  console.log("鼠标移动", e);
});

// 鼠标拖拽
openLayers.on("pointerdrag", (e) => {
  console.log("鼠标拖拽", e);
});

// 地图移动事件
openLayers.on("moveend", (e) => {
  console.log("地图移动事件", e);
});

五、完整案例

1、代码(ol@6.15.1)
<template>
  <div class="openLayers">
    <!-- map -->
    <div id="openLayerContainer"></div>
  </div>
</template>

<script>
// ----------------<<CSS文件>>----------------
import "ol/ol.css";
import imgUrl from "@assets/img/car.png"; // 引入图片

// ----------------<<常用模块>>----------------
import Map from "ol/Map.js";
import XYZ from "ol/source/XYZ.js";
import View from "ol/View.js";
import TileLayer from "ol/layer/Tile.js";
import { fromLonLat, transform } from "ol/proj.js";
import styleCircle from "ol/style/Circle.js";
import Style from "ol/style/Style.js";
import Icon from "ol/style/Icon.js";
import Stroke from "ol/style/Stroke.js"; // 线条颜色
import Fill from "ol/style/Fill.js"; // 填充色
import Feature from "ol/Feature.js";
import VectorSource from "ol/source/Vector.js";
import VectorLayer from "ol/layer/Vector.js";
import { LineString, Point, Circle, LinearRing, Polygon } from "ol/geom";

export default {
  name: "",
  components: {},
  props: {},
  data() {
    return {
      // 地图对象
      openLayers: null,
      // 绘制层
      sourceVector: null,
      // 图层
      layerVector: null,
      // 位置信息
      position: {
        localDoa: 0, // 方位
        localROA: 30, // 夹角
        localHeight: 0, // 高度
        localLon: 130, // 经度
        localLat: 30, // 纬度
      },
      // timer
      timer: null,
    };
  },
  computed: {},
  created() {},
  mounted() {
    this.queryLocalPos(); // 获取实时位置
    this.initMap();
    this.changeTowardParams();
  },
  methods: {
    // ---------------------<<请求>>---------------------
    queryLocalPos() {
      this.$API.queryLocalPosRequest().then((res) => {
        if (res.code == 1000) {
          this.position = res.data;

          // this.initMap();
        }
      });
    },

    // ---------------------<<地图>>---------------------
    // 初始化地图
    initMap() {
      const tileMap = new TileLayer({
        source: new XYZ({
          // 官网在线地图(可以添加在线和离线地图)
          // url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
          url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
        }),
      });

      // 初始化地图;
      window.openLayers = new Map({
        target: "openLayerContainer", // 地图容器
        layers: [tileMap], // 直接在配置上加载
        view: new View({
          projection: "EPSG:3857", // 坐标系
          center: fromLonLat([this.position.localLon, this.position.localLat]),
          zoom: 9, // 默认缩放比例
          minZoom: 5, // 缩放最小级别 1
          maxZoom: 10, // 缩放最大级别 20
        }),
      });

      // 画圆
      this.drawCircle(this.position, 50000);

      // 设置地图中心点-定位功能
      // openLayers.getView().setCenter(fromLonLat([this.position.localLon, this.position.localLat]));

      // openLayers.on("pointerdrag", function (e) {
      //   console.log("鼠标拖拽", e);
      // });

      // openLayers.on("singleclick", function (e) {
      //   console.log("左键单击", e);
      //   // const coordinate = transform(e.coordinate, "EPSG:3857", "EPSG:4326");
      // });

      // openLayers.on("click", function (e) {
      //   console.log("鼠标点击", e);
      //   // const coordinate = transform(e.coordinate, "EPSG:3857", "EPSG:4326");
      // });

      // // 清除默认的左键双击缩放
      // const dblClickInteraction = openLayers
      //   .getInteractions()
      //   .getArray()
      //   .find((interaction) => {
      //     return interaction instanceof ols.DoubleClickZoom;
      //   });
      // openLayers.removeInteraction(dblClickInteraction);

      // openLayers.on("dblclick", function (e) {
      //   console.log("左键双击", e);
      //   // const coordinate = transform(e.coordinate, "EPSG:3857", "EPSG:4326");
      // });
    },

    // 画圆
    drawCircle(ps, range) {
      var newCircle = new Feature({
        geometry: new Circle(fromLonLat([ps.localLon, ps.localLat]), range),
      });

      // 设置id
      newCircle.setId("newCircle");

      newCircle.setStyle(
        new Style({
          //填充色
          fill: new Fill({
            color: "rgba(255,228,181,0.5)",
          }),
          //边线颜色
          stroke: new Stroke({
            color: "#FE9E28",
            width: 3,
          }),
          //形状
          image: new styleCircle({
            radius: 7,
            fill: new Fill({
              color: "rgba(255,228,181,0.5)",
            }),
          }),
        })
      );

      //实例化一个矢量图层Vector作为绘制层
      this.sourceVector = new VectorSource({
        features: [newCircle],
      });

      //创建一个图层
      this.layerVector = new VectorLayer({
        source: this.sourceVector,
      });

      //将图层添加到地图容器中
      openLayers.addLayer(this.layerVector);

      // 添加中心点
      this.drawPoint({
        lon: ps.localLon,
        lat: ps.localLat,
        angle: ps.localDoa,
      });
      // 添加扇形
      this.drawCurve(
        fromLonLat([ps.localLon, ps.localLat]),
        range,
        ps.localDoa,
        ps.localROA
      );
    },

    // 位置:origin
    // 范围:radius
    // 朝向:angle
    // 角度:range
    drawCurve(origin, radius, angle, range) {
      const feature = new Feature({
        geometry: new Polygon([this.addCurve(origin, radius, angle, range)]),
      });

      // 设置id
      feature.setId("myCurve");

      feature.setStyle(
        new Style({
          //填充色
          fill: new Fill({
            color: "rgba(255,0,0,.5)",
          }),
          //边线颜色
          stroke: new Stroke({
            color: "#FF0000",
            width: 1,
          }),
        })
      );

      this.layerVector.getSource().addFeatures([feature]);
    },
    addCurve(origin, radius, angle, range) {
      let pointList = [];
      /**
       * 添加起始点位
       */
      pointList.push(origin);
      /**
       * 开始角度
       */
      let startAngle = angle - range / 2 + 90;
      /**
       * 根据传进来的角度范围绘制
       */
      for (let i = 0; i < range; i++) {
        startAngle += 1;
        /**
         * 利用余弦计算出维度,因为在二维地图中正北方向是朝上的,同理经度有正弦可以计算出来
         */
        let lon = Math.cos((startAngle * Math.PI) / 180) * radius + origin[0];
        let lat = Math.sin((startAngle * Math.PI) / 180) * radius + origin[1];
        /**
         * 添加进数组中
         */

        pointList.push([lon, lat]);
      }
      return pointList;
    },

    // 画点
    drawPoint(ps) {
      // 创建点位
      const point = new Feature({
        geometry: new Point(fromLonLat([ps.lon, ps.lat])),
      });

      // 设置id
      point.setId("myPoint");

      // 设置点位样式
      point.setStyle(
        new Style({
          image: new Icon({
            src: imgUrl,
            scale: 0.1,
            rotation: -(ps.angle * (6.3 / 360)),
          }),
        })
      );

      // 添加到图层
      this.layerVector.getSource().addFeatures([point]);
    },

    // 重新添加所有实体
    addAll() {
      // 清除所有实体
      this.clearAll();

      // 添加所有实体
      this.drawCircle(this.position, 50000);

      // 设置地图中心点
      openLayers
        .getView()
        .setCenter(
          fromLonLat([this.position.localLon, this.position.localLat])
        );
    },

    // 清除所有
    clearAll() {
      // 删除所有feature
      this.layerVector
        .getSource()
        .getFeatures()
        .forEach((feature) => {
          this.layerVector.getSource().removeFeature(feature);
        });

      // 删除图层
      openLayers.removeLayer(this.layerVector);
    },

    // 调整方位
    changeToward(ps, range) {
      this.addAll();
    },

    // 调整方位参数
    changeTowardParams() {
      // 自动调整方位
      if (this.timer) {
        clearInterval(this.timer);
      }

      this.timer = setInterval(() => {
        if (this.position.localDoa == 360) {
          this.position.localDoa = 0;
        }
        this.position.localDoa -= 6;
      }, 500);
    },
  },
  watch: {
    position: {
      handler(newVal, oldVal) {
        this.changeToward(newVal, 50000);
      },
      deep: true,
    },
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
};
</script>

<style lang="less" scoped>
.openLayers {
  width: 100%;
  height: 100%;

  #openLayerContainer {
    width: 100%;
    height: 100%;
    background-color: #2f4f4f;
  }
}
</style>

GitHub 加速计划 / vu / vue
80
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
9e887079 [skip ci] 2 个月前
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐