619 lines
17 KiB
Vue
619 lines
17 KiB
Vue
<template>
|
||
<div class="ditu">
|
||
<div id="marsContainer-map" ref="marsMaps" class="mars3d-container"></div>
|
||
<div class="btns" v-if="!disabled">
|
||
<div class="toolbar" v-if="typeOf === 'polygon'">
|
||
<div
|
||
:class="{ drawPolygon: true, disabled: isDisabled }"
|
||
@click="lineClick('polygon')"
|
||
>
|
||
<div class="drawPolygonIcon"></div>
|
||
</div>
|
||
<div class="drawPolygon" @click="lineClick('circle')">
|
||
<div class="drawCircularIcon"></div>
|
||
</div>
|
||
<!-- <div class="drawPolygon">
|
||
<el-upload
|
||
action=""
|
||
class="upload-demo"
|
||
:before-upload="beforeUpload"
|
||
:on-change="handleChange"
|
||
:file-list="fileList"
|
||
:show-file-list="false"
|
||
accept=".json"
|
||
:auto-upload="false"
|
||
ref="upLoad"
|
||
>
|
||
<i class="el-icon-upload2"></i>
|
||
</el-upload>
|
||
</div> -->
|
||
</div>
|
||
<div class="toolbar" v-if="typeOf === 'pointP'">
|
||
<div class="drawPolygon" @click="lineClicks('pointP')">
|
||
<div class="drawpointIcon"></div>
|
||
</div>
|
||
</div>
|
||
<div class="topbtns">
|
||
<el-input
|
||
v-model="lonData"
|
||
:disabled="isinputDisabled"
|
||
placeholder="请输入经度"
|
||
></el-input>
|
||
<el-input
|
||
v-model="latData"
|
||
:disabled="isinputDisabled"
|
||
placeholder="请输入纬度"
|
||
></el-input>
|
||
<el-button @click="handleSearchClick()">定位</el-button>
|
||
<el-button class="btns" @click="clearDraw">清空</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
"use script";
|
||
import { Drawarectangle } from "./map.js";
|
||
import iconimg from "@/assets/img/dianweidingweiqizi.png";
|
||
export default {
|
||
name: "myMarsmap",
|
||
props: {
|
||
mapData: {
|
||
type: Object,
|
||
default: () => {}
|
||
},
|
||
mapgeoJson: {
|
||
type: String,
|
||
default: ""
|
||
},
|
||
typeOf: {
|
||
type: String
|
||
},
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
jsonData: [],
|
||
lon: "",
|
||
lat: "",
|
||
num: 0,
|
||
attrType: "",
|
||
fileList: [],
|
||
lonData: "",
|
||
latData: "",
|
||
fileContent: "",
|
||
isDisabled: false,
|
||
isinputDisabled: false
|
||
};
|
||
},
|
||
components: {},
|
||
mounted() {
|
||
this.getMapJson();
|
||
console.log(this.typeOf, "this.typeOf");
|
||
},
|
||
watch: {
|
||
mapgeoJson: {
|
||
deep: true,
|
||
immediate: true,
|
||
handler(newVal) {
|
||
console.log("newVal1111", newVal);
|
||
if (newVal) {
|
||
this.jsonData = JSON.parse(newVal);
|
||
if (this.jsonData) {
|
||
this.showRegion(this.jsonData, "geojson");
|
||
}
|
||
}
|
||
}
|
||
},
|
||
mapData: {
|
||
deep: true,
|
||
immediate: true,
|
||
handler(newVal) {
|
||
if (newVal) {
|
||
if (newVal.lon && newVal.lat) {
|
||
this.lonData = newVal.lon;
|
||
this.latData = newVal.lat;
|
||
} else {
|
||
this.lonData = "";
|
||
this.latData = "";
|
||
}
|
||
if (this.lonData && this.latData) {
|
||
if (this.lonData && this.latData) {
|
||
this.isinputDisabled = true;
|
||
this.deviceDrid(this.lonData, this.latData);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
handleSearchClick() {
|
||
this.map.setCameraView(
|
||
{ lat: this.latData, lng: this.lonData, alt: 4607, pitch: -50 },
|
||
{ duration: 0 }
|
||
);
|
||
if (this.lonData && this.latData) {
|
||
this.isinputDisabled = true;
|
||
this.deviceDrid(this.lonData, this.latData);
|
||
}
|
||
},
|
||
getMapJson() {
|
||
// eslint-disable-next-line no-undef
|
||
mars3d.Util.fetchJson({
|
||
url: "/configJson/mapArea.json"
|
||
}).then((res) => {
|
||
this.initMarsMap({
|
||
// 合并配置项
|
||
...res.map3d
|
||
});
|
||
});
|
||
},
|
||
initMarsMap(options) {
|
||
// eslint-disable-next-line no-undef
|
||
this.map = new mars3d.Map(this.$refs.marsMaps, options);
|
||
// eslint-disable-next-line no-undef
|
||
this.graphicLayer = new mars3d.layer.GraphicLayer();
|
||
this.map.addLayer(this.graphicLayer);
|
||
|
||
// 设备点位
|
||
// eslint-disable-next-line no-undef
|
||
this.graphicDevice = new mars3d.layer.GraphicLayer();
|
||
this.map.addLayer(this.graphicDevice);
|
||
// 禁止右键菜单
|
||
this.map.unbindContextMenu();
|
||
this.map.setCameraView(
|
||
{
|
||
lat: "43.895464",
|
||
lng: "109.10559",
|
||
alt: 3269697,
|
||
pitch: -90,
|
||
heading: 360
|
||
},
|
||
{ duration: 0 }
|
||
);
|
||
|
||
// 针对不同终端的优化配置
|
||
// eslint-disable-next-line no-undef
|
||
if (mars3d.Util.isPCBroswer()) {
|
||
this.map.zoomFactor = 2.0; // 鼠标滚轮放大的步长参数
|
||
|
||
// IE浏览器优化
|
||
if (navigator.userAgent.toLowerCase().includes("msie")) {
|
||
this.map.viewer.targetFrameRate = 20; // 限制帧率
|
||
this.map.scene.requestRenderMode = false; // 取消实时渲染
|
||
}
|
||
} else {
|
||
this.map.zoomFactor = 5.0; // 鼠标滚轮放大的步长参数
|
||
|
||
// 移动设备上禁掉以下几个选项,可以相对更加流畅
|
||
this.map.scene.requestRenderMode = false; // 取消实时渲染
|
||
this.map.scene.fog.enabled = false;
|
||
this.map.scene.skyAtmosphere.show = false;
|
||
this.map.scene.globe.showGroundAtmosphere = false;
|
||
}
|
||
|
||
// map构造完成后的一些处理
|
||
this.onMapLoad();
|
||
// this.map.on(
|
||
// // eslint-disable-next-line no-undef
|
||
// mars3d.EventType.click,
|
||
// this.map_dblClickHandler,
|
||
// this.graphicLayer
|
||
// );
|
||
// this.map.on(mars3d.EventType.dblClick, map_clickHandler, graphicLayer)
|
||
},
|
||
// map_dblClickHandler() {},
|
||
onMapLoad() {
|
||
console.log("地图加载完成", this.graphicLayer);
|
||
// 设置鼠标操作习惯,更换中键和右键
|
||
this.map.changeMouseModel(true);
|
||
if (this.jsonData.length !== 0) {
|
||
this.showRegion(this.jsonData, "geojson");
|
||
}
|
||
if (this.lonData && this.latData) {
|
||
this.deviceDrid(this.lonData, this.latData);
|
||
this.isinputDisabled = true;
|
||
}
|
||
},
|
||
lineClicks(val) {
|
||
this.clearDraw();
|
||
this.graphicLayer.eachGraphic((item) => {
|
||
if (item.id === "pointP") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
let style = {};
|
||
style = {
|
||
color: "#ffff00",
|
||
pixelSize: 10,
|
||
clampToGround: true,
|
||
outlineWidth: 0
|
||
};
|
||
|
||
Drawarectangle(val, this.graphicLayer, style);
|
||
},
|
||
lineClick(val) {
|
||
if (this.typeOf === "polygon") {
|
||
this.attrType = val;
|
||
|
||
// 检查 graphicLayer 中的图形
|
||
const graphicsArray = this.graphicLayer._graphicList._array || [];
|
||
let hasPolygon = false;
|
||
let hasCircle = false;
|
||
|
||
// 遍历检查是否有 polygon 或 circle
|
||
graphicsArray.forEach((graphic) => {
|
||
if (graphic.type === "polygon") {
|
||
hasPolygon = true;
|
||
} else if (graphic.type === "circle") {
|
||
hasCircle = true;
|
||
}
|
||
});
|
||
|
||
let style = {};
|
||
if (val === "polygon") {
|
||
// 如果已有 polygon 或 circle,限制只能绘制一个 polygon
|
||
if (hasPolygon) {
|
||
this.$message.error("已存在,请先清空");
|
||
return; // 阻止继续执行
|
||
}
|
||
if (hasCircle) {
|
||
// 清除已有 circle
|
||
this.graphicLayer.eachGraphic((item) => {
|
||
if (item.type === "circle") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
}
|
||
style = {
|
||
materialType: mars3d.MaterialType.PolyGradient,
|
||
materialOptions: {
|
||
color: "#3388cc",
|
||
opacity: 0.7,
|
||
alphaPower: 1.3
|
||
}
|
||
};
|
||
} else if (val === "pointP") {
|
||
// pointP 可以与 polygon 或 circle 共存,仅清除已有 pointP
|
||
this.graphicLayer.eachGraphic((item) => {
|
||
if (item.id === "pointP") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
style = {
|
||
color: "#ffff00",
|
||
pixelSize: 10,
|
||
clampToGround: true,
|
||
outlineWidth: 0
|
||
};
|
||
} else if (val === "circle") {
|
||
// 如果已有 circle 或 polygon,限制只能绘制一个 circle
|
||
if (hasCircle) {
|
||
this.$message.error("已存在,请先清空");
|
||
return; // 阻止继续执行
|
||
}
|
||
if (hasPolygon) {
|
||
// 清除已有 polygon
|
||
this.graphicLayer.eachGraphic((item) => {
|
||
if (item.type === "polygon") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
}
|
||
style = {
|
||
materialType: mars3d.MaterialType.PolyGradient,
|
||
materialOptions: {
|
||
color: "#3388cc",
|
||
opacity: 0.7,
|
||
alphaPower: 1.3
|
||
}
|
||
};
|
||
}
|
||
|
||
// 如果 val 是 polygon 或 circle,且已有另一种类型,则提示并阻止
|
||
if (
|
||
(hasPolygon && val === "circle") ||
|
||
(hasCircle && val === "polygon")
|
||
) {
|
||
this.$message.error("只能显示一种类型,已清空");
|
||
return; // 阻止继续执行
|
||
}
|
||
|
||
// 绘制新图形
|
||
Drawarectangle(val, this.graphicLayer, style);
|
||
}
|
||
},
|
||
clearDraw() {
|
||
console.log(111);
|
||
this.isinputDisabled = false;
|
||
if (this.graphicLayer) {
|
||
this.graphicLayer.clear();
|
||
}
|
||
},
|
||
toGeoJSON() {
|
||
if (this.typeOf === "pointP") {
|
||
return this.graphicLayer.toGeoJSON({ noAlt: true });
|
||
} else {
|
||
this.graphicLayer._graphicList._array.forEach((item) => {
|
||
if (item.type === "billboard") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
return this.graphicLayer.toGeoJSON({ noAlt: true });
|
||
}
|
||
},
|
||
showRegion(value, type) {
|
||
this.clearDraw();
|
||
let geojson = {};
|
||
if (type === "uploadGeojson") {
|
||
if (this.graphicLayer._graphicList.length === 0) {
|
||
geojson = value;
|
||
} else {
|
||
this.$message.error("请先清空数据在添加");
|
||
}
|
||
} else {
|
||
geojson = {
|
||
type: "Feature",
|
||
geometry: value,
|
||
properties: {
|
||
name: ""
|
||
}
|
||
};
|
||
this.clearDraw();
|
||
}
|
||
if (this.graphicLayer) {
|
||
this.graphicLayer.loadGeoJSON(geojson, {
|
||
style: {
|
||
type: "polygon",
|
||
// eslint-disable-next-line no-undef
|
||
materialType: mars3d.MaterialType.PolyGradient,
|
||
materialOptions: {
|
||
color: "#3388cc",
|
||
opacity: 0.7,
|
||
alphaPower: 1.3
|
||
}
|
||
},
|
||
flyTo: true
|
||
});
|
||
let _this = this;
|
||
// eslint-disable-next-line no-undef
|
||
this.graphicLayer.on(mars3d.EventType.click, function (event) {
|
||
_this.attrType = "";
|
||
console.log("单击了图层", event);
|
||
});
|
||
}
|
||
},
|
||
deviceDrid(lon, lat) {
|
||
console.log(this.graphicLayer, "this.graphicLayer");
|
||
if (this.graphicLayer) {
|
||
this.graphicLayer.eachGraphic((item) => {
|
||
if (item.name === "贴地点") {
|
||
this.graphicLayer.removeGraphic(item);
|
||
}
|
||
});
|
||
}
|
||
|
||
const graphic = new mars3d.graphic.BillboardEntity({
|
||
position: new mars3d.LngLatPoint(lon, lat),
|
||
style: {
|
||
image: iconimg,
|
||
scale: 1,
|
||
width: 30,
|
||
height: 50,
|
||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
|
||
},
|
||
flyTo: true
|
||
});
|
||
|
||
if (this.graphicLayer) {
|
||
this.graphicLayer.addGraphic(graphic);
|
||
}
|
||
console.log(this.graphicLayer, "this.graphicLayer");
|
||
},
|
||
// 地图跳转
|
||
mapJump(lon, lat, alt) {
|
||
if (lon !== 0 && lat !== 0) {
|
||
this.map.setCameraView({
|
||
lat: lat,
|
||
lng: lon,
|
||
alt: alt || 10000,
|
||
pitch: -90
|
||
});
|
||
}
|
||
},
|
||
clearDevice() {
|
||
if (this.graphicDevice) {
|
||
this.graphicDevice.clear();
|
||
}
|
||
},
|
||
// 设备点位
|
||
mapDevice(lon, lat) {
|
||
if (lon !== null && lat !== null) {
|
||
this.clearDevice();
|
||
// eslint-disable-next-line no-undef
|
||
const graphic = new mars3d.graphic.PointPrimitive({
|
||
name: "设备点位",
|
||
// eslint-disable-next-line no-undef
|
||
position: new mars3d.LngLatPoint(lon, lat),
|
||
style: {
|
||
color: "#ff0000",
|
||
pixelSize: 10,
|
||
clampToGround: true,
|
||
outlineWidth: 0
|
||
},
|
||
flyTo: true
|
||
});
|
||
if (this.graphicDevice) {
|
||
this.graphicDevice.addGraphic(graphic);
|
||
}
|
||
} else {
|
||
this.clearDevice();
|
||
}
|
||
},
|
||
beforeUpload(file) {
|
||
console.log(file);
|
||
// const isJson = file.type === "json/geojson";
|
||
// if (!isJson) {
|
||
// this.$message.error("只能上传 JSON 或 GeoJSON 文件");
|
||
// }
|
||
// return isJson;
|
||
const isJPG = file.type === "image/jpeg";
|
||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||
|
||
if (!isJPG) {
|
||
this.$message.error("上传头像图片只能是 JPG 格式!");
|
||
}
|
||
if (!isLt2M) {
|
||
this.$message.error("上传头像图片大小不能超过 2MB!");
|
||
}
|
||
return isJPG && isLt2M;
|
||
},
|
||
handleChange(file) {
|
||
console.log(file);
|
||
const reader = new FileReader();
|
||
reader.onload = (e) => {
|
||
const content = e.target.result;
|
||
this.fileContent = JSON.parse(content);
|
||
console.log(this.fileContent);
|
||
this.showRegion(this.fileContent, "uploadGeojson");
|
||
};
|
||
reader.readAsText(file.raw);
|
||
// this.$refs.upLoad.submit();
|
||
},
|
||
isGeoJSON(content) {
|
||
try {
|
||
// eslint-disable-next-line no-undef
|
||
const multiPolygon = turf.multiPolygon(content);
|
||
console.log("MultiPolygon is valid:", multiPolygon);
|
||
} catch (error) {
|
||
console.error("Error processing MultiPolygon:", error);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.ditu {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
#marsContainer-map {
|
||
width: 100%;
|
||
height: 250px;
|
||
}
|
||
.topbtns {
|
||
width: 100%;
|
||
height: 45px;
|
||
position: absolute;
|
||
top: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
background-color: rgba(30, 93, 160, 0.5);
|
||
.el-input {
|
||
width: 30%;
|
||
margin-left: 1%;
|
||
// transform: translateX(-50%);
|
||
}
|
||
.el-button--small {
|
||
margin-left: 10px;
|
||
}
|
||
}
|
||
.toolbar {
|
||
position: absolute;
|
||
right: 0%;
|
||
top: 20%;
|
||
z-index: 999;
|
||
height: auto;
|
||
display: flex;
|
||
align-items: center;
|
||
.disabled {
|
||
pointer-events: none;
|
||
opacity: 0.5;
|
||
}
|
||
.drawPolygon {
|
||
width: 40px;
|
||
height: 40px;
|
||
margin-top: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
background: rgba(15, 24, 41, 0.5);
|
||
border-radius: 8px;
|
||
margin-right: 5px;
|
||
.drawPolygonIcon {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/wbx.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.drawPolygonIcon:hover {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/wbxH.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.drawCircularIcon {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/y.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.drawCircularIcon:hover {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/yh.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.drawpointIcon {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/point.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.drawpointIcon:hover {
|
||
width: 20px;
|
||
height: 20px;
|
||
background: url(@/assets/img/pointh.png);
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center;
|
||
cursor: pointer;
|
||
}
|
||
.el-icon-upload2 {
|
||
color: #fff;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
}
|
||
.el-icon-upload2:hover {
|
||
color: #1e5da0;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|