二十四、openlayers官网示例Custom Interactions——自定义交互实现在地图上移动、拖拽feature

官网demo地址:

Custom Interactions

这个示例介绍了如何在地图上自定义一个交互实现在地图上拖拽、移动要素。

首先是加载了三个要素到地图上,一个点、一个多边形、一条线。

const pointFeature = new Feature(new Point([0, 0]));

      const lineFeature = new Feature(
        new LineString([
          [-1e7, 1e6],
          [-1e6, 3e6],
        ])
      );

      const polygonFeature = new Feature(
        new Polygon([
          [
            [-3e6, -1e6],
            [-3e6, 1e6],
            [-1e6, 1e6],
            [-1e6, -1e6],
            [-3e6, -1e6],
          ],
        ])
      );

  new VectorLayer({
       source: new VectorSource({
          features: [pointFeature, lineFeature, polygonFeature],
        }),
        style: {
          "icon-src": "data/icon.png",
          "icon-opacity": 0.95,
          "icon-anchor": [0.5, 46], //设置图标锚点的位置  
          "icon-anchor-x-units": "fraction", //指定锚点的水平单位是比例值
          "icon-anchor-y-units": "pixels", //指定锚点的垂直单位是像素值
          "stroke-width": 3,
          "stroke-color": [255, 0, 0, 1],
          "fill-color": [0, 0, 255, 0.6],
        },
    }),

然后创建了一个类继承原本的PointerInteraction,将四个事件作为参数传递给PointerInteraction。来处理事件逻辑。

class Drag extends PointerInteraction {
    constructor() {
        super({
            handleDownEvent: handleDownEvent, //按下事件
            handleDragEvent: handleDragEvent, //拖动事件
            handleMoveEvent: handleMoveEvent, //移动事件
            handleUpEvent: handleUpEvent, //释放事件
        });
        //存储鼠标点击时的坐标
        this.coordinate_ = null;

        //用于存储鼠标悬停在要素上时的光标样式
        this.cursor_ = "pointer";

        //存储被拖拽的要素  
        this.feature_ = null;

        //存储之前的光标样式,以便恢复
        this.previousCursor_ = undefined;
    }


}

可以看下源码中PointerInteraction的定义。

这里移动要素用了一个geometry.translate()方法,如果我们自己写方法来完成移动的话会比较麻烦。

/**
* @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.
*/
function handleDragEvent(evt) {
    //计算鼠标拖动的位移
    const deltaX = evt.coordinate[0] - this.coordinate_[0];
    const deltaY = evt.coordinate[1] - this.coordinate_[1];
    //平移被拖拽要素的几何图形
    const geometry = this.feature_.getGeometry();
    geometry.translate(deltaX, deltaY);
    //更新存储的坐标为当前鼠标的位置
    this.coordinate_[0] = evt.coordinate[0];
    this.coordinate_[1] = evt.coordinate[1];
}

重新定义了一个Drag类,我放在了utils下的Drag.js中便于多次使用。

import Drag from '@/utils/Drag'
const map = new Map({
     interactions: defaultInteractions().extend([new Drag()]),
})

完整代码:

utils/Drag.js:

import {
    Pointer as PointerInteraction,
} from "ol/interaction.js";
class Drag extends PointerInteraction {
    constructor() {
        super({
            handleDownEvent: handleDownEvent, //按下事件
            handleDragEvent: handleDragEvent, //拖动事件
            handleMoveEvent: handleMoveEvent, //移动事件
            handleUpEvent: handleUpEvent, //释放事件
        });
        //存储鼠标点击时的坐标
        this.coordinate_ = null;

        //用于存储鼠标悬停在要素上时的光标样式
        this.cursor_ = "pointer";

        //存储被拖拽的要素  
        this.feature_ = null;

        //存储之前的光标样式,以便恢复
        this.previousCursor_ = undefined;
    }


}

/**
         * @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.
         * @return {boolean} `true` to start the drag sequence.
         */

function handleDownEvent(evt) {
    const map = evt.map;
    // 在地图上检测鼠标点击的位置是否有要素,如果有,则存储要素和点击位置的坐标
    const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
        return feature;
    });

    if (feature) {
        this.coordinate_ = evt.coordinate;
        this.feature_ = feature;
    }

    return !!feature;
}
/**
* @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.
*/
function handleDragEvent(evt) {
    //计算鼠标拖动的位移
    const deltaX = evt.coordinate[0] - this.coordinate_[0];
    const deltaY = evt.coordinate[1] - this.coordinate_[1];
    //平移被拖拽要素的几何图形
    const geometry = this.feature_.getGeometry();
    geometry.translate(deltaX, deltaY);
    //更新存储的坐标为当前鼠标的位置
    this.coordinate_[0] = evt.coordinate[0];
    this.coordinate_[1] = evt.coordinate[1];
}
/**
 * @param {import("../src/ol/MapBrowserEvent.js").default} evt Event.
 */
function handleMoveEvent(evt) {
    if (this.cursor_) {
        const map = evt.map;
        const feature = map.forEachFeatureAtPixel(
            evt.pixel,
            function (feature) {
                return feature;
            }
        );
        //检测鼠标移动到的要素,如果有要素则改变光标样式。
        const element = evt.map.getTargetElement();
        if (feature) {
            if (element.style.cursor != this.cursor_) {
                this.previousCursor_ = element.style.cursor;
                element.style.cursor = this.cursor_;
            }
            //如果鼠标移出要素,则恢复之前的光标样式
        } else if (this.previousCursor_ !== undefined) {
            element.style.cursor = this.previousCursor_;
            this.previousCursor_ = undefined;
        }
    }
}
/**
 * @return {boolean} `false` to stop the drag sequence.
 */
//重置存储的坐标和要素,表示拖拽序列结束
function handleUpEvent() {
    this.coordinate_ = null;
    this.feature_ = null;
    return false;
}
export default Drag

.vue文件:

<template>
  <div class="box">
    <h1>自定义工具</h1>
    <div id="map"></div>
  </div>
</template>

<script>
import Feature from "ol/Feature.js";
import Map from "ol/Map.js";
import View from "ol/View.js";
import { LineString, Point, Polygon } from "ol/geom.js";
import { OGCMapTile, Vector as VectorSource } from "ol/source.js";
import {
    defaults as defaultInteractions,
} from "ol/interaction.js";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer.js";
import Drag from '@/utils/Drag'
export default {
  name: "",
  components: {},
  data() {
    return {
      map: null,
    };
  },
  computed: {},
  created() {},
  mounted() {
    this.addfeatureToMap();
  },
  methods: {
    addfeatureToMap() {
      const pointFeature = new Feature(new Point([0, 0]));

      const lineFeature = new Feature(
        new LineString([
          [-1e7, 1e6],
          [-1e6, 3e6],
        ])
      );

      const polygonFeature = new Feature(
        new Polygon([
          [
            [-3e6, -1e6],
            [-3e6, 1e6],
            [-1e6, 1e6],
            [-1e6, -1e6],
            [-3e6, -1e6],
          ],
        ])
      );
      const map = new Map({
        interactions: defaultInteractions().extend([new Drag()]),
        layers: [
          new TileLayer({
            source: new OGCMapTile({
              url: "https://maps.gnosis.earth/ogcapi/collections/NaturalEarth:raster:HYP_HR_SR_OB_DR/map/tiles/WebMercatorQuad",
              crossOrigin: "",
            }),
          }),
          new VectorLayer({
            source: new VectorSource({
              features: [pointFeature, lineFeature, polygonFeature],
            }),
            style: {
              "icon-src": "data/icon.png",
              "icon-opacity": 0.95,
              "icon-anchor": [0.5, 46], //设置图标锚点的位置  
              "icon-anchor-x-units": "fraction", //指定锚点的水平单位是比例值
              "icon-anchor-y-units": "pixels", //指定锚点的垂直单位是像素值
              "stroke-width": 3,
              "stroke-color": [255, 0, 0, 1],
              "fill-color": [0, 0, 255, 0.6],
            },
          }),
        ],
        target: "map",
        view: new View({
          center: [0, 0],
          zoom: 2,
        }),
      });
    },
  },
};
</script>

<style lang="scss" scoped>
#map {
  width: 100%;
  height: 500px;
}
.box {
  height: 100%;
}

#info {
  width: 100%;
  height: 24rem;
  overflow: scroll;
  display: flex;
  align-items: baseline;
  border: 1px solid black;
  justify-content: flex-start;
}
</style>
相关推荐
我要洋人死34 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#