vue+mapbox-gl-draw 绘制矩形并添加第一个点

这篇博客介绍了如何在Mapbox Draw中自定义`draw_rectangle`模式,使得在绘制矩形时在第一个点击位置显示一个起始点。通过修改`DrawRectangle.js`文件,实现了在鼠标点击地图时创建起始点,并在移动鼠标时更新矩形坐标。在完成绘制后,将触发`draw.create`事件,创建GeoJSON特征。同时,该模式禁用了双击缩放功能,确保绘制过程不受干扰。
摘要由CSDN通过智能技术生成

添加draw组件

      let modes = MapboxDraw.modes;
      modes.draw_rectangle = DrawRectangle;
      //添加工具
      this.draw = new MapboxDraw({
        modes: modes,
        displayControlsDefault: false,
      });
      map.addControl(this.draw, "top-right");
      map.on("draw.create", this.createFeature);
      map.on("draw.delete", this.delFeature);
      map.on("draw.update", this.createFeature);
import DrawRectangle from "./DrawRectangle";

使用在点击事件调用

 this.draw.changeMode("draw_rectangle");

 MODES源码:https://github.com/mapbox/mapbox-gl-draw/blob/main/docs/MODES.md 

https://github.com/mapbox/mapbox-gl-draw/blob/main/src/constants.js

DrawRectangle.js

const doubleClickZoom = {
    enable: ctx => {
        setTimeout(() => {
            // First check we've got a map and some context.
            if (
                !ctx.map ||
                !ctx.map.doubleClickZoom ||
                !ctx._ctx ||
                !ctx._ctx.store ||
                !ctx._ctx.store.getInitialConfigValue
            )
                return;
            // Now check initial state wasn't false (we leave it disabled if so)
            if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom")) return;
            ctx.map.doubleClickZoom.enable();
        }, 0);
    },
    disable(ctx) {
        setTimeout(() => {
            if (!ctx.map || !ctx.map.doubleClickZoom) return;
            // Always disable here, as it's necessary in some cases.
            ctx.map.doubleClickZoom.disable();
        }, 0);
    }
};

const DrawRectangle = {
    // When the mode starts this function will be called.
    onSetup: function (opts) {
        const rectangle = this.newFeature({
            type: "Feature",
            properties: {},
            geometry: {
                type: "Polygon",
                coordinates: [[]]
            }
        });
        this.addFeature(rectangle);
        this.clearSelectedFeatures();
        doubleClickZoom.disable(this);
        this.updateUIClasses({ mouse: "add" });
        this.setActionableState({
            trash: true
        });
        return {
            rectangle
        };
    },
    // support mobile taps
    onTap: function (state, e) {
        // emulate 'move mouse' to update feature coords
        if (state.startPoint) this.onMouseMove(state, e);
        // emulate onClick
        this.onClick(state, e);
    },
    // Whenever a user clicks on the map, Draw will call `onClick`
    onClick: function (state, e) {
        // if state.startPoint exist, means its second click
        //change to  simple_select mode
        if (
            state.startPoint &&
            state.startPoint[0] !== e.lngLat.lng &&
            state.startPoint[1] !== e.lngLat.lat
        ) {
            this.updateUIClasses({ mouse: "pointer" });
            state.endPoint = [e.lngLat.lng, e.lngLat.lat];
            this.changeMode("simple_select", { featuresId: state.rectangle.id });
        }
        // on first click, save clicked point coords as starting for  rectangle
        const startPoint = [e.lngLat.lng, e.lngLat.lat];
        state.startPoint = startPoint;
    },
    onMouseMove: function (state, e) {
        // if startPoint, update the feature coordinates, using the bounding box concept
        // we are simply using the startingPoint coordinates and the current Mouse Position
        // coordinates to calculate the bounding box on the fly, which will be our rectangle
        if (state.startPoint) {
            state.rectangle.updateCoordinate(
                "0.0",
                state.startPoint[0],
                state.startPoint[1]
            ); //minX, minY - the starting point
            state.rectangle.updateCoordinate(
                "0.1",
                e.lngLat.lng,
                state.startPoint[1]
            ); // maxX, minY
            state.rectangle.updateCoordinate("0.2", e.lngLat.lng, e.lngLat.lat); // maxX, maxY
            state.rectangle.updateCoordinate(
                "0.3",
                state.startPoint[0],
                e.lngLat.lat
            ); // minX,maxY
            state.rectangle.updateCoordinate(
                "0.4",
                state.startPoint[0],
                state.startPoint[1]
            ); //minX,minY - ending point (equals to starting point)
        }
    },
    // Whenever a user clicks on a key while focused on the map, it will be sent here
    onKeyUp: function (state, e) {
        if (e.keyCode === 27) return this.changeMode("simple_select");
    },
    onStop: function (state) {
        doubleClickZoom.enable(this);
        this.updateUIClasses({ mouse: "none" });
        this.activateUIButton();

        // check to see if we've deleted this feature
        if (this.getFeature(state.rectangle.id) === undefined) return;

        //remove last added coordinate
        state.rectangle.removeCoordinate("0.4");
        if (state.rectangle.isValid()) {
            this.map.fire("draw.create", {
                features: [state.rectangle.toGeoJSON()]
            });
        } else {
            this.deleteFeature([state.rectangle.id], { silent: true });
            this.changeMode("simple_select", {}, { silent: true });
        }
    },
    toDisplayFeatures: function (state, geojson, display) {
        const isActivePolygon = geojson.properties.id === state.rectangle.id;
        geojson.properties.active = isActivePolygon ? "true" : "false";
        if (!isActivePolygon) return display(geojson);

        // Only render the rectangular polygon if it has the starting point
        if (!state.startPoint) return;

        return display(geojson);
    },
    onTrash: function (state) {
        this.deleteFeature([state.rectangle.id], { silent: true });
        this.changeMode("simple_select");
    },
};

export default DrawRectangle;

但是现在的问题是提出来要在点击的第一个位置绘制一个起始点,所以这是修改后的文件

DrawRectangle.js

实现的样式

const doubleClickZoom = {
    enable: ctx => {
        setTimeout(() => {
            // First check we've got a map and some context.
            if (
                !ctx.map ||
                !ctx.map.doubleClickZoom ||
                !ctx._ctx ||
                !ctx._ctx.store ||
                !ctx._ctx.store.getInitialConfigValue
            )
                return;
            // Now check initial state wasn't false (we leave it disabled if so)
            if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom")) return;
            ctx.map.doubleClickZoom.enable();
        }, 0);
    },
    disable(ctx) {
        setTimeout(() => {
            if (!ctx.map || !ctx.map.doubleClickZoom) return;
            // Always disable here, as it's necessary in some cases.
            ctx.map.doubleClickZoom.disable();
        }, 0);
    }
};

const DrawRectangle = {
    // When the mode starts this function will be called.
    onSetup: function (opts) {
        const rectangle = this.newFeature({
            type: "Feature",
            properties: {},
            geometry: {
                type: "Polygon",
                coordinates: [[]]
            }
        });
        this.addFeature(rectangle);
        this.clearSelectedFeatures();
        doubleClickZoom.disable(this);
        this.updateUIClasses({ mouse: "add" });
        this.setActionableState({
            trash: true
        });
        return {
            rectangle
        };
    },
    // support mobile taps
    onTap: function (state, e) {
        // emulate 'move mouse' to update feature coords
        if (state.startPoint) this.onMouseMove(state, e);
        // emulate onClick
        this.onClick(state, e);
    },
    // Whenever a user clicks on the map, Draw will call `onClick`
    onClick: function (state, e) {
        // if state.startPoint exist, means its second click
        //change to  simple_select mode
        if (
            state.startPoint &&
            state.startPoint[0] !== e.lngLat.lng &&
            state.startPoint[1] !== e.lngLat.lat
        ) {
            this.updateUIClasses({ mouse: "pointer" });
            state.endPoint = [e.lngLat.lng, e.lngLat.lat];
            this.changeMode("simple_select", { featuresId: state.rectangle.id });
        }
        // on first click, save clicked point coords as starting for  rectangle
        const startPoint = [e.lngLat.lng, e.lngLat.lat];
        state.startPoint = startPoint;
    },
    onMouseMove: function (state, e) {
        // if startPoint, update the feature coordinates, using the bounding box concept
        // we are simply using the startingPoint coordinates and the current Mouse Position
        // coordinates to calculate the bounding box on the fly, which will be our rectangle
        if (state.startPoint) {
            state.rectangle.updateCoordinate(
                "0.0",
                state.startPoint[0],
                state.startPoint[1]
            ); //minX, minY - the starting point
            state.rectangle.updateCoordinate(
                "0.1",
                e.lngLat.lng,
                state.startPoint[1]
            ); // maxX, minY
            state.rectangle.updateCoordinate("0.2", e.lngLat.lng, e.lngLat.lat); // maxX, maxY
            state.rectangle.updateCoordinate(
                "0.3",
                state.startPoint[0],
                e.lngLat.lat
            ); // minX,maxY
            state.rectangle.updateCoordinate(
                "0.4",
                state.startPoint[0],
                state.startPoint[1]
            ); //minX,minY - ending point (equals to starting point)
        }
    },
    // Whenever a user clicks on a key while focused on the map, it will be sent here
    onKeyUp: function (state, e) {
        if (e.keyCode === 27) return this.changeMode("simple_select");
    },
    onStop: function (state) {
        doubleClickZoom.enable(this);
        this.updateUIClasses({ mouse: "none" });
        this.activateUIButton();

        // check to see if we've deleted this feature
        if (this.getFeature(state.rectangle.id) === undefined) return;

        //remove last added coordinate
        state.rectangle.removeCoordinate("0.4");
        if (state.rectangle.isValid()) {
            this.map.fire("draw.create", {
                features: [state.rectangle.toGeoJSON()]
            });
        } else {
            this.deleteFeature([state.rectangle.id], { silent: true });
            this.changeMode("simple_select", {}, { silent: true });
        }
    },
    toDisplayFeatures: function (state, geojson, display) {
        const isActivePolygon = geojson.properties.id === state.rectangle.id;
        geojson.properties.active = isActivePolygon ? "true" : "false";
        if (!isActivePolygon) return display(geojson);

        // Only render the rectangular polygon if it has the starting point
        if (!state.startPoint) return;

        // wxm_new
        if (state.startPoint) {
            display(this.createVertex(state.rectangle.id, geojson.geometry.coordinates[0][0], `0.0`, false));
        }
        // wxm_new

        return display(geojson);
    },
    onTrash: function (state) {
        this.deleteFeature([state.rectangle.id], { silent: true });
        this.changeMode("simple_select");
    },
    // wxm_new
    createVertex: function (parentId, coordinates, path, selected) {
        return {
            type: "Feature",
            properties: {
                meta: 'vertex',
                parent: parentId,
                coord_path: path,
                active: (selected) ? 'true' : "false"
            },
            geometry: {
                type: 'Point',
                coordinates
            }
        };
    }
};

export default DrawRectangle;

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

侧耳倾听...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值