arcgisjs:实现地图范围选取丝滑范围查询标绘类

🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、优快云优质创作者
💟 作 者:柳晓黑胡椒❣️
📝 专 栏:arcgis实践
🌈 若有帮助,还请关注点赞收藏,不行的话我再努努力💪💪💪

需求背景

需要使用arcgisjs 实现范围选取功能,介于网上arcgis技术文档大多英文文档,不易封装实现

解决效果

index.vue

<template>
  <div class="rangeSearch-wrap">
    <div class="measure-box">
      <div class="tit-wrap">
        <span>范围查询</span>
        <el-icon class="close-icon" color="red" size="16" @click="clearDraw">
          <delete/>
        </el-icon>
        <i class="el-icon-delete close-icon" color="red" size="18" @click="clearDraw"></i>
      </div>
      <ul>
        <li @click="startDrawing('circle')">圆形</li>
        <li @click="startDrawing('rectangle')">矩形</li>
        <li @click="startDrawing('polygon')">多边形</li>
      </ul>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {usearcgisMapStore} from "@/store/modules/arcgisMap";
import {onMounted, onUnmounted, reactive, toRefs} from "vue"
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer'
import Graphic from '@arcgis/core/Graphic';
import Draw from '@arcgis/core/views/draw/Draw';
import Point from '@arcgis/core/geometry/Point'
import * as geometryEngine from '@arcgis/core/geometry/geometryEngine.js'
import Circle from "@arcgis/core/geometry/Circle.js";
import Extent from '@arcgis/core/geometry/Extent'
import * as projection from '@arcgis/core/geometry/projection'
import {toWKT} from "@/utils/dictionary";

const mapStore = usearcgisMapStore()

onMounted(() => {
  viewer.map.layers.add(graphicsLayer)
})

onUnmounted(() => {
  viewer.map.layers.remove(graphicsLayer)
  graphicsLayer.removeAll()
})

// 地图逻辑
let action
const viewer = mapStore.getArcgisViewer();
const graphicsLayer = new GraphicsLayer();
const draw = new Draw({
  view: viewer
});

const startDrawing = (type) => {
  if (action) action.destroy()
  switch (type) {
    case 'circle':
      action = draw.create("circle", {mode: "click"});
      break
    case 'rectangle':
      action = draw.create("rectangle", {mode: "click"});
      break
    case 'polygon':
      action = draw.create("polygon", {mode: "click"});
      break
  }
  action.on(["vertex-add", "cursor-update", "draw-complete", "vertex-remove"], (evt) => measureLine(evt, type));
}


const clearDraw = () => {
  graphicsLayer?.removeAll()
  mapStore.setRangeSearchWKT("")
}

const measureLine = (evt, drawType) => {
  graphicsLayer.removeAll();
  const {vertices, type} = evt
  let geometry
  let point1, point2, radius = 10
  switch (drawType) {
    case "circle":
      point1 = new Point({x: vertices[0][0], y: vertices[0][1], spatialReference: viewer.spatialReference})
      if (vertices[1]) {
        point2 = new Point({x: vertices[1][0], y: vertices[1][1], spatialReference: viewer.spatialReference})
        radius = geometryEngine.distance(point1, point2, "meters")
      }
      geometry = new Circle({center: point1, radius, radiusUnit: "meters", spatialReference: viewer.spatialReference})
      if (type === "draw-complete") mercatorToWgs84(geometry.rings[0])
      break
    case "rectangle":
      point1 = vertices[0];
      point2 = vertices[1] || vertices[0];
      const xmin = Math.min(point1[0], point2[0])
      const xmax = Math.max(point1[0], point2[0])
      const ymin = Math.min(point1[1], point2[1])
      const ymax = Math.max(point1[1], point2[1])
      geometry = new Extent({xmin, ymin, xmax, ymax, spatialReference: viewer.spatialReference})
      if (type === "draw-complete") mercatorToWgs84([[xmin, ymin], [xmin, ymax], [xmax, ymin], [xmax, ymax], [xmin, ymin]])
      break
    case "polygon":
      geometry = {type: "polygon", rings: vertices, spatialReference: viewer.spatialReference}
      if (type === "draw-complete") mercatorToWgs84([...geometry.rings, geometry.rings[0]])
      break
  }
  const graphic = new Graphic({
    geometry,
    symbol: {
      type: "simple-fill",
      color: "rgba(0,196,255,.2)",
      style: "solid",
      outline: {
        width: 2,
        color: "#00C4FF"
      }
    }
  });
  graphicsLayer.add(graphic);
}

const mercatorToWgs84 = (mercatorCoords) => {
  const points = mercatorCoords.map(([x, y]) => {
    const point = new Point({x, y, spatialReference: viewer.spatialReference})
    const pt = projection.project(point, {wkid: 4326})
    return [+pt.longitude.toFixed(6), +pt.latitude.toFixed(6)]
  })
  const wkt = toWKT(points)
  mapStore.setRangeSearchWKT(wkt)
}

</script>

<style lang="scss" scoped>
.rangeSearch-wrap {
  pointer-events: auto;

  .measure-box {
    width: 230px;
    height: 100px;
    padding: 20px 15px;
    background: rgba(33, 40, 32, 0.7);
    color: #fff;
    font-size: 13px;
    box-sizing: border-box;
    z-index: 99;

    .close-icon {
      position: absolute;
      right: 5px;
      top: 5px;
    }

    .tit-wrap {
      position: relative;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;

      span {
        padding: 4px 8px;
        border-radius: 5px;
        background: #131111;
      }
    }

    ul {
      display: flex;
      justify-content: space-between;

      li {
        padding: 5px 15px;
        border-radius: 5px;
        background: #163143;
        cursor: pointer;
      }
    }
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

柳晓黑胡椒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值