vue3 使用 vue-cesium

npm install vue-cesium --save

main.js

import VueCesium from 'vue-cesium'

app.use(VueCesium).mount('#app')

页面中使用

<template>

  <div class="taskArea">

    <vc-viewer ref="vierDraw" @ready="onViewerReady" accessToken='替换为自己的cesiumkey' geocoder sceneModePicker>

    <!-- 修改定位 和 位置偏移 -->

    <vc-drawings

      ref="drawingsRef"

      position="bottom-left"

      v-if="isCanvasShow"

      :main-fab-opts="mainFabOpts"

      :offset="[10, 30]"

      @draw-evt="drawEvt"

      @active-evt="activeEvt"

      @editor-evt="editorEvt"

      @mouse-evt="mouseEvt"

      @clear-evt="clearEvt"

      @ready="drawingsReadyDefault"

      @drawings-closed="onDrawingsClosed"

      :pin-drawing-opts="pinDrawingOpts"

      :rectangle-drawing-opts="rectangleDrawingOpts"

      :polygon-drawing-opts="polygonDrawingOpts"

    ></vc-drawings>

    <!-- <vc-primitive-tileset

      url="https://zouyaoji.top/vue-cesium/SampleData/Cesium3DTiles/Tilesets/dayanta/tileset.json"

      @ready-promise="onTilesetReady"

    ></vc-primitive-tileset> -->

    <vc-layer-imagery>

      <vc-imagery-provider-tianditu map-style="img_c" :maximum-level="17" token="436ce7e50d27eede2f2929307e6b33c0"></vc-imagery-provider-tianditu>

    </vc-layer-imagery>

    <div v-for="item in rectangleDrawingOptsStorage.preRenderDatas">

      <vc-entity v-if="item.type == 'Polygon'">

        <vc-graphics-polygon ref="polygon1" :hierarchy="item.arrayList" material="rgba(255, 255, 0, 0.5)"></vc-graphics-polygon>

        <!-- <vc-graphics-polyline v-else-if="item.type == 'polyline'" :width="2" :clampToGround="false" :hierarchy="item.arrayList" material="rgba(255, 255, 0, 0.5)"></vc-graphics-polyline> -->

      </vc-entity>

      <div v-if="item.type == 'Point'">

        <vc-entity v-if="item.typeName == 'Point'" :position="item.arrayList">

          <vc-graphics-point ref="point1" color="rgba(255, 255, 0,1)" :pixel-size="8"></vc-graphics-point>

        </vc-entity>

        <vc-entity v-else-if="item.typeName == 'pin'" :position="item.arrayList">

          <vc-graphics-billboard :image="require('@/assets/airport.png')" />

        </vc-entity>

        <vc-entity v-else-if="item.typeName == 'circle'" :position="item.arrayList">

          <vc-graphics-ellipse :semiMinorAxis="item.radius" :semiMajorAxis="item.radius" :height="0.0" material="rgba(255, 255, 0,0.5)" :outline="false"></vc-graphics-ellipse>

        </vc-entity>

      </div>

      <vc-entity v-if="item.type == 'LineString'">

        <vc-graphics-polyline :positions="item.arrayList" material="rgba(255, 255, 0,1)"></vc-graphics-polyline>

      </vc-entity>

    </div>

    <vc-layer-imagery>

      <vc-imagery-provider-tianditu :map-style="mapSty" token="436ce7e50d27eede2f2929307e6b33c0"></vc-imagery-provider-tianditu>

    </vc-layer-imagery>

  </vc-viewer>

  <a-button style="position: absolute;top: 10px;left: 20px;z-index: 9;background: rgba(0,0,0,.5);color: #fff;" @click="toggleLabels">

      {{ isShowGeoName ? $t('message.hidePlaceName') : $t('message.placeName') }}

    </a-button>

  <div class="btnContainer">

   

  <div>

    <a-list size="small" style="color: #fff;text-align: center;background-color: rgba(0,0,0,.4);min-width: 200px;overflow-y:scroll;max-height: 230px;" :locale="{emptyText: ' '}" bordered :data-source="RegionList">

      <template #renderItem="{ item,index }">

        <a-list-item style="color: #fff;" :class="{ 'selected-item': isSelected(index) }">

          <a-tooltip placement="leftTop">

            <template #title>

              <div>

                <a-button type="link" @click="clearAllDrawn(index,item)" danger>{{ $t('message.delete') }}</a-button>

                <a-button type="link" @click="item.isResetName = true" danger>{{ $t('message.Rename') }}</a-button>

              </div>

            </template>

            <p style="cursor: pointer;text-align: center;width: 100%;" @click="checkAlist(index)" v-if="!item.isResetName">{{ item.name }}</p>

            <div v-else>

              <a-input  v-model:value="item.name" style="width: 70%;" />

              <a-button type="link" @click="addAreaList(item,index)">{{ $t('message.ok') }}</a-button>

            </div>

          </a-tooltip>

          </a-list-item>

      </template>

      <template #header>

        <div>{{ $t('message.areaList') }}</div>

      </template>

      <template  v-if="!isCanvasShow" #footer>

        <div style="font-size: 20px;font-weight: 600;cursor: pointer;" @click="mapDialog = true">+</div>

      </template>

    </a-list>

  </div>

</div>

<a-modal v-model:visible="mapDialog" title="" ok-text="确认" cancel-text="取消" @ok="clickAddArea">

  <span>选择区域类型:</span>

  <a-select v-model:value="checkAregion" style="width: 200px;">

        <a-select-option value="1">任务区</a-select-option>

        <!-- <a-select-option value="2">结束区</a-select-option> -->

      </a-select>

</a-modal>

  </div>

</template>

<script setup>

import { ConsoleSqlOutlined } from "@ant-design/icons-vue"

import {ref,onMounted,nextTick,reactive   } from "vue"

import { postAddArea,getAreaList,delArea } from "../utils/api.js";

import { message } from "ant-design-vue";

  let checkAregion = ref('1')

  let isCanvasShow  = ref(false)

  let selectedRegionIndices  = reactive([]);

  const vierDraw = ref(null)

  const drawingsRef = ref(null)

  let mapDialog = ref(false)

  const RegionList = reactive([])

  let isShowDraw = ref(false)

  let isShowGeoName = ref(false)

  const attributes = ref(null)

  let rectangleDrawingOpts = reactive({

    preRenderDatas: [

      [

      // [108.957758283111, 34.21988950430172, 2.0019682259091733], [108.95827467484429, 34.21940420082603, 2.0019682256560865]

      ]

    ]

  });

  let mapSty = ref('img_c')

  // 响应式数据

const addTerrain = ref(false);

const editable = ref(false);

const clampToGround = ref(false);

const mainFabOpts = reactive({

  direction: 'right'

});

const isSelected = (index) => {

  return selectedRegionIndices.includes(index);

};

const checkAlist = (index) => {

  const selectedIndex = selectedRegionIndices.indexOf(index);

  if (selectedIndex > -1) {

    selectedRegionIndices.splice(selectedIndex, 1); // Deselect the item

    rectangleDrawingOptsStorage.preRenderDatas.splice(selectedIndex, 1);

  } else {

    selectedRegionIndices.push(index); // Select the item

    if(RegionList[index].type == 'LineString'){ //判断是线段

      let postionasdas = RegionList[index].geometry.coordinates

      let ooss = postionasdas.map(pos => Cesium.Cartesian3.fromDegrees(pos[0], pos[1]))

      moveToPolygon(ooss)

      rectangleDrawingOptsStorage.preRenderDatas.push({

          arrayList: [],

          type: RegionList[index].type,

          indexi:index,

        })

        //改变数据格式后才可以绘制出线段

        for (let ii = 0; ii < RegionList[index].geometry.coordinates.length; ii++) {

          const element = RegionList[index].geometry.coordinates[ii];

          rectangleDrawingOptsStorage.preRenderDatas[rectangleDrawingOptsStorage.preRenderDatas.length - 1].arrayList.push({

            lng:element[0],

            lat:element[1]

          })

        }

    }else if(RegionList[index].type == 'Point'){//判断是不是绘制的点

      //判断是图标点还是颜色点,pin为图标点

      if(RegionList[index].properties && RegionList[index].properties.type && RegionList[index].properties.type == 'pin'){

        rectangleDrawingOptsStorage.preRenderDatas.push({

          arrayList: RegionList[index].geometry.coordinates,

          type: RegionList[index].type,

          indexi:index,

          typeName: 'pin'

        })

      }else if(RegionList[index].properties && RegionList[index].properties.type && RegionList[index].properties.type == 'circle'){

        rectangleDrawingOptsStorage.preRenderDatas.push({

          arrayList: RegionList[index].geometry.coordinates,

          radius: RegionList[index].properties.radius,

          type: RegionList[index].type,

          indexi:index,

          typeName: 'circle'

        })

      }else{

        rectangleDrawingOptsStorage.preRenderDatas.push({

          arrayList: RegionList[index].geometry.coordinates,

          type: RegionList[index].type,

          indexi:index,

          typeName: 'Point'

        })

      }

      let postionasda = RegionList[index].geometry.coordinates

      let pointOss = Cesium.Cartesian3.fromDegrees(postionasda[0],postionasda[1],3000)

      moveTo(pointOss)

    }else{

      // delete RegionList[index].geometry.coordinates[0][RegionList[index].geometry.coordinates[0].length -1]

      rectangleDrawingOptsStorage.preRenderDatas.push({

        arrayList: RegionList[index].geometry.coordinates[0],

        indexi:index,

        type: RegionList[index].type

      })

      let postionasda = RegionList[index].geometry.coordinates[0]

      let oos = postionasda.map(pos => Cesium.Cartesian3.fromDegrees(pos[0], pos[1]))

      moveToPolygon(oos)

    }

   

    // polygonDrawingOpts.preRenderDatas.push(RegionList[index].geometry.coordinates[0])

    // drawingsRef.value.getDrawingActionInstances()[4].cmpRef.value.renderDatas.value.push([

    //   'position',Cesium.Cartesian3.fromDegreesArrayHeights(rectangleDrawingOptsStorage.preRenderDatas[index][0].flat())

    // ])

  }

  // console.log(rectangleDrawingOptsStorage.preRenderDatas,'哈哈哈哈哈')

  // console.log(Cesium.Cartesian3.fromDegreesArrayHeights(rectangleDrawingOptsStorage.preRenderDatas[index][0].flat()),'阿萨大1231大')

  // console.log(rectangleDrawingOptsStorage.preRenderDatas,'阿萨大大')

  // drawingsRef.value.reload()

  // onViewerReady()

};

//点击切换是否显示地点名称

const toggleLabels = () => {

  isShowGeoName.value = !isShowGeoName.value;

  if (isShowGeoName.value) {

    mapSty.value = 'cva_c'

  } else {

    mapSty.value = 'img_c'

  }

}

let rectangleDrawingOptsStorage = reactive({

  preRenderDatas: [

  ]

});

const pinDrawingOpts = reactive({

  billboardOpts: {

    image: require('@/assets/airport.png'),

    onClick(e) {

      console.log(e);

    }

  },

  labelOpts: {

    text: '图标点',

    pixelOffset: [0, -60],

    onClick(e) {

      console.log(e);

    }

  }

});

const polygonDrawingOpts = reactive({

  preRenderDatas: []

});

let restoreCursorMove = ref('')

let drawing = ref('')

//绘制图形事件

const drawEvt = (e, viewer) => {

  const restoreCursor = getComputedStyle(viewer.canvas).cursor;

  vierDraw.value = viewer

  if (e.finished) { //状态为绘制结束

    if (e.type === 'move') {

      viewer.canvas.setAttribute('style', `cursor: ${restoreCursorMove.value}`);

    }

    drawing.value = false;

    // rectangleDrawingOptsStorage.preRenderDatas

    // rectangleDrawingOptsStorage.preRenderDatas.push([e.positionsDegreesArray])

    if(e.name != 'point' && e.name != 'pin'){ //e.name是绘制的类型

      // rectangleDrawingOptsStorage.preRenderDatas.push({

      //   arrayList:e.positionsDegreesArray,

      //   type:e.name

      // })

      if(e.name == 'polygon'){ //因为传递参数的时候用的是GEOjson的格式,所以要把第一个字母大写

        e.name = 'Polygon'

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates:[e.positionsDegreesArray]}})

      }else if(e.name == 'polyline'){ //面

        e.name = 'LineString'

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates:e.positionsDegreesArray}})

      }else if(e.name == 'circle'){ //圆形

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates:e.positionsDegreesArray}})

      }else if(e.name == 'rectangle'){ //矩形,进页面初始绘制矩形获取不到polygonPositionsDegreesArray,绘制矩形要清除一次后再绘制

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates: [e.polygonPositionsDegreesArray]}})

      }else if(e.name == "regular"){//正多边形

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates: [e.polygonPositionsDegreesArray]}})

      }

    }else{

      if(e.name == 'pin'){

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates:e.positionDegrees}})

      }else if(e.name == 'point'){

        e.name = 'Point'

        RegionList.push({name:'',isResetName:true,type:e.name,geometry:{coordinates:e.positionDegrees}})

      }

    }

    // console.log(drawingsRef.value.getDrawingActionInstances()[3].cmpRef.value.renderDatas,'adada阿三大苏asdasd打')    

  } else {

    drawing.value = true;

    if (e.type === 'move') {

      viewer.canvas.setAttribute('style', 'cursor: move');

    }

    if (e.type === 'new') {

      viewer.canvas.setAttribute('style', 'cursor: crosshair');

    }

  }

};

const changeData = (list) => {

  const centerDegrees = list[0]

  const pointDegrees = list[1]

  const center = Cesium.Cartesian3.fromDegrees(...centerDegrees)

  const point = Cesium.Cartesian3.fromDegrees(...pointDegrees)

  const radius = Cesium.Cartesian3.distance(center, point)

  return radius

}

const convertToGeoJSON = (rectangleDrawingOptsStorage,index) => {

  let coordinates = RegionList[index].geometry.coordinates;

  let geoJSON = {

    "type": "Feature",

    "properties": {

      name:RegionList[index].name,

    },

    // bbox: [0],

    // crs: {

    //   properties: {},

    //   type: "name"

    // },

    geometry: {

    },

  };

  const geometry = {

    type: RegionList[index].type,

    coordinates: coordinates

  };

  if(geometry.type == 'regular'){

    geometry.type = 'Polygon'

    RegionList[index].type = 'Polygon'

  }

  if(geometry.type == 'Polygon'){

    coordinates[0].push(coordinates[0][0])

  }

  if(geometry.type == 'rectangle'){

    geometry.type = 'Polygon'

    RegionList[index].type = 'Polygon'

  }

  //type=pin是图标点,GeoJSON里面没有图标点格式,所以properties加了一个type

  if(geometry.type == 'pin'){

    geometry.type = 'Point'

    geoJSON.properties.type = 'pin'

    RegionList[index].properties = {

      type : 'pin'

    }

    RegionList[index].type = 'Point'

  }

  if(geometry.type == 'circle'){

    geometry.type = 'Point'

    RegionList[index].type = 'Point'

    geoJSON.properties.type = 'circle'

    RegionList[index].properties = {

      type : 'circle'

    }

    geometry.coordinates = RegionList[index].geometry.coordinates[0]

    geoJSON.properties.radius = changeData(RegionList[index].geometry.coordinates)

  }

  geoJSON.geometry = geometry;

  return geoJSON;

};

const addAreaList = (item,index) => {

  const geoJSONData = convertToGeoJSON(RegionList,index);

  if(item.name == ''){

    message.error('请输入名称!')

    return

  }

  postAddArea(geoJSONData).then(res => {

    if(res.code == 200){

      message.success(res.data)

      item.isResetName = false

      // selectedRegionIndices.push(index)

      isCanvasShow.value = false

    }

  })

}

const clickAddArea = () => {

  mapDialog.value = false

  isCanvasShow.value = true

}

const getList = () => {

  rectangleDrawingOptsStorage.preRenderDatas = []

  getAreaList().then(res => {

    for (let index = 0; index < res.data.length; index++) {

      const element = res.data[index];

      element.name = element.properties.name

      element.isResetName = false

      element.type = element.geometry.type

      RegionList.push(element)

      // rectangleDrawingOptsStorage.preRenderDatas.push([element.geometry.coordinates[0]])

    }

    // drawingsRef.value.reload()

  })

}

const clearAllDrawn = (i,item) => {

  if(item.id){

    delArea({id:item.id}).then(res => {

      if(res.code == 200){

        RegionList.splice(i,1)

       

        let inil = rectangleDrawingOptsStorage.preRenderDatas.findIndex((item) => item.indexi === i);

        rectangleDrawingOptsStorage.preRenderDatas.splice(inil,1)

        // for (let index = 0; index < selectedRegionIndices.length; index++) {

        //   const element = selectedRegionIndices[index];

        //   if(element == i){

        //     selectedRegionIndices.splice(selectedRegionIndices.indexOf(i),1)

        //   }

        // }

        // rectangleDrawingOptsStorage.preRenderDatas.splice(i,1)

        message.success(res.data)

      }else{

        message.error(res.message)

      }

    })

  }else{

    RegionList.splice(i,1)

    rectangleDrawingOptsStorage.preRenderDatas.splice(i,1)

    // rectangleDrawingOptsStorage.preRenderDatas.splice(i,1)

  }

}

var viewerx

var tempEntities = reactive([])

const onViewerReady =  ({ Cesium, viewer } ) => {

    const destination = Cesium.Cartesian3.fromDegrees(103.954204, 30.845838, 5000)

    const orientation = {

      heading : Cesium.Math.toRadians(0.0),

      pitch: Cesium.Math.toRadians(-90.0),

      roll : 0.0

    }

    viewer.camera.setView({destination, orientation})

    vierDraw.value = viewer

    viewerx = viewer

}

const moveTo = (position) => {

  viewerx.camera.flyTo({

    destination: position,

    orientation: {

      heading: Cesium.Math.toRadians(0),

      pitch: Cesium.Math.toRadians(-90),

      roll: 0.0

    }

  })

}

const moveToPolygon = (positions) => {

  const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)

  viewerx.camera.flyToBoundingSphere(boundingSphere)

}

// 方法和事件处理程序

const drawingsReadyDefault = ({ Cesium, viewer, cesiumObject }) => {

  console.log('绘制选项参数:', cesiumObject);

  viewer = viewer;

  vierDraw.value = viewer

  drawingsRef.value.clearAll()

};

const toggle = (drawingActionInstance) => {

  drawingsRef.value.toggleAction(drawingActionInstance.name);

};

// const onTilesetReady = (tileset, viewer) => {

//   const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);

//   const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);

//   const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 5);

//   const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());

//   tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

//   viewer.zoomTo(tileset);

//   viewer.scene.globe.depthTestAgainstTerrain = true;

//   restoreCursorMove.value = 'auto';

//   drawing.value = false;

// };

const activeEvt = (e, viewer) => {

  console.log(e);

  viewer.canvas.setAttribute('style', `cursor: ${e.isActive ? 'crosshair' : 'auto'}`);

  if (!e.isActive) {

    drawing.value = false;

    restoreCursorMove.value = 'auto';

  }

};

const editorEvt = (e, viewer) => {

  if (e.type === 'move') {

    viewer.canvas.setAttribute('style', 'cursor: move');

    drawing.value = true;

  } else {

    viewer.canvas.setAttribute('style', 'cursor: auto');

  }

};

const mouseEvt = (e, viewer) => {

  const restoreCursor = getComputedStyle(viewer.canvas).cursor;

  if (!drawing.value) {

    console.log(e);

    if (e.type === 'onmouseover') {

      restoreCursorMove.value = restoreCursor;

      viewer.canvas.setAttribute('style', 'cursor: pointer');

    } else {

      viewer.canvas.setAttribute('style', `cursor: ${restoreCursorMove.value || 'auto'}`);

    }

  }

};

const clearEvt = (e, viewer) => {

  if(RegionList[RegionList.length-1].isResetName){

    RegionList.splice(RegionList.length-1,1)

  }

};

const unload = () => {

  drawingsRef.value.unload();

};

const load = () => {

  const drawingsInstance = drawingsRef.value

  // 手动触发load事件

  drawingsInstance.load()

};

const reload = () => {

  drawingsRef.value.reload();

};

const pickEvt = (e) => {

  console.log(e);

};

   

const polygon1 = ref(null)

    onMounted(() => {

      getList()

     

      const viewer = vierDraw.value.getCesiumObject();

        if (viewer) {

          onViewerReady({ viewer });

        }

    })

   

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->

<style>

::-webkit-scrollbar {

display: none; /* Chrome Safari */

}

.cesium-viewer-bottom {

  display: none !important;

}

#cesiumContainer {

  width: 100%;

  height: 100%;

}

.taskArea{

  width: 100%;

  height: 99.3%;

  position: relative;

}

.ant-list-empty-text{

  color: #fff !important;

}

.btnContainer {

  position: absolute;

  left: 5px;

  top: 40px;

  padding: 10px 15px;

    /*添加圆角边框*/

  border-radius: 5px;

  /* border: 1px solid rgba(128,128,128, 0.5); */

  color: #ffffff;

  max-width: 300px;

}

button {

  background: transparent;

  border: 1px solid #00d0ffb8;

  color: white;

  padding: 7px 9px;

  border-radius: 3px;

    /*鼠标光标变为手形*/

  cursor: pointer;

}

.selected-item {

  background-color: #1890ff;

}

.bg-primary{

  background-color: #1890ff !important;

}

.bg-info{

  background-color: #1890ff !important;

}

.cesium-widget canvas{

  height: 98% !important;

}

</style>

vc-drawings是vue-cesium的绘制图形工具。

a-list是绘制添加后的区域列表,点击区域列表进行回显

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值