zhgdyun/src/components/mars3d/MarsBoxarea.vue

855 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="mars3d-com">
<div class="mars3d-com" ref="mars3dContainer" style="width: 100%; height: 100%"></div>
<!-- 绘制区域 -->
<div class="mars-3d-deleter">
{{ !latlntswtich ? '绘制面' : '获取经纬度'}}
<i
@click="onclonemap"
class="el-icon-close"
style="font-size:'16px'; cursor: pointer;"
></i>
</div>
<div class="mars3d-box" v-if="!latlntswtich">
<div class="mars-3d-header">
<el-radio-group v-model="marsheader">
<el-radio :label="1">多边形面</el-radio>
<el-radio :label="2">自定义面</el-radio>
</el-radio-group>
</div>
<div class="mars3d-Controls">
<div class="mars3d-item" style="margin-top: 50px;">
<div class="mar3d-title">数据维护</div>
<div class="mar3d-con">
<el-button size="mini" type="primary" @click="startDrawGraphic">绘制</el-button>
<el-button size="mini" type="danger" @click="deleteSelectedGraphic">删除</el-button>
<el-button size="mini" type="success" @click="updateGraphicStyle">保存</el-button>
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">区域名称</div>
<div class="mar3d-con">
<input v-model="itemdata.texttitle" placeholder="填充文字" />
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">边框颜色</div>
<div class="mar3d-con distinction">
<el-color-picker v-model="itemdata.fillColor" size="small" />
<input v-model="itemdata.fillColor" placeholder="填充色" />
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">填充颜色</div>
<div class="mar3d-con distinction">
<el-color-picker v-model="itemdata.collColor" size="small" />
<input v-model="itemdata.collColor" placeholder="填充色" />
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">文字颜色</div>
<div class="mar3d-con distinction">
<el-color-picker v-model="itemdata.textColor" size="small" />
<input v-model="itemdata.textColor" placeholder="文字颜色" />
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">不透明度</div>
<div class="mar3d-con">
<div class="block">
<el-slider v-model="itemdata.transpitem" :min="0.1" :max="1" :step="0.1"></el-slider>
</div>
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">是否虚线</div>
<div class="mar3d-con">
<el-switch v-model="itemdata.swtichitem" active-color="#34c759" inactive-color="#ccc"></el-switch>
</div>
</div>
<div class="mars3d-item">
<el-button size="mini" type="success" @click="saveArea">保存区域</el-button>
</div>
</div>
</div>
<!-- 经纬度数据 -->
<div class="mars3djinwie-box" v-if="latlntswtich">
<div class="mars3d-Controls">
<div class="mars3d-item" style="margin-top: 50px;">
<div class="mar3d-title">当前经度</div>
<div class="mar3d-con">
<input v-model="latlntdata.lon" placeholder="经度" disabled />
</div>
</div>
<div class="mars3d-item">
<div class="mar3d-title">当前纬度</div>
<div class="mar3d-con">
<input v-model="latlntdata.lat" placeholder="纬度" disabled />
</div>
</div>
<div class="mars3d-item">
<el-button size="mini" type="success" @click="onlatlnt">保存经纬度</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
// import * as mars3d from "mars3d";
// import { Cesium } from "mars3d";
import "mars3d/dist/mars3d.css";
import "mars3d-cesium/Build/Cesium/Widgets/widgets.css";
export default {
data() {
return {
mars3dContainer: null,
map: null,
// 图层
graphicLayer: null,
// 开关
selectedGraphic: null,
// 修改图形
itemdata: {
// 填充色
fillColor: "",
// 文字颜色
textColor: "",
// 填充文字
texttitle: "",
// 填充颜色
collColor: "",
// 透明度
transpitem: 0.2,
// 是否虚线
swtichitem: false,
// 画圆范围
scopedata: 0
},
// 唯一值
datatitle: 1,
// 选中自定义图形
marsheader: 1,
// 获取经纬度-开关
latlntswtich: false,
// 经纬度
latlntdata: {
lat: "",
lon: ""
},
// 搜索值
inputmap: "",
// 查询回来值
searchdata: []
};
},
mounted() {
console.log("====================加载地图======================");
this.mars3dContainer = this.$refs.mars3dContainer;
// 初始化Mars3D地图
this.map = new mars3d.Map(this.mars3dContainer, {
scene: {
center: { lat: 42.8, lng: 90.4, alt: 150000, heading: 0, pitch: -45 },
showSun: true,
showMoon: true,
showSkyBox: true,
showSkyAtmosphere: false, // 关闭球周边的白色轮廓 map.scene.skyAtmosphere = false
fog: true,
fxaa: true,
globe: {
showGroundAtmosphere: false, // 关闭大气(球表面白蒙蒙的效果)
depthTestAgainstTerrain: false,
baseColor: "#546a53"
},
cameraController: {
zoomFactor: 3.0,
minimumZoomDistance: 1,
maximumZoomDistance: 50000000,
enableRotate: true,
enableZoom: true
},
mapProjection: mars3d.CRS.EPSG3857, // 2D下展示墨卡托投影
mapMode2D: Cesium.MapMode2D.INFINITE_SCROLL // 2D下左右一直可以滚动重复世界地图
},
control: {
contextmenu: { hasDefault: true }, // 右键菜单
distanceLegend: { left: "100px", bottom: "50px" },
// zoom: true,
baseLayerPicker: true, // basemaps底图切换按钮
geocoder: { service: "geocoder" }, // 使用高德POI服务
homeButton: true
},
// terrain: {
// url: "//data.mars3d.cn/terrain",
// show: true
// },
basemaps: [
{
name: "高德地图",
icon: "http://jxj.zhgdyun.com:100/image/670f36d001fd0d65e36e1224.png", // 假设你有一个高德地图的图标
type: "xyz",
url:
"http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
subdomains: ["1", "2", "3", "4"],
show: true // 设置为默认显示
}
]
});
const locationBar = new mars3d.control.LocationBar({
template:
"<div>经度:{lng}</div><div>纬度:{lat}</div> <div>海拔:{alt}米</div> <div>层级:{level}</div><div>方向:{heading}度</div> <div>俯仰角:{pitch}度</div><div>视高:{cameraHeight}米</div><div>帧率:{fps} FPS</div>"
});
// 添加控件到地图
this.map.addControl(locationBar);
const compass = new mars3d.control.Compass({
bottom: "400px",
left: "10px"
});
this.map.addControl(compass);
this.map.control.geocoder._czmContrl.viewModel.complete.addEventListener(
function() {
const arrdata = map.control.geocoder._czmContrl.viewModel.suggestions;
console.log("查询结果", arrdata);
}
);
if (this.$parent.$parent.MarsBoxareadata) {
console.log("this.$parent.MarsBoxareadata", this.$parent.MarsBoxareadata);
console.log(
"this.$parent.MarsBoxareadata",
JSON.parse(this.$parent.$parent.MarsBoxareadata, null, 2)
);
this.graphicLayer = new mars3d.layer.GraphicLayer();
this.map.addLayer(this.graphicLayer);
let a = JSON.parse(this.$parent.$parent.MarsBoxareadata, null, 2);
console.log("a.geojsonData.features.length > 1", a.features.length > 0);
if (a.features.length > 0) {
a.features.forEach(item => {
console.log("每个item", item);
if (item.geometry.type == "Polygon") {
this.addDemoGraphic14(item);
} else {
this.addCircleDemoGraphic12(item);
}
});
}
} else {
console.log("执行没有绘制==============");
// 没有修改过
// 创建一个图形图层
this.graphicLayer = new mars3d.layer.GraphicLayer();
this.map.addLayer(this.graphicLayer);
}
// this.bindLayerPopup();
this.bindGraphicClick();
// 绑定地图点击事件
this.map.on(mars3d.EventType.click, this.handleMapClick);
},
methods: {
// 保存经纬度
onlatlnt() {
this.$parent.$parent.onsetlatlnt({
lon: this.latlntdata.lon,
lat: this.latlntdata.lat
});
},
// 处理地图点击事件
handleMapClick(event) {
const position = event.position; // 获取点击位置的屏幕坐标 (x, y)
const cartesian = this.map.scene.globe.pick(
this.map.camera.getPickRay(position),
this.map.scene
); // 获取点击位置的笛卡尔坐标
if (cartesian) {
const cartographic = mars3d.Cesium.Cartographic.fromCartesian(
cartesian
); // 转换为地理坐标
const longitude = mars3d.Cesium.Math.toDegrees(cartographic.longitude); // 转换为经度
const latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude); // 转换为纬度
const altitude = cartographic.height; // 获取海拔高度
console.log(`经度: ${longitude}, 纬度: ${latitude}, 海拔: ${altitude}`);
this.latlntdata.lat = latitude;
this.latlntdata.lon = longitude;
// 这里可以根据需要将经纬度信息显示在界面上
// 例如this.showCoordinates(longitude, latitude, altitude);
}
},
// 通知父组件关闭
onclonemap() {
this.$parent.$parent.onclose();
},
addCircleDemoGraphic12(item) {
console.log("item===圆形", item);
const graphic = new mars3d.graphic.CircleEntity({
positions: item.geometry.coordinates, // 圆心位置
style: {
radius: item.properties.radius, // 圆的半径
color: item.properties.collColor, // 填充颜色
opacity: item.properties.transpitem, // 透明度
outline: true,
outlineStyle: {
width: 2,
materialType: item.properties.swtichitem
? mars3d.MaterialType.PolylineDash
: "",
materialOptions: {
color: item.properties.fillColor // 边框颜色
}
}, // 设置边框为虚线
label: {
text: item.properties.texttitle,
font_size: 18,
color: item.properties.textColor,
distanceDisplayCondition: true,
distanceDisplayCondition_far: 500000,
distanceDisplayCondition_near: 0
}
}
});
// 将圆形实体添加到图形图层
this.graphicLayer.addGraphic(graphic);
},
addDemoGraphic14(item) {
console.log("item============", item);
const graphic = new mars3d.graphic.PolygonEntity({
positions: item.geometry.coordinates,
style: {
color: item.properties.collColor, // 填充颜色
opacity: item.properties.transpitem, // 透明度
outline: true,
outlineWidth: 2,
outlineColor: item.properties.fillColor,
outlineStyle: {
materialType: item.properties.swtichitem
? mars3d.MaterialType.PolylineDash
: ""
}, // 设置边框为虚线
label: {
text: item.properties.texttitle,
font_size: 18,
color: item.properties.textColor,
distanceDisplayCondition: true,
distanceDisplayCondition_far: 500000,
distanceDisplayCondition_near: 0
}
}
});
this.graphicLayer.addGraphic(graphic);
},
// 开始绘制
startDrawGraphic() {
console.log("执行绘画");
if (this.selectedGraphic) {
this.updateGraphicStyle();
}
const that = this;
if (this.graphicLayer) {
this.graphicLayer.unbindPopup();
}
if (this.marsheader == 1) {
// 多边形
this.graphicLayer.startDraw({
type: "polygon",
style: {
color: "#3c444f", // 填充颜色
opacity: this.itemdata.transpitem, // 透明度
outline: true,
outlineWidth: 1,
outlineColor: "#93a9cc",
outlineStyle: {
materialType: this.itemdata.swtichitem
? mars3d.MaterialType.PolylineDash
: ""
}, // 设置边框为虚线
label: {
text: "未命名",
font_size: 18,
color: "#ffffff",
distanceDisplayCondition: true,
distanceDisplayCondition_far: 500000,
distanceDisplayCondition_near: 0
}
}
});
} else {
// 圆形
this.graphicLayer.startDraw({
type: "circle",
style: {
color: "#3c444f", // 填充颜色
opacity: this.itemdata.transpitem, // 透明度
clampToGround: false,
outline: true,
outlineStyle: {
width: 2,
materialType: this.itemdata.swtichitem
? mars3d.MaterialType.PolylineDash
: "", // 使用虚线材质
materialOptions: {
color: "#93a9cc" // 边框颜色
// dashLength: 36, // 虚线长度
// maskLength: 10, // 空隙间隔长度
// centerPower: 0.1, // 中心宽百分比
// dashPower: 0.2 // 虚线百分比
}
},
label: {
text: "未命名",
font_size: 18,
color: "#ffffff",
distanceDisplayCondition: true,
distanceDisplayCondition_far: 500000,
distanceDisplayCondition_near: 0
}
},
drawShowRadius: true
});
}
// this.updateGraphicStyle();
},
// 在图层绑定Popup弹窗
bindLayerPopup() {
this.graphicLayer.bindPopup(function(event) {
console.log("event", event);
const data = event.graphic.style;
const attr = {};
// attr["类型"] = event.graphic.type;
// attr["来源"] = "我是layer上绑定的Popup";
// attr["备注"] = "我支持鼠标交互";
attr["名称"] = data.label.text;
// attr["描述"] = attr.description || "默认描述"; // 使用图形属性中的描述信息
return mars3d.Util.getTemplateHtml({
title: "矢量图层",
template: "all",
attr
});
});
},
// 绑定图形点击事件
bindGraphicClick() {
const that = this;
this.graphicLayer.on(mars3d.EventType.click, function(event) {
that.selectedGraphic = event.graphic;
console.log("event.graphic", event.graphic);
console.log("this.itemdata", that.itemdata);
console.log("this.itemdata", that.itemdata.fillColor);
that.itemdata.collColor = event.graphic.style.color;
that.itemdata.textColor = event.graphic.style.label.color;
that.itemdata.texttitle = event.graphic.style.label.text;
that.itemdata.transpitem = event.graphic.style.opacity;
that.itemdata.swtichitem =
event.graphic.style.outlineStyle.materialType == "PolylineDash"
? true
: false;
if (event.graphic.type == "polygon") {
that.itemdata.fillColor = event.graphic.style.outlineColor;
} else {
that.itemdata.fillColor =
event.graphic.style.outlineStyle.materialOptions.color;
}
// 重新绑定弹窗
that.bindLayerPopup();
});
},
// 更新图形样式
updateGraphicStyle() {
if (this.selectedGraphic) {
console.log("this.selectedGraphic", this.selectedGraphic);
console.log("this.selectedGraphic.id", this.selectedGraphic.id);
this.selectedGraphic.style.color = this.itemdata.collColor;
this.selectedGraphic.style.label.color = this.itemdata.textColor;
this.selectedGraphic.style.label.text = this.itemdata.texttitle;
this.selectedGraphic.style.opacity = this.itemdata.transpitem;
this.selectedGraphic.style.outlineStyle.materialType = this.itemdata
.swtichitem
? mars3d.MaterialType.PolylineDash
: "";
if (this.selectedGraphic.type == "polygon") {
this.selectedGraphic.style.outlineColor = this.itemdata.fillColor;
} else {
this.selectedGraphic.style.outlineStyle.materialOptions.color = this.itemdata.fillColor;
}
// // 移除之前的监听器
// map.off(mars3d.EventType.postUpdate, updateGraphicStyle);
// // 添加新的监听器
// map.on(mars3d.EventType.postUpdate, function (event) {
// console.log("更新了", event);
// // 在这里可以进行其他操作
// });
const graphic = this.graphicLayer.getGraphicById(
this.selectedGraphic.id
);
// console.log("graphic", graphic);
// console.dir("111111",graphic)
// console.log("graphic", graphic.redraw());
graphic.redraw();
// 重新渲染地图
// this.map.render();
// 关闭弹窗
this.graphicLayer.unbindPopup();
// 清理 selectedGraphic.value
// this.selectedGraphic = null;
}
},
// 删除
deleteSelectedGraphic() {
if (this.selectedGraphic) {
this.updateGraphicStyle();
this.graphicLayer.removeGraphic(this.selectedGraphic);
this.selectedGraphic = null;
this.itemdata = {};
}
},
// 保存区域
saveArea() {
if (this.graphicLayer) {
this.updateGraphicStyle();
const graphics = this.graphicLayer.getGraphics();
const features = graphics
.map(graphic => {
const geometry = graphic.positions; // 获取图形的坐标点
console.log("图形坐标点:", geometry); // 调试信息
// 将笛卡尔坐标转换为经纬度坐标
const positions = geometry.map(point => {
const cartographic = Cesium.Cartographic.fromCartesian(point);
return [
Cesium.Math.toDegrees(cartographic.longitude),
Cesium.Math.toDegrees(cartographic.latitude)
];
});
const properties = {
fillColor:
graphic.style.outlineColor ||
graphic.style.outlineStyle.materialOptions.color,
collColor: graphic.style.color,
textColor: graphic.style.label.color,
texttitle: graphic.style.label.text,
transpitem: graphic.style.opacity,
swtichitem:
graphic.style.outlineStyle.materialType == "PolylineDash"
? true
: false,
radius: graphic.style.radius
};
// 根据图形的类型如多边形、线等创建相应的GeoJSON几何对象
let geoJSONGeometry;
console.log("graphic.type", graphic.type);
if (graphic.type === "polygonP") {
geoJSONGeometry = {
type: "polygon",
coordinates: [positions]
};
} else if (graphic.type === "polygon") {
geoJSONGeometry = {
type: "Polygon",
coordinates: [positions]
};
} else if (graphic.type === "polyline") {
geoJSONGeometry = {
type: "LineString",
coordinates: positions
};
} else if (graphic.type === "circle") {
geoJSONGeometry = {
type: "Circle",
coordinates: positions
};
} else {
// 其他类型的图形处理
return null;
}
return {
type: "Feature",
geometry: geoJSONGeometry,
properties: properties
};
})
.filter(feature => feature !== null); // 过滤掉无效的图形
const geoJSON = {
type: "FeatureCollection",
features: features
};
console.log("导出的GeoJSON数据", JSON.stringify(geoJSON, null, 2));
const a = geoJSON.features;
const formattedCoordinates = a
.map(feature => {
return feature.geometry.coordinates
.map(coord => {
return `${coord[0]}|${coord[1]}`;
})
.join(", ");
})
.join(", ");
console.log(formattedCoordinates);
this.itemdata = {
// 填充色
fillColor: "",
// 文字颜色
textColor: "",
// 填充文字
texttitle: ""
};
this.$parent.$parent.MarsBoxareadata = JSON.stringify(geoJSON);
this.$parent.$parent.fenceShapedata = formattedCoordinates;
// this.$parent.submit("form");
this.$parent.$parent.MarsBoxSwtich = false;
} else {
this.$parent.$parent.MarsBoxSwtich = false;
}
}
},
beforeDestroy() {
// 组件销毁前,销毁地图
if (this.map) {
this.map.destroy();
}
}
};
</script>
<style lang="scss" scoped>
::v-deep .cesium-viewer {
// background: red !important;
.cesium-viewer-toolbar {
width: 100px;
height: 100px;
display: flex;
flex-direction: column;
// background: red !important;
position: absolute;
left: 15px; /* 调整到左下角 */
top: 670px; /* 调整到左下角 */
z-index: 9999 !important; /* 确保在地图上方 */
}
// .mars3d-locationba {
// background: red !important;
// .mars3d-locationbar-content {
// margin-top: 10px !important;
// }
// }
.cesium-baseLayerPicker-dropDown {
top: -242px;
right: -304px;
}
.cesium-viewer-geocoderContainer {
position: relative;
display: inline-block;
margin: 0 3px;
position: absolute;
top: -41px;
left: -1px;
}
}
.mars3d-com {
position: relative;
.mars-3d-deleter {
width: 300px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
height: 42px;
// border-left: 5px solid linear-gradient(180deg, #3170e2 0%, #52b2ee 100%);
// border-bottom: 2px solid #4faced;
background: rgba(11, 22, 51, 0.3);
background-image: url("~@/assets/images/mapbox/Group 31.png");
background-position: center center;
background-repeat: no-repeat;
background-size: 100% 100%;
color: #ffffff;
// box-sizing: border-box;
position: absolute;
right: 50px;
top: 20px;
}
.mars3d-jinwei {
height: 220px !important;
}
.mars3djinwie-box {
height: 220px !important;
}
.mars3d-box,
.mars3djinwie-box {
position: absolute;
right: 50px;
top: 70px;
width: 300px;
height: 420px;
background-image: url("~@/assets/images/mapbox/Rectangle 24.png");
// background-position: center center;
background-size: 100% 100%;
background-repeat: no-repeat;
z-index: 1000;
padding: 0 15px 15px;
display: flex;
flex-direction: column;
// position: relative;
color: #ffffff;
border-radius: 5px;
.mars-3d-header {
width: 100%;
display: flex;
height: 45px;
line-height: 45px;
padding-left: 15px !important;
padding-right: 15px !important;
background-image: url("~@/assets/images/mapbox/Rectangle 22.png");
background-size: 100% 100%;
background-repeat: no-repeat;
border: 1px solid #344c7b;
position: absolute;
left: 0;
padding: 0;
box-sizing: border-box;
border: 10px 10px 0 0 !important;
display: flex;
align-items: center;
justify-content: space-between;
::v-deep .el-radio-group {
// background: skyblue !important;
.el-radio__label {
color: #ffffff;
}
}
i {
cursor: pointer;
}
}
.mars3d-Controls {
flex: 1;
display: flex;
flex-wrap: wrap;
.mars3d-item {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
.mar3d-title {
width: 100px;
}
.distinction {
// background: skyblue;
display: flex;
// align-items: flex-start;
align-items: center;
input {
width: 140px !important;
}
::v-deep .el-color-picker--small .el-color-picker__trigger {
width: 23px !important;
height: 23px !important;
margin-right: 8px !important;
margin-top: 5px !important;
}
}
.mar3d-con {
flex: 1;
display: flex;
align-items: center;
.block {
width: 180px;
::v-deep .el-slider__runway {
background-image: url("~@/assets/images/mapbox/Rectangle 34624274.png") !important;
background-size: 100% 100%;
background-repeat: no-repeat;
.el-slider__bar {
background: transparent !important;
}
.el-slider__button {
// background: yellow !important;
background-image: url("~@/assets/images/mapbox/Group 1000015866.png") !important;
background-size: 100% 100%;
background-repeat: no-repeat;
border: 0px !important;
}
}
}
}
}
}
}
}
</style>