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.
                !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
            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.
                !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
            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;
添加draw组件 let modes = MapboxDraw.modes; modes.draw_rectangle = DrawRectangle; //添加工具 this.draw = new MapboxDraw({ modes: modes, displayControlsDefault: false, }); map.addControl(this.draw, "top-right").. 增加了对地图上的绘图和编辑功能的支持。 需要 。 兼容版本记录在package.json中 在NPM上,此软件包最近已从 mapbox-gl-draw 移至@mapbox/ mapbox-gl-draw npm install @mapbox/ mapbox-gl-draw Draw随CSS一起提供,请确保将其包含在构建中。 Typescript定义文件可作为包的一部分提供。 npm install @types/mapbox__ mapbox-gl-draw 使用模块时 import '@mapbox/ mapbox-gl-draw /dist/ mapbox-gl-draw .css' 使用CDN时 < link rel =' stylesheet ' href =' https://api.mapbox.com/mapbox
mapbox自定义 绘制 工具如何使用mapbox 绘制 常用的工具需要引入的资源创建div引入mapbox实例设置circle工具创建 point 绘制 工具创建line 绘制 工具创建polygon(多边形) 绘制 工具创建 rectangle( 矩形 绘制 工具清除图层(layer)和资源(source) 如何使用mapbox 绘制 常用的工具 每次在网上查资源,尼玛脑袋疼,好多大神写的啥玩意呀。我们知道,操作地图不外乎就是一些事件,其实mapbox有一些关于 绘制 工具的一些插件,也可以自己定义 绘制 工具。 我这里的demo,就是
一、在index.html全局引入mapbox-gl的js和css包,由于项目中会涉及到部分空间几何对象关系的计算,需借助turf.js,详细使用方法可参考https://blog.csdn.net/weixin_39150852/article/details/116758542 二、创建地图组件,初始化地图 <template> <div class="map-wrapper" :id="mapId"></div> </template>
mapbox-gl-draw API ReferenceTo use DrawOptionsModes 最近工作有一项需求就是在web上进行数据点采集,生成一个geojson的数据。其他框架没细看,之前用过mapbox,就继续用mapbox来实现,参考了mapbox例子之后,发现draw是没什么问题,mapbox主页单独有个这个例子 show draw polygon area,但是问题在我想取d...