地图编写

main
项洋 2 days ago
parent ad8847e0df
commit a7c57ae5c6

@ -35,13 +35,16 @@
"js-cookie": "2.2.0",
"js-md5": "^0.7.3",
"jszip": "^3.7.1",
"leaflet": "^1.9.4",
"lottie-web": "^5.7.13",
"mapbox-gl": "^2.6.1",
"mars2d": "^3.3.2",
"moment": "^2.27.0",
"mux.js": "^5.6.4",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"proj4": "^2.16.2",
"qs": "^6.9.4",
"save": "^2.4.0",
"swiper": "^7.2.0",

@ -52,10 +52,10 @@ export default {
// this.reportTotalCount = res.data.reportTotalCount
// this.completedPercent = res.data.completedPercent
// })
screenreportmap().then(res => {
this.reportTotalCount = res.data.count
this.completedPercent = this.isInteger(res.data.rate) ? res.data.rate : res.data.rate.toFixed(2)
});
// screenreportmap().then(res => {
// this.reportTotalCount = res.data.count
// this.completedPercent = this.isInteger(res.data.rate) ? res.data.rate : res.data.rate.toFixed(2)
// });
// console.log(data)
}

@ -849,32 +849,7 @@ export default {
],
};
// 2000
proj4.defs(
"EPSG:4527",
"+proj=tmerc +lat_0=0 +lon_0=120.75 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"
);
function transformGeoJSON(geojson) {
//
const result = JSON.parse(JSON.stringify(geojson));
//
if (result.features) {
result.features.forEach((feature) => {
if (feature.geometry.type === "Polygon") {
feature.geometry.coordinates.forEach((ring) => {
for (let i = 0; i < ring.length; i++) {
const transformed = proj4("EPSG:4527", "EPSG:4326", ring[i]);
ring[i] = transformed;
}
});
}
});
}
return result;
}
const transformedData = transformGeoJSON(originalGeoJSON.value);
console.log(transformedData);
},
//

@ -1,6 +1,6 @@
<template>
<div class="map-container">
<div id="container"></div>
<!-- <div id="container"></div> -->
<el-dialog
v-if="isShowDialog"
title=""

@ -1,449 +1,175 @@
<template>
<div class="map-container">
<div id="container"></div>
<!-- 信息弹窗 -->
<div class="map-overlay" v-if="showOverlay">
<div class="overlay-content">
<div class="overlay-header">
<div class="overlay-title">{{ currentDistrict.name }}</div>
<div class="overlay-close" @click="showOverlay = false">×</div>
</div>
<div class="overlay-body">
<div class="data-stats">
<div class="stat-item">
<div class="stat-value">{{ currentDistrict.issues || 0 }}</div>
<div class="stat-label">问题数量</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ currentDistrict.reports || 0 }}</div>
<div class="stat-label">举报数量</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ currentDistrict.handled || 0 }}</div>
<div class="stat-label">处理数量</div>
</div>
</div>
<div class="problem-list" v-if="currentDistrict.problemList && currentDistrict.problemList.length">
<div class="problem-title">主要问题类型</div>
<div class="problem-item" v-for="(item, index) in currentDistrict.problemList" :key="index">
<span class="problem-dot"></span>
<span class="problem-name">{{ item.name }}</span>
<span class="problem-value">{{ item.value }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- 数据卡片 -->
<div class="data-card">
<div class="data-card-title">数据信息</div>
<div class="data-card-content">
<div class="data-row">
<div class="data-label">网络动态:</div>
<div class="data-value highlight">88 </div>
</div>
<div class="data-row">
<div class="data-label">舆情事件:</div>
<div class="data-value highlight">78 </div>
</div>
<div class="data-row">
<div class="data-label">举报事件:</div>
<div class="data-value highlight">24 </div>
</div>
</div>
</div>
<div class="map-label">苏州工业园</div>
<div class="map-radial-bg"></div>
</div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import * as echarts from 'echarts';
import * as mars2d from "mars2d";
import * as turf from "@turf/turf";
import geoData from "./gongyeyuan.json";
import shadow1Data from "./阴影1.json";
import shadow2Data from "./阴影2.json";
import shadow3Data from "./阴影3.json";
// Mars2D
import "mars2d/dist/mars2d.css";
export default {
data() {
return {
center: [120.75, 31.32],
zoom: 12.5,
map: null,
districtLayer: null,
showOverlay: false,
currentDistrict: {},
districts: [
{
id: 1,
name: "苏州工业园区金鸡湖商务区",
center: [120.7214, 31.3217],
issues: 24,
reports: 68,
handled: 56,
problemList: [
{ name: "网络违法行为", value: 12 },
{ name: "有害信息传播", value: 8 },
{ name: "信息安全隐患", value: 4 }
]
},
{
id: 2,
name: "苏州工业园区高新制造与国际贸易区",
center: [120.7531, 31.2945],
issues: 32,
reports: 45,
handled: 38,
problemList: [
{ name: "网络违法行为", value: 14 },
{ name: "有害信息传播", value: 10 },
{ name: "信息安全隐患", value: 8 }
]
},
{
id: 3,
name: "苏州阳澄湖半岛旅游度假区",
center: [120.7895, 31.3915],
issues: 15,
reports: 29,
handled: 22,
problemList: [
{ name: "网络违法行为", value: 7 },
{ name: "有害信息传播", value: 5 },
{ name: "信息安全隐患", value: 3 }
]
},
{
id: 4,
name: "苏州独墅湖科教创新区",
center: [120.7364, 31.2650],
issues: 18,
reports: 36,
handled: 30,
problemList: [
{ name: "网络违法行为", value: 8 },
{ name: "有害信息传播", value: 6 },
{ name: "信息安全隐患", value: 4 }
]
}
],
// markerImages: {
// blue: require('@/assets/ecosphere/blue-marker.png'),
// red: require('@/assets/ecosphere/red-marker.png'),
// },
mapStyle: [
{
"featureType": "land",
"elementType": "geometry",
"stylers": {
"color": "#081220",
"visibility": "on"
}
},
{
"featureType": "water",
"elementType": "geometry",
"stylers": {
"color": "#0e253d",
"visibility": "on"
}
},
{
"featureType": "green",
"elementType": "geometry",
"stylers": {
"color": "#0c1f34",
"visibility": "on"
}
},
{
"featureType": "building",
"elementType": "geometry",
"stylers": {
"color": "#113549",
"visibility": "on"
}
},
{
"featureType": "road",
"elementType": "geometry",
"stylers": {
"color": "#193e5e",
"visibility": "on"
}
},
{
"featureType": "road",
"elementType": "labels",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "highway",
"elementType": "geometry",
"stylers": {
"color": "#193e5e",
"visibility": "on"
}
},
{
"featureType": "highway",
"elementType": "labels",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "nationalway",
"elementType": "geometry",
"stylers": {
"color": "#193e5e",
"visibility": "on"
}
},
{
"featureType": "nationalway",
"elementType": "labels",
"stylers": {
"visibility": "off"
}
},
{
"featureType": "provincialway",
"elementType": "geometry",
"stylers": {
"color": "#193e5e",
"visibility": "on"
}
},
{
"featureType": "provincialway",
"elementType": "labels",
"stylers": {
"visibility": "off"
}
}
]
layers: []
};
},
mounted() {
this.$nextTick(() => {
this.initMap();
this.initMars2dMap();
});
},
methods: {
async initMap() {
// Mars2D
initMars2dMap() {
try {
// API
const AMap = await AMapLoader.load({
key: "b3c7a7ce466721c3be1d4ea539f82421",
version: "2.0",
plugins: [
'AMap.DistrictSearch',
'AMap.DistrictLayer'
]
});
// dom
const containerEl = document.getElementById("container");
if (!containerEl) {
console.error("地图容器不存在");
return;
}
//
containerEl.style.width = "100%";
containerEl.style.height = "100%";
containerEl.style.position = "absolute";
containerEl.style.top = "0";
containerEl.style.left = "0";
containerEl.style.zIndex = "-1";
containerEl.style.pointerEvents = "none";
containerEl.style.backgroundColor = "transparent";
//
const mapOptions = {
zoom: this.zoom,
center: this.center,
minZoom: this.zoom,
maxZoom: this.zoom,
zoomControl: false,
dragging: false,
doubleClickZoom: false,
scrollWheelZoom: false,
keyboard: false,
touchZoom: false,
boxZoom: false,
worldCopyJump: false,
continuousWorld: true,
attributionControl: false,
basemap: {
name: "黑色底图",
type: "empty",
}
};
//
this.map = new AMap.Map("container", {
zoom: 11.5,
center: [120.7389, 31.2909], //
viewMode: "3D",
pitch: 35,
rotation: 0,
mapStyle: 'amap://styles/darkblue',
expandZoomRange: true,
zooms: [8, 20],
showBuildingBlock: false,
showLabel: false,
skyColor: 'transparent',
backgroundColor: 'transparent',
features: ['bg', 'road'],
//
dragEnable: true,
zoomEnable: true,
doubleClickZoom: true,
keyboardEnable: true,
rotateEnable: true
//
this.map = new mars2d.Map("container", mapOptions);
//
this.map.on("error", (error) => {
console.error("地图加载错误:", error);
});
//
this.createCustomMap();
//
this.map.on("load", () => {
console.log("地图加载完成");
setTimeout(() => {
this.create4LayerEffect();
}, 500);
});
} catch (error) {
console.error("地图加载失败", error);
console.error("地图初始化失败:", error);
}
},
//
createCustomMap() {
//
const parkBoundary = [
[120.7214, 31.3317], [120.7714, 31.3417], [120.7894, 31.3307],
[120.7994, 31.3107], [120.7894, 31.2907], [120.7714, 31.2707],
[120.7514, 31.2607], [120.7314, 31.2607], [120.7114, 31.2707],
[120.6914, 31.2907], [120.6914, 31.3107], [120.7114, 31.3307]
];
// 使
const subDistricts = [
{
name: "苏州阳澄湖半岛旅游度假区",
coordinates: [
[120.7214, 31.3517], [120.7714, 31.3617], [120.7894, 31.3407],
[120.7614, 31.3307], [120.7414, 31.3407]
],
center: [120.7614, 31.3417],
markerType: "blue"
},
{
name: "苏州工业园区高新制造与国际贸易区",
coordinates: [
[120.7614, 31.3007], [120.7894, 31.3107], [120.7894, 31.2907],
[120.7714, 31.2707], [120.7514, 31.2807], [120.7514, 31.2907]
],
center: [120.7714, 31.2907],
markerType: "blue"
},
{
name: "苏州工业园区金鸡湖商务区",
coordinates: [
[120.7114, 31.3107], [120.7514, 31.3207], [120.7514, 31.2907],
[120.7314, 31.2807], [120.7114, 31.2907]
],
center: [120.7314, 31.3007],
markerType: "red"
},
{
name: "苏州独墅湖科教创新区",
coordinates: [
[120.7214, 31.2707], [120.7414, 31.2607], [120.7614, 31.2507],
[120.7414, 31.2407], [120.7214, 31.2507]
],
center: [120.7414, 31.2607],
markerType: "blue"
}
];
//
this.createDistrictPolygon(parkBoundary, {
strokeColor: '#00eaff',
strokeWeight: 3,
fillColor: '#3ecbff',
fillOpacity: 0.3,
strokeStyle: 'solid',
zIndex: 2
});
//
this.createDistrictPolygon(parkBoundary, {
strokeColor: '#00eaff',
strokeWeight: 6,
fillColor: 'transparent',
fillOpacity: 0,
strokeOpacity: 0.4,
zIndex: 1
});
//
subDistricts.forEach(district => {
//
this.createDistrictPolygon(district.coordinates, {
strokeColor: '#00eaff',
strokeWeight: 2,
fillColor: '#3ecbff',
fillOpacity: 0.2,
zIndex: 3
// 4
create4LayerEffect() {
try {
console.log("开始创建4层立体效果");
// 1: ()
const bottomLayer = new mars2d.layer.GeoJsonLayer({
data: shadow1Data,
style: {
color: "#00667a",
weight: 5,
opacity: 0.5,
fillColor: "#00667a",
fillOpacity: 0.18
}
});
//
this.createDistrictLabel(district.center, district.name);
//
this.createMarker(district.center, district.markerType);
});
//
this.addDataCard();
},
//
createDistrictPolygon(coordinates, style) {
const AMap = window.AMap;
if (!AMap) return;
const polygon = new AMap.Polygon({
path: coordinates,
...style
});
this.map.add(polygon);
return polygon;
},
//
createDistrictLabel(position, name) {
const AMap = window.AMap;
if (!AMap) return;
const textMarker = new AMap.Text({
text: name,
position: position,
style: {
'color': '#fff',
'background-color': 'transparent',
'font-size': '14px',
'font-weight': 'bold',
'text-shadow': '0 0 5px rgba(0, 0, 0, 0.8)'
},
zIndex: 10
});
this.map.add(textMarker);
return textMarker;
},
//
createMarker(position, type) {
const AMap = window.AMap;
if (!AMap) return;
// 使
const icon = type === 'red' ?
'//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png' :
'//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png';
//
const marker = new AMap.Marker({
position: position,
icon: new AMap.Icon({
image: icon,
size: new AMap.Size(24, 34),
imageSize: new AMap.Size(24, 34)
}),
offset: new AMap.Pixel(-12, -34),
zIndex: 11
});
//
this.map.add(marker);
//
const pulseMarker = new AMap.Marker({
position: position,
content: '<div class="pulse-marker-container"><div class="pulse-marker"></div></div>',
zIndex: 10,
offset: new AMap.Pixel(-10, -10)
});
this.map.add(pulseMarker);
return marker;
},
//
addDataCard() {
//
this.map.addLayer(bottomLayer);
// 2:
const middleLayer = new mars2d.layer.GeoJsonLayer({
data: shadow2Data,
style: {
color: "#0099b5",
weight: 3,
opacity: 0.7,
fillColor: "#0099b5",
fillOpacity: 0.25
}
});
this.map.addLayer(middleLayer);
// 3:
const topFillLayer = new mars2d.layer.GeoJsonLayer({
data: shadow3Data,
style: {
color: "#00c8e6",
weight: 2,
opacity: 0.8,
fillColor: "#00c8e6",
fillOpacity: 0.35
}
});
this.map.addLayer(topFillLayer);
// 4: 线
const edgeLayer = new mars2d.layer.GeoJsonLayer({
data: geoData,
style: {
color: "#7fffff",
weight: 1,
opacity: 1,
fillColor: "#40e6ff",
fillOpacity: 0.2
}
});
this.map.addLayer(edgeLayer);
// GeoJSON
try {
const bounds = topFillLayer.getBounds();
if (bounds && bounds.isValid()) {
this.map.fitBounds(bounds);
}
} catch (e) {
console.error("设置地图边界失败:", e);
}
} catch (error) {
console.error("创建3D效果失败:", error);
}
}
},
beforeDestroy() {
if (this.map) {
this.map.destroy();
this.map = null;
}
}
};
@ -451,211 +177,94 @@ export default {
<style lang="scss" scoped>
.map-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: relative;
background-color: transparent;
#container {
width: 100%;
height: 100%;
background-color: transparent !important;
}
.map-overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
width: 400px;
background: rgba(4, 32, 66, 0.8);
border: 1px solid #0a5080;
border-radius: 5px;
box-shadow: 0 0 15px rgba(0, 193, 222, 0.7);
overflow: hidden;
}
.overlay-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
background: rgba(10, 80, 128, 0.8);
border-bottom: 1px solid #0a5080;
}
.overlay-title {
color: #fff;
font-size: 18px;
font-weight: bold;
}
.overlay-close {
color: #fff;
font-size: 24px;
cursor: pointer;
width: 24px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
line-height: 1;
}
.overlay-body {
padding: 15px;
}
.data-stats {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
.stat-item {
flex: 1;
text-align: center;
padding: 0 10px;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #00c1de;
}
.stat-label {
font-size: 14px;
color: #ccc;
margin-top: 5px;
}
.problem-list {
background: rgba(10, 80, 128, 0.3);
border-radius: 5px;
padding: 10px;
}
.problem-title {
font-size: 16px;
color: #fff;
margin-bottom: 10px;
}
.problem-item {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.problem-dot {
width: 8px;
height: 8px;
background-color: #00c1de;
border-radius: 50%;
margin-right: 8px;
}
.problem-name {
flex: 1;
color: #ccc;
}
.problem-value {
color: #00c1de;
font-weight: bold;
}
.data-card {
position: absolute;
top: 20px;
right: 20px;
width: 300px;
background: rgba(4, 32, 66, 0.8);
border: 1px solid #0a5080;
border-radius: 5px;
box-shadow: 0 0 15px rgba(0, 193, 222, 0.3);
z-index: 9;
overflow: hidden;
}
.data-card-title {
padding: 10px 15px;
background: rgba(10, 80, 128, 0.8);
color: #fff;
font-size: 36px;
font-weight: bold;
border-bottom: 1px solid rgba(0, 193, 222, 0.3);
}
.data-card-content {
padding: 15px;
}
.data-row {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
}
.data-label {
color: #ccc;
font-size: 14px;
}
.data-value {
font-size: 14px;
}
.highlight {
color: #f7d342;
font-weight: bold;
}
overflow: hidden;
z-index: -1;
pointer-events: none;
perspective: 1200px;
}
/* 确保高德地图的背景透明 */
:global(.amap-container),
:global(.amap-maps),
:global(.amap-layers),
:global(.amap-layer) {
#container {
position: absolute;
left: 0;
top: 0;
width: 100% !important;
height: 100% !important;
z-index: -1;
background-color: transparent !important;
filter: drop-shadow(0 0 25px rgba(0, 210, 255, 0.7)) brightness(1.3) contrast(1.5) saturate(1.2);
transform: rotateX(60deg) rotateZ(-1deg) scale(0.85);
transform-style: preserve-3d;
transform-origin: center center;
}
/* 确保标记点和脉冲效果可以正常互动 */
:global(.amap-marker) {
pointer-events: auto;
}
/* 脉冲标记的样式 */
:global(.pulse-marker-container) {
position: relative;
width: 20px;
height: 20px;
}
:global(.pulse-marker) {
width: 12px;
height: 12px;
background: rgba(0, 193, 222, 0.7);
border-radius: 50%;
.map-label {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 10px rgba(0, 193, 222, 0.9);
animation: pulse 1.5s ease-in-out infinite;
color: rgba(255, 255, 255, 1);
font-size: 32px;
font-weight: bold;
text-shadow: 0 0 20px rgba(0, 225, 255, 1);
z-index: 10;
pointer-events: none;
white-space: nowrap;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(0, 193, 222, 0.9);
}
70% {
box-shadow: 0 0 0 15px rgba(0, 193, 222, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(0, 193, 222, 0);
}
.map-radial-bg {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: radial-gradient(circle at center, rgba(0, 20, 35, 0) 30%, rgba(0, 50, 70, 0.3) 70%, rgba(0, 60, 80, 0.5) 100%);
z-index: -2;
pointer-events: none;
}
/* 确保leaflet容器样式正确 */
:deep(.leaflet-container) {
background: transparent !important;
width: 100% !important;
height: 100% !important;
pointer-events: none !important;
}
/* 强制覆盖Mars2D内部样式 */
:deep(.mars2d-container) {
width: 100% !important;
height: 100% !important;
z-index: -1 !important;
pointer-events: none !important;
}
/* 隐藏控件 */
:deep(.leaflet-control-container) {
display: none !important;
}
/* 增强GeoJSON图层效果 */
:deep(.leaflet-overlay-pane) {
z-index: -1 !important;
filter: drop-shadow(0 0 25px rgba(0, 220, 255, 0.8));
}
:deep(.leaflet-pane) {
z-index: -1 !important;
pointer-events: none !important;
}
:deep(.leaflet-tile-pane) {
opacity: 0 !important;
}
/* 路径特效 */
:deep(.leaflet-interactive) {
transition: all 0.3s ease-in-out;
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,18 +1,18 @@
<template>
<div class="main">
<!-- <div class="map" style="z-index:2;">
<div class="center-container" style="z-index: 1">
<component-mapbox />
</div> -->
</div>
<div class="left-container" style="z-index: 3">
<div class="left-container" style="z-index: 100">
<component-left />
</div>
<div class="right-container" style="z-index: 3">
<div class="right-container" style="z-index: 100">
<component-right />
</div>
<div class="center-container" style="z-index: 3">
<!-- <div class="center-container" style="z-index: 3">
<component-center />
</div>
</div> -->
</div>
</template>
@ -21,14 +21,14 @@ import ComponentMapbox from "./components/componentmapbox.vue";
import ComponentLeft from "./components/componentLeft.vue";
import ComponentRight from "./components/componentRight.vue";
// import ComponentCenter from './components/componentCenter'
import ComponentCenter from "../security/components/componentCenter.vue";
// import ComponentCenter from "../security/components/componentCenter.vue";
export default {
name: "ecosphere",
components: {
ComponentLeft,
ComponentRight,
ComponentCenter,
// ComponentCenter,
ComponentMapbox,
},
data() {
@ -82,18 +82,19 @@ export default {
position: relative;
background: url("~@/assets/sentimeent/背景底图.png") no-repeat;
background-size: 100% 100%;
z-index: 1;
// z-index: 999;
// mix-blend-mode: overlay;
// pointer-events: none;
}
.map {
position: absolute;
z-index: 2;
width: 100%;
height: 100%;
background-color: transparent;
pointer-events: auto;
}
.left-container {
z-index: 3;
z-index: 100; /* 提高z-index确保在地图之上 */
position: absolute;
left: 0;
top: 0;
@ -105,7 +106,7 @@ export default {
}
.right-container {
z-index: 3;
z-index: 100; /* 提高z-index确保在地图之上 */
position: absolute;
right: 0;
top: 0;
@ -118,10 +119,11 @@ export default {
.center-container {
position: absolute;
z-index: 3;
left: 35%;
margin: 0 auto;
width: 1914px;
z-index: 1; /* 地图容器层级设为最低 */
left: 0;
top: 0;
margin: 0;
width: 100%;
height: 100%;
pointer-events: auto;
}

Loading…
Cancel
Save