vue3+arcgisAPI4示例:绘图工具动态修改样式导出GeoJSON(附源码下载)

demo源码运行环境以及配置

运行环境:依赖Node安装环境,需要安装Node。 运行工具:vscode或者其他工具。

配置方式:下载demo源码,vscode打开,然后顺序执行以下命令: (1)下载demo环境依赖包命令:npm install -g

(2)yarn install (3)启动demo命令:yarn dev (4)打包demo命令: yarn build:prod

示例效果

核心部分代码

javascript 复制代码
<template>
    <div v-if="isSHowPlotPanel" class="map-plot-panel">
        <div class="plot-img">
            <div class="plot-marginleft">
                <el-color-picker v-model="color" show-alpha :predefine="predefineColors" @change="handleColorChange" />
                <span class="plot-span ml8">颜色</span>
            </div>
            <div :class="['plot-marginleft-1', currentTool == 'point' && 'active']" @click="ceateActiveTool('point')">
                <img src="@/views/plotMap/assets/point.png" alt="" class="tool-icon">
                <span class="plot-span">点</span>
            </div>
            <div :class="['plot-marginleft-1', currentTool == 'polyline' && 'active']"
                @click="ceateActiveTool('polyline')">
                <img src="@/views/plotMap/assets/line.png" alt="" class="tool-icon">
                <span class="plot-span">线</span>
            </div>
            <div :class="['plot-marginleft-1', currentTool == 'polygon' && 'active']"
                @click="ceateActiveTool('polygon')">
                <img src="@/views/plotMap/assets/polygon.png" alt="" class="tool-icon">
                <span class="plot-span">面</span>
            </div>
            <div class="plot-marginleft-2" @click="savePlotData">
                <img src="@/views/plotMap/assets/save.png" alt="" class="tool-icon">
                <span class="plot-span-1">保存</span>
            </div>
            <div class="plot-marginleft-3" @click="exportPlotData">
                <img src="@/views/plotMap/assets/export.png" alt="" class="tool-icon">
                <span class="plot-span-1">导出</span>
            </div>
            <div class="plot-marginleft-3" @click="clearPlotData">
                <img src="@/views/plotMap/assets/delete.png" alt="" class="tool-icon">
                <span class="plot-span-1">清除</span>
            </div>
            <div class="plot-marginleft-3" title="关闭绘图工具" @click="closePlotPanel">
                <img src="@/views/plotMap/assets/close.png" alt="" class="tool-icon-1">
            </div>
        </div>
    </div>
    <div v-else class="map-plot-panel set-pointer-events" title="打开绘图工具" @click="openPlotPanel">
        <img src="@/views/plotMap/assets/side-collapse-up.png" alt="" class="tool-icon-2">
    </div>
</template>
<script setup>
import { onMounted, onUnmounted, ref, getCurrentInstance } from "vue";
import SketchViewModel from "@arcgis/core/widgets/Sketch/SketchViewModel.js";
import { xyToLngLat } from "@arcgis/core/geometry/support/webMercatorUtils.js";
import { ElMessage } from "element-plus";
const { proxy } = getCurrentInstance();
const currentTool = ref('');
const color = ref('rgba(72, 187, 250, 0.75)');
const predefineColors = ref([
    '#ff4500',
    '#ff8c00',
    '#ffd700',
    '#90ee90',
    '#00ced1',
    '#1e90ff',
    '#c71585',
    'rgba(255, 69, 0, 0.68)',
    'rgb(255, 120, 0)',
    'hsv(51, 100, 98)',
    'hsva(120, 40, 94, 0.5)',
    'hsl(181, 100%, 37%)',
    'hsla(209, 100%, 56%, 0.73)',
    '#c7158577',
])
const isSHowPlotPanel = ref(true);
let sketchViewModel = null;
let polygonSymbol = {
    type: "simple-fill",
    color: color.value,
    outline: {
        color: color.value,
        width: 2
    }
};
let polylineSymbol = {
    type: "simple-line",
    color: color.value,
    width: 2
};
let pointSymbol = {
    type: "simple-marker",
    style: "circle",
    color: color.value,
    size: 8,
    outline: {
        color: color.value,
        width: 2
    }
};
let view = null;
onMounted(() => {
    proxy.$Bus.on('init-PlotLayers', initPlotLayers);
});
onUnmounted(() => {
    proxy.$Bus.off('init-PlotLayers', initPlotLayers);
})
const initPlotLayers = (activeView) => {
    view = activeView;
    const plotLayer = view.map.findLayerById("plotLayer");
    if (plotLayer) {
        sketchViewModel = new SketchViewModel({
            view: view,
            layer: plotLayer,
            polygonSymbol: polygonSymbol,
            polylineSymbol: polylineSymbol,
            pointSymbol: pointSymbol,
            defaultCreateOptions: {
                hasZ: true  // default value
            },
            defaultUpdateOptions: {
                enableZ: true  // default value
            }
        });
        sketchViewModel.on("update", function (event) {
            if (event.state === "complete") {
                console.log("绘制完成");
                setGraphicsSymbol(event.graphics);
            }
        });
    }
}
//动态修改选中的绘制图形graphics
const setGraphicsSymbol = (graphics) => {
    if (graphics) {
        graphics.forEach((graphic) => {
            if (graphic.geometry.type === "point") {
                graphic.symbol = pointSymbol;
            } else if (graphic.geometry.type === "polyline") {
                graphic.symbol = polylineSymbol;
            } else if (graphic.geometry.type === "polygon") {
                graphic.symbol = polygonSymbol;
            }
        });
    }
}
const handleColorChange = (val) => {
    if (sketchViewModel) {
        // 更新符号颜色
        polygonSymbol.color = val;
        polygonSymbol.outline.color = val;
        polylineSymbol.color = val;
        pointSymbol.color = val;
        pointSymbol.outline.color = val;
        sketchViewModel.polygonSymbol = polygonSymbol;
        sketchViewModel.polylineSymbol = polylineSymbol;
        sketchViewModel.pointSymbol = pointSymbol;
        // 如果有需要可以在这里添加其他逻辑
        console.log('颜色已更新为:', val);
        sketchViewModel.cancel();
    }
};
// 绘制点线面
const ceateActiveTool = (activeTool) => {
    if (!sketchViewModel) return;
    if (sketchViewModel.activeTool === activeTool) {
        sketchViewModel.cancel();
        currentTool.value = '';
        return;
    }
    currentTool.value = activeTool;
    sketchViewModel.create(activeTool);
}
const openPlotPanel = () => {
    isSHowPlotPanel.value = true;
}
// 关闭绘制工具面板
const closePlotPanel = () => {
    // clearPlotData();
    isSHowPlotPanel.value = false;
}
const clearPlotData = () => {
    const plotLayer = view.map.findLayerById("plotLayer");
    if (plotLayer) {
        plotLayer.removeAll();
    }
    sketchViewModel.cancel();
}
const savePlotData = () => {
    const plotLayer = view.map.findLayerById("plotLayer");
    if (plotLayer) {
        const geoJSON = plotLayerToGeoJSON(plotLayer);
        // console.log('geoJSON', geoJSON);
        ElMessage.success(JSON.stringify(geoJSON));
    }
}
const exportPlotData = () => {
    const plotLayer = view.map.findLayerById("plotLayer");
    if (plotLayer) {
        const geoJSON = plotLayerToGeoJSON(plotLayer);
        // console.log('geoJSON', geoJSON);
        // ElMessage.success(JSON.stringify(geoJSON));
        const blob = new Blob([JSON.stringify(geoJSON)], { type: `application/json` });
        const blobUrl = URL.createObjectURL(blob);
        // 创建一个临时的<a>标签
        const downloadLink = document.createElement('a');
        downloadLink.href = blobUrl;
        // 指定下载文件名
        downloadLink.download = `geojson`;
        // 触发下载
        document.body.appendChild(downloadLink);
        downloadLink.click();
        // 清理临时创建的元素和URL对象
        document.body.removeChild(downloadLink);
        URL.revokeObjectURL(blobUrl);
    }
}
/**
 * 将plotLayer图层中的数据按照点线面分组转换为GeoJSON格式
 * @param {Object} plotLayer - 图层对象
 * @returns {Object} - 返回GeoJSON数据的对象
 */
const plotLayerToGeoJSON = (plotLayer) => {
    // 初始化结果对象
    const result = {
        type: "FeatureCollection",
        features: []
    };
    // 检查图层是否存在
    if (!plotLayer) {
        console.warn("plotLayer图层不存在");
        return result;
    }
    // 检查图层中是否有图形数据
    if (!plotLayer.graphics || plotLayer.graphics.length === 0) {
        console.warn("plotLayer图层中没有图形数据");
        return result;
    }
    // 遍历图层中的所有图形
    plotLayer.graphics.forEach((graphic, index) => {
        if (!graphic.geometry) return;
        // 根据几何类型分类
        const geometryType = graphic.geometry.type;
        let geoJSONType = "";
        let coordinates = [];
        let symbol = "";
        // 转换坐标和类型
        switch (geometryType) {
            case "point":
                geoJSONType = "Point";
                coordinates = [graphic.geometry.longitude, graphic.geometry.latitude];
                symbol = {
                    type: graphic.symbol?.type || "",
                    style: graphic.symbol?.style || "",
                    color: graphic.symbol?.color || "",
                    size: graphic.symbol?.size || "",
                    outline: graphic.symbol?.outline || ""
                };
                break;
            case "polyline":
                geoJSONType = "LineString";
                coordinates = graphic.geometry.paths[0].map(point => xyToLngLat(point[0], point[1]));
                symbol = {
                    type: graphic.symbol?.type || "",
                    color: graphic.symbol?.color || "",
                    style: graphic.symbol?.style || "",
                    width: graphic.symbol?.width || ""
                };
                break;
            case "polygon":
                geoJSONType = "Polygon";
                coordinates = [graphic.geometry.rings[0].map(point => xyToLngLat(point[0], point[1]))];
                symbol = {
                    type: graphic.symbol?.type || "",
                    color: graphic.symbol?.color || "",
                    style: graphic.symbol?.style || "",
                    outline: graphic.symbol?.outline || ""
                };
                break;
            default:
                return; // 跳过不支持的几何类型
        }
        // 创建GeoJSON特征对象
        const feature = {
            type: "Feature",
            id: index,
            properties: {
                // 添加属性信息,如果graphic有attributes则使用
                ...(graphic.attributes || {}),
                // 添加符号信息
                symbol: symbol
            },
            geometry: {
                type: geoJSONType,
                coordinates: coordinates
            }
        };
        result.features.push(feature);
    });
    return result;
}
</script>
相关推荐
zhz52146 小时前
ArcGIS实习教程
arcgis·地理信息·空间数据
小艳加油7 小时前
ArcGIS赋能水文水环境保护:从基础操作到高级分析,涵盖数据库构建、空间插值、水文模拟与水环境容量计算的综合技能
arcgis·水文水资源·地理信息系统
智航GIS1 天前
ArcGIS大师之路500技---069整形边工具
arcgis
葱明撅腚1 天前
shapely空间数据分析
python·pandas·gis·shapely
瑞瑞大大1 天前
arcgis中判断栅格数据有没有0值
arcgis·栅格0值
DreamOneDay1 天前
MapLibre GL JS加载ArcGis Terrain3D地形
javascript·3d·arcgis·maplibre·terrain3d
暗中讨饭的卫31 天前
【ARCGIS】点生成以点为半径的圆圈
arcgis
WebGIS开发2 天前
新中地系统学习3个月能做出什么效果?
openlayers·mapbox·webgis
极海拾贝2 天前
秒加在线底图!天地图、高德地图、星图地球、吉林一号底图一次配齐,收藏这篇就够了!
arcgis·gis·geoscene
智航GIS2 天前
ArcGIS大师之路500技---068分类统计
arcgis