You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1926 lines
60 KiB
HTML
1926 lines
60 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>中国敏感海域问题事件热点图</title>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.0/echarts.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts-gl/2.0.0/echarts-gl.min.js"></script>
|
|
<!-- 确保这些文件路径正确 -->
|
|
<script src="./model/mars3d-cesium/Build/Cesium/Cesium.js"></script>
|
|
<link href="./model/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
|
|
<script src="./model/mars3d/mars3d.js"></script>
|
|
<link href="./model/mars3d/mars3d.css" rel="stylesheet">
|
|
<!-- Mars3D热力图插件 - 使用正确的CDN路径 -->
|
|
<!-- <script src="https://cdn.jsdelivr.net/npm/mars3d-plugin-heatmap/dist/mars3d-plugin-heatmap.min.js"></script> -->
|
|
|
|
<style>
|
|
/* 控制面板内容区域添加滚动条 */
|
|
.control-panel-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding-right: 10px;
|
|
margin-right: -10px;
|
|
}
|
|
|
|
/* 美化控制面板内容区域的滚动条 */
|
|
.control-panel-content::-webkit-scrollbar {
|
|
width: 4px;
|
|
}
|
|
|
|
.control-panel-content::-webkit-scrollbar-track {
|
|
background: rgba(12, 42, 73, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.control-panel-content::-webkit-scrollbar-thumb {
|
|
background: rgba(79, 195, 247, 0.5);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.control-panel-content::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(79, 195, 247, 0.8);
|
|
}
|
|
|
|
/* 替换原有的过滤器样式为以下代码 */
|
|
|
|
/* 修改过滤器相关样式 */
|
|
.filter-options {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.filter-option {
|
|
display: flex;
|
|
align-items: center;
|
|
position: relative;
|
|
padding-left: 30px;
|
|
margin-bottom: 5px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.filter-option:hover {
|
|
transform: translateX(5px);
|
|
background: rgba(40, 80, 130, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.filter-option input[type="checkbox"] {
|
|
position: absolute;
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
height: 0;
|
|
width: 0;
|
|
}
|
|
|
|
.filter-option .checkmark {
|
|
position: absolute;
|
|
left: 0;
|
|
height: 20px;
|
|
width: 20px;
|
|
background-color: rgba(25, 55, 95, 0.6);
|
|
border: 2px solid #4fc3f7;
|
|
border-radius: 4px;
|
|
transition: all 0.3s ease;
|
|
pointer-events: all;
|
|
/* 确保可以点击 */
|
|
}
|
|
|
|
.filter-option:hover .checkmark {
|
|
background-color: rgba(79, 195, 247, 0.2);
|
|
}
|
|
|
|
.filter-option input:checked~.checkmark {
|
|
background-color: #4fc3f7;
|
|
}
|
|
|
|
.filter-option .checkmark:after {
|
|
content: "";
|
|
position: absolute;
|
|
display: none;
|
|
}
|
|
|
|
.filter-option input:checked~.checkmark:after {
|
|
display: block;
|
|
}
|
|
|
|
.filter-option .checkmark:after {
|
|
left: 6px;
|
|
top: 2px;
|
|
width: 6px;
|
|
height: 10px;
|
|
border: solid white;
|
|
border-width: 0 2px 2px 0;
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
.filter-option label {
|
|
font-size: 0.95rem;
|
|
color: #e0f0ff;
|
|
padding: 5px 0;
|
|
cursor: pointer;
|
|
width: 100%;
|
|
margin-left: 10px;
|
|
user-select: none;
|
|
/* 防止文本选择 */
|
|
}
|
|
|
|
.control-title {
|
|
font-size: 1.1rem;
|
|
margin: 15px 0 10px 0;
|
|
color: #4fc3f7;
|
|
padding-bottom: 5px;
|
|
border-bottom: 1px solid rgba(79, 195, 247, 0.3);
|
|
}
|
|
|
|
.control-group {
|
|
margin-bottom: 20px;
|
|
padding: 10px;
|
|
background: rgba(16, 36, 62, 0.3);
|
|
border-radius: 8px;
|
|
border: 1px solid rgba(64, 156, 255, 0.2);
|
|
}
|
|
|
|
/* 优化滚动条以确保内容可见 */
|
|
/* .info-panel {
|
|
overflow-y: auto;
|
|
} */
|
|
|
|
/* 美化滚动条 */
|
|
.info-panel::-webkit-scrollbar {
|
|
width: 4px;
|
|
}
|
|
|
|
.info-panel::-webkit-scrollbar-track {
|
|
background: rgba(12, 42, 73, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.info-panel::-webkit-scrollbar-thumb {
|
|
background: rgba(79, 195, 247, 0.5);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.info-panel::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(79, 195, 247, 0.8);
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
font-family: 'Segoe UI', Arial, sans-serif;
|
|
}
|
|
|
|
body {
|
|
background: url('/assets/img/bg.png') no-repeat;
|
|
background-size: 100% 100%;
|
|
color: #e0f0ff;
|
|
overflow: hidden;
|
|
height: 100vh;
|
|
}
|
|
|
|
/* 定义本地字体 */
|
|
@font-face {
|
|
font-family: 'DS-Digital';
|
|
/* 自定义字体族名称 */
|
|
src: url('/assets/fonts/DS-Digita.TTF') format('truetype');
|
|
/* 指定字体文件路径和格式 */
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
}
|
|
|
|
/* 定义本地字体 */
|
|
@font-face {
|
|
font-family: 'pmzd';
|
|
/* 自定义字体族名称 */
|
|
src: url('/assets/fonts/PMZD.TTF') format('truetype');
|
|
/* 指定字体文件路径和格式 */
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'YouSheBiaoTiHei';
|
|
/* 自定义字体族名称 */
|
|
src: url('/assets/fonts/YouSheBiaoTiHei.ttf') format('truetype');
|
|
/* 指定字体文件路径和格式 */
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'qweather';
|
|
/* 自定义字体族名称 */
|
|
src: url('/assets/fonts/qweather-icons.ttf') format('truetype');
|
|
/* 指定字体文件路径和格式 */
|
|
font-weight: normal;
|
|
font-style: normal;
|
|
}
|
|
|
|
/* 新增顶部标题栏样式 */
|
|
.topDiv {
|
|
width: 100%;
|
|
height: 8vh;
|
|
background: url('/assets/img/topBg2.png') top no-repeat;
|
|
background-size: 100% 115%;
|
|
display: flex;
|
|
justify-content: center;
|
|
z-index: 990;
|
|
position: relative;
|
|
/* background-color: rgba(12, 42, 73, 0.8); */
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.topDiv .center {
|
|
font-family: 'pmzd', 'DS-Digital', 'PangMenZhengDao', 'Source Han Sans CN', sans-serif;
|
|
/* 优先使用 DS-Digital 字体 */
|
|
/* font-family: PangMenZhengDao, 'Source Han Sans CN'; */
|
|
font-weight: 400;
|
|
font-size: 4vh;
|
|
color: #ffffff;
|
|
align-self: center;
|
|
margin-top: -10px;
|
|
}
|
|
|
|
.topDiv .left {
|
|
position: absolute;
|
|
top: 4vh;
|
|
left: 3vw;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.topDiv .left span:nth-child(1) {
|
|
font-weight: bold;
|
|
font-size: 0.8vw;
|
|
margin-right: 0.5vh;
|
|
}
|
|
|
|
.topDiv .left span:nth-child(2) {
|
|
font-weight: bold;
|
|
font-size: 1.2vw;
|
|
}
|
|
|
|
.topDiv .right {
|
|
position: absolute;
|
|
top: 3vh;
|
|
right: 0;
|
|
color: #ffffff;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.topDiv .right img:nth-child(1) {}
|
|
|
|
.topDiv .right span {
|
|
font-weight: bold;
|
|
font-size: 1.2vw;
|
|
}
|
|
|
|
.topDiv .icon-home {
|
|
position: absolute;
|
|
top: 1vh;
|
|
right: 8vw;
|
|
width: 4vh;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.container {
|
|
display: flex;
|
|
height: calc(100vh - 8vh - 20px);
|
|
position: relative;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
/* 左侧信息面板 */
|
|
.info-panel {
|
|
width: 300px;
|
|
height: 100%;
|
|
padding: 20px;
|
|
background: rgba(12, 42, 73, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
box-shadow: 5px 0 15px rgba(0, 0, 0, 0.3);
|
|
z-index: 10;
|
|
border-radius: 8px;
|
|
position: absolute;
|
|
left: 15px;
|
|
top: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 右侧控制面板 */
|
|
.control-panel {
|
|
width: 280px;
|
|
height: 100%;
|
|
padding: 20px;
|
|
background: rgba(12, 42, 73, 0.9);
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
box-shadow: -5px 0 15px rgba(0, 0, 0, 0.3);
|
|
z-index: 10;
|
|
border-radius: 8px;
|
|
position: absolute;
|
|
right: 15px;
|
|
top: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 卡片头部样式 */
|
|
/* .card-header {
|
|
height: 40px;
|
|
background: linear-gradient(to right, #1a3a5f, #2a5a8f);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 8px 8px 0 0 !important;
|
|
border-bottom: 1px solid #4fc3f7;
|
|
padding: 12px 20px;
|
|
position: relative;
|
|
margin: -20px -20px 20px -20px;
|
|
}
|
|
|
|
.card-header span {
|
|
font-size: 1.2rem;
|
|
letter-spacing: 1px;
|
|
font-family: 'Microsoft YaHei';
|
|
font-weight: 400;
|
|
color: #ffffff;
|
|
} */
|
|
|
|
.stats-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.stat-card {
|
|
background: rgba(25, 55, 95, 0.6);
|
|
/* background: url('/assets/img/common/kva2.png') no-repeat; */
|
|
/* background-size: 100% 100%; */
|
|
border-radius: 10px;
|
|
padding: 15px;
|
|
border-left: 4px solid #4fc3f7;
|
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 0.9rem;
|
|
color: #a0d2ff;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 1.8rem;
|
|
font-weight: bold;
|
|
color: #4fc3f7;
|
|
}
|
|
|
|
.data-list {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
margin-top: 10px;
|
|
padding-right: 5px;
|
|
}
|
|
|
|
.data-item {
|
|
min-width: 200px;
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border-radius: 8px;
|
|
padding: 10px;
|
|
border-left: 3px solid #4fc3f7;
|
|
transition: all 0.3s ease;
|
|
margin-bottom: 10px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.data-item:hover {
|
|
transform: translateX(5px);
|
|
background: rgba(40, 80, 130, 0.7);
|
|
}
|
|
|
|
.stream-device-info {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.stream-device-icon {
|
|
font-size: 1.5rem;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.stream-device-details {
|
|
flex: 1;
|
|
}
|
|
|
|
.stream-device-name {
|
|
font-weight: bold;
|
|
color: #4fc3f7;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.stream-parameter {
|
|
font-size: 0.8rem;
|
|
color: #a0d2ff;
|
|
}
|
|
|
|
.stream-value-section {
|
|
text-align: right;
|
|
}
|
|
|
|
.stream-value {
|
|
font-weight: bold;
|
|
font-size: 1.1rem;
|
|
font-family: 'Courier New', monospace;
|
|
}
|
|
|
|
.stream-timestamp {
|
|
font-size: 0.7rem;
|
|
color: #81d4fa;
|
|
}
|
|
|
|
.control-group {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.control-title {
|
|
font-size: 1.2rem;
|
|
margin-bottom: 15px;
|
|
color: #4fc3f7;
|
|
}
|
|
|
|
.toggle-switch {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.switch-label {
|
|
margin-right: 10px;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 60px;
|
|
height: 30px;
|
|
}
|
|
|
|
.switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
|
|
.slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #2c3e50;
|
|
transition: .4s;
|
|
border-radius: 34px;
|
|
}
|
|
|
|
.slider:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 22px;
|
|
width: 22px;
|
|
left: 4px;
|
|
bottom: 4px;
|
|
background-color: white;
|
|
transition: .4s;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
input:checked+.slider {
|
|
background-color: #4fc3f7;
|
|
}
|
|
|
|
input:checked+.slider:before {
|
|
transform: translateX(30px);
|
|
}
|
|
|
|
.filter-options {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.filter-option {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.filter-option input {
|
|
margin-right: 10px;
|
|
}
|
|
|
|
/* 地球容器样式 */
|
|
.earth-container {
|
|
flex: 1;
|
|
height: 100%;
|
|
position: relative;
|
|
/* margin: 0 300px 0 320px; */
|
|
background: #0c1a2d;
|
|
}
|
|
|
|
#earthCanvas {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
|
|
/* 信息卡片样式 */
|
|
.info-card {
|
|
position: absolute;
|
|
background: rgba(16, 36, 62, 0.95);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 10px;
|
|
padding: 15px;
|
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.4);
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
z-index: 1000;
|
|
width: 250px;
|
|
transform: translate(-50%, -100%);
|
|
margin-top: -20px;
|
|
}
|
|
|
|
.info-card::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
border-width: 10px;
|
|
border-style: solid;
|
|
border-color: rgba(16, 36, 62, 0.95) transparent transparent transparent;
|
|
}
|
|
|
|
/* 卡片头部样式 */
|
|
.card-header {
|
|
height: 40px;
|
|
background: url('/assets/img/common/homeTitle2.png') no-repeat;
|
|
background-position: center;
|
|
background-size: 108% 120%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 8px 8px 0 0 !important;
|
|
border-bottom: 1px solid var(--light-blue);
|
|
padding: 32px 20px;
|
|
position: relative;
|
|
margin: -20px -20px 0px -20px;
|
|
}
|
|
|
|
.card-header span {
|
|
font-size: 1.2rem;
|
|
letter-spacing: 1px;
|
|
font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei';
|
|
font-weight: 400;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.info-card-title {
|
|
font-size: 1.1rem;
|
|
color: #4fc3f7;
|
|
margin: 0;
|
|
}
|
|
|
|
.info-card-close {
|
|
background: none;
|
|
border: none;
|
|
color: #a0d2ff;
|
|
font-size: 1.2rem;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
width: 24px;
|
|
height: 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.info-card-close:hover {
|
|
color: #ffffff;
|
|
}
|
|
|
|
.info-card-content {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.info-item {
|
|
margin: 8px 0;
|
|
display: flex;
|
|
}
|
|
|
|
.info-label {
|
|
width: 70px;
|
|
color: #a0d2ff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.info-value {
|
|
flex: 1;
|
|
color: #e0f0ff;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.status-online {
|
|
color: #4caf50;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.status-offline {
|
|
color: #f44336;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 响应式调整 */
|
|
@media (max-width: 1200px) {
|
|
|
|
.info-panel,
|
|
.control-panel {
|
|
width: 260px;
|
|
}
|
|
|
|
.earth-container {
|
|
margin: 0 275px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
|
|
.info-panel,
|
|
.control-panel {
|
|
width: 220px;
|
|
padding: 15px;
|
|
}
|
|
|
|
.earth-container {
|
|
margin: 0 235px;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 1.5rem;
|
|
}
|
|
}
|
|
|
|
/* 滚动条样式 */
|
|
::-webkit-scrollbar {
|
|
width: 4px;
|
|
height: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: rgba(12, 42, 73, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: rgba(106, 149, 201, 0.5);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(106, 149, 201, 0.7);
|
|
}
|
|
|
|
/* 警报列表样式 */
|
|
.alert-list {
|
|
/* height: 240px;
|
|
overflow-y: auto; */
|
|
height: calc(40vh - 8vh - 20px);
|
|
overflow: scroll;
|
|
}
|
|
|
|
.alert-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 12px 15px;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
transition: background 0.3s;
|
|
}
|
|
|
|
.alert-item:hover {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
}
|
|
|
|
.alert-level {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.level-high {
|
|
background: #ff4560;
|
|
box-shadow: 0 0 8px #ff4560;
|
|
}
|
|
|
|
.level-medium {
|
|
background: #ffa726;
|
|
box-shadow: 0 0 8px #ffa726;
|
|
}
|
|
|
|
.level-low {
|
|
background: #00e396;
|
|
box-shadow: 0 0 8px #00e396;
|
|
}
|
|
|
|
.alert-content {
|
|
flex: 1;
|
|
}
|
|
|
|
.alert-title {
|
|
font-weight: bold;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.alert-desc {
|
|
font-size: 13px;
|
|
color: #a0c8ff;
|
|
}
|
|
|
|
.alert-time {
|
|
font-size: 12px;
|
|
color: #7a9ccc;
|
|
}
|
|
|
|
/* 图表容器样式 */
|
|
.chart-container {
|
|
width: 100%;
|
|
/* height: 200px; */
|
|
margin-top: 10px;
|
|
height: calc(40vh - 8vh - 20px);
|
|
}
|
|
|
|
/* 新增样式:实时数据监控网格布局 */
|
|
.stats-grid {
|
|
height: calc(40vh - 8vh - 20px);
|
|
overflow: scroll;
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 10px;
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.stat-grid-item {
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
/* border-left: 3px solid #4fc3f7; */
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
}
|
|
|
|
.stat-grid-value {
|
|
font-size: 1rem;
|
|
font-weight: bold;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.stat-grid-label {
|
|
font-size: 0.8rem;
|
|
color: #a0d2ff;
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.stat-grid-status {
|
|
font-size: 0.7rem;
|
|
color: #81d4fa;
|
|
}
|
|
|
|
/* 视频会议系统样式 */
|
|
.video-conference {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 10px;
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.video-item {
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.video-item:hover {
|
|
transform: translateY(-3px);
|
|
background: rgba(40, 80, 130, 0.7);
|
|
}
|
|
|
|
.video-icon {
|
|
font-size: 2rem;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.video-name {
|
|
font-size: 0.9rem;
|
|
color: #e0f0ff;
|
|
}
|
|
|
|
/* 网络系统状态样式 */
|
|
.network-status {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.network-item {
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.network-label {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 5px;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.network-name {
|
|
color: #a0d2ff;
|
|
}
|
|
|
|
.network-value {
|
|
color: #4fc3f7;
|
|
}
|
|
|
|
.network-progress {
|
|
height: 8px;
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.network-progress-bar {
|
|
height: 100%;
|
|
border-radius: 4px;
|
|
transition: width 0.5s ease;
|
|
}
|
|
|
|
/* 项目监控样式 */
|
|
.project-monitor {
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.project-item {
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.project-label {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 5px;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.project-name {
|
|
color: #a0d2ff;
|
|
}
|
|
|
|
.project-value {
|
|
color: #4fc3f7;
|
|
}
|
|
|
|
.project-progress {
|
|
height: 8px;
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.project-progress-bar {
|
|
height: 100%;
|
|
border-radius: 4px;
|
|
transition: width 0.5s ease;
|
|
}
|
|
|
|
.mars3d-popup-background {
|
|
background: var(--mars-base-bg, rgba(16, 36, 62, 0.85)) !important;
|
|
}
|
|
|
|
/* 区域选择器样式 */
|
|
.region-selector {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.region-selector select {
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
background: rgba(25, 55, 95, 0.6);
|
|
border: 1px solid rgba(79, 195, 247, 0.5);
|
|
border-radius: 4px;
|
|
color: #e0f0ff;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.region-selector select:focus {
|
|
outline: none;
|
|
border-color: #4fc3f7;
|
|
}
|
|
|
|
.region-selector label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
font-size: 0.9rem;
|
|
color: #a0d2ff;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- 顶部标题栏 -->
|
|
<div class="topDiv">
|
|
<div class="left">
|
|
<span id="current-date">2025年9月17日</span>
|
|
<span id="current-time">15:18:00</span>
|
|
</div>
|
|
<div class="center">中国敏感海域问题事件热点图</div>
|
|
<div class="right">
|
|
<img src="/common/images/logo_gt.png" alt="" />
|
|
</div>
|
|
</div>
|
|
<div class="container">
|
|
<!-- 地球容器 -->
|
|
<div class="earth-container">
|
|
<div id="mars3dMap" style="width:100%; height:100%;"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
// 全局变量
|
|
let map;
|
|
let isSimulationRunning = true;
|
|
let waterQualityChart;
|
|
let oxygenChart;
|
|
let chlorophyllChart;
|
|
let heatLayer = null
|
|
let heatLayer_clustering = null; // 添加这一行
|
|
|
|
// 替换原有的 lianyungangEcoRegions 数据为以下代码:
|
|
|
|
// 连云港生态区域数据 - 修正为正确的连云港地理坐标范围
|
|
const lianyungangEcoRegions = [
|
|
{
|
|
name: "非湿地",
|
|
type: "non-wetland",
|
|
color: "#cccccc",
|
|
coordinates: [
|
|
[[119.2, 34.8], [119.4, 34.8], [119.4, 35.0], [119.2, 35.0], [119.2, 34.8]]
|
|
]
|
|
},
|
|
{
|
|
name: "永久水域",
|
|
type: "permanent-water",
|
|
color: "#2ca25f",
|
|
coordinates: [
|
|
[[119.3, 34.6], [119.5, 34.6], [119.5, 34.8], [119.3, 34.8], [119.3, 34.6]]
|
|
]
|
|
},
|
|
{
|
|
name: "沼泽(乔木/灌木)",
|
|
type: "swamp-woody",
|
|
color: "#756bb1",
|
|
coordinates: [
|
|
[[119.1, 34.7], [119.3, 34.7], [119.3, 34.9], [119.1, 34.9], [119.1, 34.7]]
|
|
]
|
|
},
|
|
{
|
|
name: "沼泽(草本植被)",
|
|
type: "swamp-herbaceous",
|
|
color: "#dd3497",
|
|
coordinates: [
|
|
[[119.0, 34.6], [119.2, 34.6], [119.2, 34.8], [119.0, 34.8], [119.0, 34.6]]
|
|
]
|
|
},
|
|
{
|
|
name: "淹滩",
|
|
type: "flooded-beach",
|
|
color: "#fdbb84",
|
|
coordinates: [
|
|
[[119.4, 34.5], [119.6, 34.5], [119.6, 34.7], [119.4, 34.7], [119.4, 34.5]]
|
|
]
|
|
},
|
|
{
|
|
name: "盐碱地",
|
|
type: "saline-land",
|
|
color: "#b30000",
|
|
coordinates: [
|
|
[[119.5, 34.7], [119.7, 34.7], [119.7, 34.9], [119.5, 34.9], [119.5, 34.7]]
|
|
]
|
|
},
|
|
{
|
|
name: "红树林",
|
|
type: "mangrove",
|
|
color: "#41b6c4",
|
|
coordinates: [
|
|
[[119.6, 34.6], [119.8, 34.6], [119.8, 34.8], [119.6, 34.8], [119.6, 34.6]]
|
|
]
|
|
},
|
|
{
|
|
name: "盐沼",
|
|
type: "salt-marsh",
|
|
color: "#1d91c0",
|
|
coordinates: [
|
|
[[119.7, 34.5], [119.9, 34.5], [119.9, 34.7], [119.7, 34.7], [119.7, 34.5]]
|
|
]
|
|
},
|
|
{
|
|
name: "潮滩",
|
|
type: "tidal-flat",
|
|
color: "#ffff00",
|
|
coordinates: [
|
|
[[119.8, 34.4], [120.0, 34.4], [120.0, 34.6], [119.8, 34.6], [119.8, 34.4]]
|
|
]
|
|
},
|
|
{
|
|
name: "海洋",
|
|
type: "ocean",
|
|
color: "#081d58",
|
|
coordinates: [
|
|
[[119.9, 34.3], [120.1, 34.3], [120.1, 34.5], [119.9, 34.5], [119.9, 34.3]]
|
|
]
|
|
}
|
|
];
|
|
// 初始化页面
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
initDateTime();
|
|
// initWaterQualityChart();
|
|
// initOxygenChart();
|
|
// initChlorophyllChart();
|
|
initMap();
|
|
//initEventListeners();
|
|
});
|
|
|
|
// 初始化日期时间
|
|
function initDateTime() {
|
|
function updateDateTime() {
|
|
const now = new Date();
|
|
const dateStr = now.getFullYear() + '年' +
|
|
(now.getMonth() + 1) + '月' +
|
|
now.getDate() + '日';
|
|
const timeStr = now.toTimeString().substr(0, 8);
|
|
|
|
document.getElementById('current-date').textContent = dateStr;
|
|
document.getElementById('current-time').textContent = timeStr;
|
|
}
|
|
|
|
updateDateTime();
|
|
setInterval(updateDateTime, 1000);
|
|
}
|
|
|
|
// 初始化生态水质分析图表
|
|
function initWaterQualityChart() {
|
|
waterQualityChart = echarts.init(document.getElementById('waterQualityChart'));
|
|
|
|
const option = {
|
|
backgroundColor: 'transparent',
|
|
tooltip: {
|
|
trigger: 'axis'
|
|
},
|
|
legend: {
|
|
data: ['PH值', '浊度', '盐度'],
|
|
textStyle: {
|
|
color: '#e0f0ff'
|
|
},
|
|
top: '0%'
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '4%',
|
|
bottom: '3%',
|
|
top: '15%',
|
|
containLabel: true
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
boundaryGap: false,
|
|
data: ['2019', '2020', '2021', '2022', '2023'],
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
}
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
color: 'rgba(79, 195, 247, 0.2)'
|
|
}
|
|
}
|
|
},
|
|
series: [
|
|
{
|
|
name: 'PH值',
|
|
type: 'line',
|
|
smooth: true,
|
|
data: [7.9, 8.0, 8.1, 8.2, 8.1],
|
|
lineStyle: {
|
|
color: '#00e396'
|
|
},
|
|
itemStyle: {
|
|
color: '#00e396'
|
|
}
|
|
},
|
|
{
|
|
name: '浊度',
|
|
type: 'line',
|
|
smooth: true,
|
|
data: [12.5, 11.8, 10.2, 9.5, 8.3],
|
|
lineStyle: {
|
|
color: '#00c6ff'
|
|
},
|
|
itemStyle: {
|
|
color: '#00c6ff'
|
|
}
|
|
},
|
|
{
|
|
name: '盐度',
|
|
type: 'line',
|
|
smooth: true,
|
|
data: [30.5, 30.8, 31.2, 31.5, 31.3],
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
},
|
|
itemStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
waterQualityChart.setOption(option);
|
|
}
|
|
|
|
// 初始化含氧量趋势分析图表
|
|
function initOxygenChart() {
|
|
oxygenChart = echarts.init(document.getElementById('oxygenChart'));
|
|
|
|
const option = {
|
|
backgroundColor: 'transparent',
|
|
tooltip: {
|
|
trigger: 'axis'
|
|
},
|
|
legend: {
|
|
data: ['溶解氧'],
|
|
textStyle: {
|
|
color: '#e0f0ff'
|
|
},
|
|
top: '0%'
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '4%',
|
|
bottom: '3%',
|
|
top: '15%',
|
|
containLabel: true
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
boundaryGap: false,
|
|
data: ['2019', '2020', '2021', '2022', '2023'],
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
}
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
name: 'mg/L',
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
color: 'rgba(79, 195, 247, 0.2)'
|
|
}
|
|
}
|
|
},
|
|
series: [
|
|
{
|
|
name: '溶解氧',
|
|
type: 'line',
|
|
smooth: true,
|
|
data: [6.8, 6.9, 7.1, 7.2, 7.0],
|
|
lineStyle: {
|
|
color: '#ff6b6b'
|
|
},
|
|
itemStyle: {
|
|
color: '#ff6b6b'
|
|
},
|
|
areaStyle: {
|
|
color: {
|
|
type: 'linear',
|
|
x: 0,
|
|
y: 0,
|
|
x2: 0,
|
|
y2: 1,
|
|
colorStops: [{
|
|
offset: 0,
|
|
color: 'rgba(255, 107, 107, 0.5)'
|
|
}, {
|
|
offset: 1,
|
|
color: 'rgba(255, 107, 107, 0.1)'
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
oxygenChart.setOption(option);
|
|
}
|
|
|
|
// 初始化叶绿素趋势分析图表
|
|
function initChlorophyllChart() {
|
|
chlorophyllChart = echarts.init(document.getElementById('chlorophyllChart'));
|
|
|
|
const option = {
|
|
backgroundColor: 'transparent',
|
|
tooltip: {
|
|
trigger: 'axis'
|
|
},
|
|
legend: {
|
|
data: ['叶绿素a'],
|
|
textStyle: {
|
|
color: '#e0f0ff'
|
|
},
|
|
top: '0%'
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '4%',
|
|
bottom: '3%',
|
|
top: '15%',
|
|
containLabel: true
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
boundaryGap: false,
|
|
data: ['2019', '2020', '2021', '2022', '2023'],
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
}
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
name: 'μg/L',
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: '#4fc3f7'
|
|
}
|
|
},
|
|
axisLabel: {
|
|
color: '#a0d2ff'
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
color: 'rgba(79, 195, 247, 0.2)'
|
|
}
|
|
}
|
|
},
|
|
series: [
|
|
{
|
|
name: '叶绿素a',
|
|
type: 'line',
|
|
smooth: true,
|
|
data: [3.2, 3.5, 4.1, 4.3, 4.0],
|
|
lineStyle: {
|
|
color: '#a8e6cf'
|
|
},
|
|
itemStyle: {
|
|
color: '#a8e6cf'
|
|
},
|
|
areaStyle: {
|
|
color: {
|
|
type: 'linear',
|
|
x: 0,
|
|
y: 0,
|
|
x2: 0,
|
|
y2: 1,
|
|
colorStops: [{
|
|
offset: 0,
|
|
color: 'rgba(168, 230, 207, 0.5)'
|
|
}, {
|
|
offset: 1,
|
|
color: 'rgba(168, 230, 207, 0.1)'
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
chlorophyllChart.setOption(option);
|
|
}
|
|
|
|
// 初始化地图
|
|
async function initMap() {
|
|
try {
|
|
// 通过 AJAX 加载 config.json 配置文件
|
|
fetch('./config/config.json')
|
|
.then(response => response.json())
|
|
.then(config => {
|
|
// 使用配置文件初始化地图
|
|
map = new mars3d.Map("mars3dMap", config.map3d);
|
|
|
|
// 等待地图完全加载后再添加图层
|
|
map.on(mars3d.EventType.load, function () {
|
|
console.log('地图加载完成');
|
|
setTimeout(() => {
|
|
|
|
// 加载热力图
|
|
loadHeatLayer();
|
|
// 添加图例
|
|
addLegend();
|
|
}, 1000);
|
|
|
|
});
|
|
|
|
})
|
|
.catch(error => {
|
|
console.error('加载配置文件失败:', error);
|
|
// 使用默认配置
|
|
initDefaultMap();
|
|
});
|
|
} catch (error) {
|
|
console.error('初始化 Mars3D 地图时出错:', error);
|
|
initDefaultMap();
|
|
}
|
|
}
|
|
// 默认地图配置
|
|
function initDefaultMap() {
|
|
map = new mars3d.Map("mars3dMap", {
|
|
scene: {
|
|
sceneMode: Cesium.SceneMode.SCENE2D, // 设置默认为二维模式
|
|
center: { lat: 15.0, lng: 110.0, alt: 3000000, heading: 0, pitch: -45 }, // 调整为中心显示南海区域
|
|
showSun: true,
|
|
showMoon: true,
|
|
showSkyBox: true,
|
|
showSkyAtmosphere: true,
|
|
fog: true,
|
|
fxaa: true,
|
|
cameraController: {
|
|
zoomFactor: 2.0,
|
|
minimumZoomDistance: 1,
|
|
maximumZoomDistance: 50000000,
|
|
}
|
|
},
|
|
control: {
|
|
homeButton: true,
|
|
sceneModePicker: true,
|
|
baseLayerPicker: true,
|
|
navigationHelpButton: true,
|
|
animation: true,
|
|
timeline: true,
|
|
fullscreenButton: true,
|
|
vrButton: true,
|
|
},
|
|
basemaps: [
|
|
{
|
|
id: 10,
|
|
name: "天地图影像",
|
|
icon: "img/basemaps/tdt_img.png",
|
|
type: "group",
|
|
layers: [
|
|
{
|
|
name: "底图",
|
|
type: "tdt",
|
|
layer: "img_d",
|
|
},
|
|
{
|
|
name: "注记",
|
|
type: "tdt",
|
|
layer: "cia_w",
|
|
}
|
|
]
|
|
}
|
|
]
|
|
});
|
|
|
|
// 地图加载完成后添加图层
|
|
map.on(mars3d.EventType.load, function () {
|
|
console.log('默认地图加载完成');
|
|
|
|
setTimeout(() => {
|
|
|
|
// 加载热力图
|
|
loadHeatLayer();
|
|
// 添加图例
|
|
addLegend();
|
|
}, 1000);
|
|
});
|
|
}
|
|
|
|
// // 添加区域选择事件监听
|
|
// document.getElementById('region-select').addEventListener('change', function () {
|
|
// updateCharts(this.value);
|
|
// });
|
|
// 生成模拟数据
|
|
function getPointData() {
|
|
const points = [];
|
|
|
|
// 连云港区域坐标范围
|
|
const minLng = 118.5, maxLng = 120.0;
|
|
const minLat = 34.0, maxLat = 35.2;
|
|
|
|
// 生成1500个随机点位
|
|
for (let i = 0; i < 50; i++) {
|
|
const lng = minLng + Math.random() * (maxLng - minLng);
|
|
const lat = minLat + Math.random() * (maxLat - minLat);
|
|
|
|
points.push({
|
|
grid: `{"type":"Point","coordinates":[${lng.toFixed(6)},${lat.toFixed(6)}]}`,
|
|
name: `监测点${i + 1}`,
|
|
remark: '连云港海域监测点',
|
|
});
|
|
}
|
|
|
|
return points;
|
|
}
|
|
// // 正常应该为接口获取数据,我这里是自己随机生成的点位
|
|
// function getPointData() {
|
|
// return [
|
|
// {
|
|
// grid: '{"type":"Point","coordinates":[117.111,36.652]}',
|
|
// name: '济南点位',
|
|
// remark: '济南市',
|
|
// },
|
|
// {
|
|
// grid: '{"type":"Point","coordinates":[118.127,36.183]}',
|
|
// name: '枣庄点位',
|
|
// remark: '枣庄市',
|
|
// },
|
|
// // 新增28个随机点位
|
|
// ...Array.from({ length: 30 }, (_, i) => {
|
|
// // 生成山东省范围内的随机坐标
|
|
// const lng = 115 + Math.random() * 2
|
|
// const lat = 34 + Math.random() * 2
|
|
|
|
// return {
|
|
// grid: `{"type":"Point","coordinates":[${lng.toFixed(
|
|
// 6
|
|
// )},${lat.toFixed(6)}]}`,
|
|
// name: `测试点位${i + 1}`,
|
|
// remark: '随机位置',
|
|
// }
|
|
// }),
|
|
// ...Array.from({ length: 10 }, (_, i) => {
|
|
// // 生成山东省范围内的随机坐标
|
|
// const lng = 105 + Math.random() * 2
|
|
// const lat = 32 + Math.random() * 2
|
|
|
|
// return {
|
|
// grid: `{"type":"Point","coordinates":[${lng.toFixed(
|
|
// 6
|
|
// )},${lat.toFixed(6)}]}`,
|
|
// name: `测试点位${i + 1}`,
|
|
// remark: '随机位置',
|
|
// }
|
|
// }),
|
|
// ]
|
|
// }
|
|
|
|
// // 加载热力图,将数据放到图层上
|
|
// async function loadHeatLayer() {
|
|
// let arrPoints = []
|
|
// let arr = await getPointData() //这里为获取的数据
|
|
// arr.forEach((item) => {
|
|
// if (item.grid) {
|
|
// let pointData = JSON.parse(item.grid).coordinates
|
|
// arrPoints.push({ lng: pointData[0], lat: pointData[1], value: 1 })
|
|
// }
|
|
// })
|
|
// if (heatLayer) {
|
|
// map.removeLayer(heatLayer)
|
|
// heatLayer = null
|
|
// }
|
|
|
|
// // 热力图 图层
|
|
// heatLayer = new mars3d.layer.graphicLayer({
|
|
// name: 'Point',
|
|
// positions: arrPoints,
|
|
// heatStyle: {
|
|
// radius: 40,
|
|
// blur: 0.85,
|
|
// gradient: { 0.4: 'blue', 0.6: 'green', 0.9: 'yellow', 1: 'red' },
|
|
// },
|
|
// // 以下为矩形矢量对象的样式参数
|
|
// style: {
|
|
// arc: false, // 是否为曲面
|
|
// height: 10,
|
|
// },
|
|
// // flyTo: true,
|
|
// })
|
|
// map.value.addLayer(heatLayer)
|
|
// }
|
|
|
|
// 替换原有的 loadHeatLayer 函数,增加聚合功能
|
|
async function loadHeatLayer() {
|
|
try {
|
|
console.log('开始加载南海事件数据...');
|
|
|
|
// 定义文件和对应的颜色
|
|
const fileColors = {
|
|
'./data/jiison/1_lan.json': '#0000FF', // 蓝色
|
|
'./data/jiison/2_hong.json': '#FF0000', // 红色
|
|
'./data/jiison/3_cheng.json': '#FFA500', // 橙色
|
|
'./data/jiison/4_lv.json': '#008000', // 绿色
|
|
'./data/jiison/5_huang.json': '#FFFF00', // 黄色
|
|
'./data/jiison/6_zi.json': '#800080', // 紫色
|
|
'./data/jiison/7_zong.json': '#00FFFF' // 青色
|
|
};
|
|
|
|
let allPoints = [];
|
|
|
|
// 加载所有JSON文件
|
|
for (const [file, color] of Object.entries(fileColors)) {
|
|
try {
|
|
const response = await fetch(file);
|
|
const eventData = await response.json();
|
|
|
|
eventData.forEach(item => {
|
|
allPoints.push({
|
|
lng: item.经度,
|
|
lat: item.纬度,
|
|
value: 1.0,
|
|
color: color,
|
|
attr: {
|
|
事件: item.事件,
|
|
时间: item.时间,
|
|
经度: item.经度,
|
|
纬度: item.纬度
|
|
}
|
|
});
|
|
});
|
|
|
|
console.log(`加载 ${file} 完成,数据点数量:`, eventData.length);
|
|
} catch (fileError) {
|
|
console.error(`加载文件 ${file} 时出错:`, fileError);
|
|
}
|
|
}
|
|
|
|
console.log('总生成的事件数据点:', allPoints.length);
|
|
|
|
// 移除旧图层
|
|
if (heatLayer) {
|
|
map.removeLayer(heatLayer);
|
|
heatLayer = null;
|
|
}
|
|
|
|
// 创建带聚合功能的图形图层
|
|
heatLayer = new mars3d.layer.GraphicLayer({
|
|
name: '南海事件点图层',
|
|
// 启用图层级别的聚合功能
|
|
clustering: {
|
|
enabled: true,
|
|
pixelRange: 50,
|
|
minimumClusterSize: 3,
|
|
billboard: true,
|
|
showCoverageOnHover: true,
|
|
zoomOnClick: true,
|
|
style: {
|
|
// 聚合点样式
|
|
circle: {
|
|
color: "#4fc3f7",
|
|
radius: 20,
|
|
outline: true,
|
|
outlineColor: "#ffffff",
|
|
outlineWidth: 2
|
|
},
|
|
// 聚合点文字样式
|
|
label: {
|
|
font_size: 16,
|
|
color: "#ffffff",
|
|
offset_y: -20,
|
|
font_family: "Arial",
|
|
font_weight: "bold"
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
map.addLayer(heatLayer);
|
|
|
|
// 为每个点创建图形元素
|
|
allPoints.forEach(point => {
|
|
const graphic = new mars3d.graphic.BillboardEntity({
|
|
position: [point.lng, point.lat],
|
|
style: {
|
|
pixelSize: 10,
|
|
color: point.color,
|
|
outlineColor: '#FFFFFF',
|
|
outlineWidth: 1,
|
|
opacity: 0.8,
|
|
scaleByDistance: true,
|
|
scaleByDistance_far: 2000000,
|
|
scaleByDistance_farValue: 0.8,
|
|
scaleByDistance_near: 100000,
|
|
scaleByDistance_nearValue: 1.2
|
|
},
|
|
attr: point.attr,
|
|
popup: `
|
|
<div style="padding: 10px">
|
|
<h3 style="margin:0 0 10px 0;color:#4fc3f7">${point.attr.事件}</h3>
|
|
<p style="margin:5px 0"><strong>时间:</strong> ${point.attr.时间}</p>
|
|
<p style="margin:5px 0"><strong>纬度:</strong> ${point.attr.纬度}</p>
|
|
<p style="margin:5px 0"><strong>经度:</strong> ${point.attr.经度}</p>
|
|
</div>
|
|
`
|
|
});
|
|
|
|
heatLayer.addGraphic(graphic);
|
|
});
|
|
|
|
console.log('事件点图层创建完成,聚合功能已启用');
|
|
|
|
} catch (error) {
|
|
console.error('加载南海事件数据时出错:', error);
|
|
}
|
|
}
|
|
|
|
// 创建事件点图层(当热力图插件不可用时的备选方案)
|
|
function createEventPointLayer(points) {
|
|
if (heatLayer) {
|
|
map.removeLayer(heatLayer);
|
|
heatLayer = null;
|
|
}
|
|
|
|
// 创建图形图层来显示事件点
|
|
heatLayer = new mars3d.layer.GraphicLayer({
|
|
name: '南海事件点图层'
|
|
});
|
|
|
|
map.addLayer(heatLayer);
|
|
|
|
points.forEach(point => {
|
|
const graphic = new mars3d.graphic.PointEntity({
|
|
position: [point.lng, point.lat],
|
|
style: {
|
|
pixelSize: 10,
|
|
color: '#FF0000',
|
|
outlineColor: '#FFFFFF',
|
|
outlineWidth: 1,
|
|
opacity: 0.8
|
|
},
|
|
attr: point.attr,
|
|
popup: `
|
|
<div style="padding: 10px">
|
|
<h3 style="margin:0 0 10px 0;color:#4fc3f7">${point.attr.事件}</h3>
|
|
<p style="margin:5px 0"><strong>时间:</strong> ${point.attr.时间}</p>
|
|
<p style="margin:5px 0"><strong>纬度:</strong> ${point.attr.纬度}</p>
|
|
<p style="margin:5px 0"><strong>经度:</strong> ${point.attr.经度}</p>
|
|
</div>
|
|
`
|
|
});
|
|
|
|
heatLayer.addGraphic(graphic);
|
|
});
|
|
|
|
console.log('事件点图层创建完成');
|
|
}
|
|
|
|
|
|
// 添加生态区域图层 - 修复版本
|
|
function addEcoRegionsLayer() {
|
|
if (!map) {
|
|
console.warn('地图未初始化完成,延迟添加生态区域图层');
|
|
setTimeout(addEcoRegionsLayer, 1000);
|
|
return;
|
|
}
|
|
|
|
const colorMap = {
|
|
'non-wetland': '#808080',
|
|
'permanent-water': '#1E90FF',
|
|
'swamp-woody': '#6B8E23',
|
|
'swamp-herbaceous': '#8FBC8F',
|
|
'flooded-beach': '#D2B48C',
|
|
'saline-land': '#A0522D',
|
|
'mangrove': '#006400',
|
|
'salt-marsh': '#2E8B57',
|
|
'tidal-flat': '#BC8F8F',
|
|
'ocean': '#00008B'
|
|
};
|
|
|
|
const graphicLayer = new mars3d.layer.GraphicLayer({
|
|
name: "连云港生态区域"
|
|
});
|
|
|
|
// 先将图层添加到地图
|
|
map.addLayer(graphicLayer);
|
|
|
|
lianyungangEcoRegions.forEach((region, index) => {
|
|
region.coordinates.forEach((ring, ringIndex) => {
|
|
// 修复坐标格式,确保使用正确的经纬度顺序
|
|
const positions = ring.map(coord => [coord[0], coord[1], 0]); // 添加高度值
|
|
|
|
const polygon = new mars3d.graphic.PolygonEntity({
|
|
positions: positions,
|
|
style: {
|
|
fill: true,
|
|
color: colorMap[region.type] || '#808080',
|
|
opacity: 0.6,
|
|
outline: true,
|
|
outlineColor: "#ffffff",
|
|
outlineWidth: 1,
|
|
clampToGround: true
|
|
},
|
|
attr: {
|
|
name: region.name,
|
|
type: region.type
|
|
},
|
|
popup: "类型: " + region.name + "<br/>生态类型: " + region.type
|
|
});
|
|
|
|
// 添加到已存在的图层
|
|
graphicLayer.addGraphic(polygon);
|
|
});
|
|
});
|
|
|
|
console.log('生态区域图形图层已添加,共添加 ' + lianyungangEcoRegions.length + ' 个区域');
|
|
}
|
|
// 修改 addLegend 函数,添加按颜色分类的图例说明
|
|
function addLegend() {
|
|
const legend = document.createElement('div');
|
|
legend.style.cssText = `
|
|
position: absolute;
|
|
bottom: 20px;
|
|
left: 20px;
|
|
background: rgba(16, 36, 62, 0.85);
|
|
border: 1px solid rgba(64, 156, 255, 0.3);
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
color: #e0f0ff;
|
|
z-index: 1000;
|
|
max-width: 250px;
|
|
backdrop-filter: blur(5px);
|
|
`;
|
|
|
|
legend.innerHTML = `
|
|
<h3 style="margin: 0 0 10px 0; color: #4fc3f7; font-size: 14px;">事件类型图例</h3>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #0000FF; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">领海争议</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #FF0000; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">边境冲突</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #FFA500; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">低空与敌对冲突</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #008000; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">两岸海域纠纷</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #FFFF00; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">内部渔船管理与执法</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
<div style="width: 12px; height: 12px; background-color: #800080; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">渔民打捞境外设备</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center; margin-bottom: 5px;">
|
|
<div style="width: 12px; height: 12px; background-color: #00FFFF; border-radius: 50%; margin-right: 8px;"></div>
|
|
<span style="font-size: 12px;">生态安全环境</span>
|
|
</div>
|
|
`;
|
|
|
|
document.querySelector('.earth-container').appendChild(legend);
|
|
}
|
|
|
|
// 初始化事件监听器
|
|
function initEventListeners() {
|
|
// // 窗口大小变化时重新调整图表大小
|
|
// window.addEventListener('resize', function () {
|
|
// waterQualityChart.resize();
|
|
// oxygenChart.resize();
|
|
// chlorophyllChart.resize();
|
|
// });
|
|
}
|
|
|
|
// 更新图表数据
|
|
function updateCharts(region) {
|
|
// 根据区域更新图表数据
|
|
const regionData = {
|
|
'all': {
|
|
ph: [7.9, 8.0, 8.1, 8.2, 8.1],
|
|
turbidity: [12.5, 11.8, 10.2, 9.5, 8.3],
|
|
salinity: [30.5, 30.8, 31.2, 31.5, 31.3],
|
|
oxygen: [6.8, 6.9, 7.1, 7.2, 7.0],
|
|
chlorophyll: [3.2, 3.5, 4.1, 4.3, 4.0]
|
|
},
|
|
'lianyungang': {
|
|
ph: [7.8, 7.9, 8.0, 8.1, 8.0],
|
|
turbidity: [11.5, 10.8, 9.2, 8.5, 7.3],
|
|
salinity: [29.5, 29.8, 30.2, 30.5, 30.3],
|
|
oxygen: [6.7, 6.8, 7.0, 7.1, 6.9],
|
|
chlorophyll: [3.0, 3.3, 3.9, 4.1, 3.8]
|
|
},
|
|
'lanshan': {
|
|
ph: [8.0, 8.1, 8.2, 8.3, 8.2],
|
|
turbidity: [13.5, 12.8, 11.2, 10.5, 9.3],
|
|
salinity: [31.5, 31.8, 32.2, 32.5, 32.3],
|
|
oxygen: [6.9, 7.0, 7.2, 7.3, 7.1],
|
|
chlorophyll: [3.4, 3.7, 4.3, 4.5, 4.2]
|
|
},
|
|
'ganyu': {
|
|
ph: [7.7, 7.8, 7.9, 8.0, 7.9],
|
|
turbidity: [10.5, 9.8, 8.2, 7.5, 6.3],
|
|
salinity: [28.5, 28.8, 29.2, 29.5, 29.3],
|
|
oxygen: [6.6, 6.7, 6.9, 7.0, 6.8],
|
|
chlorophyll: [2.8, 3.1, 3.7, 3.9, 3.6]
|
|
},
|
|
'guannan': {
|
|
ph: [7.9, 8.0, 8.1, 8.2, 8.1],
|
|
turbidity: [12.0, 11.3, 9.7, 9.0, 7.8],
|
|
salinity: [30.0, 30.3, 30.7, 31.0, 30.8],
|
|
oxygen: [6.8, 6.9, 7.1, 7.2, 7.0],
|
|
chlorophyll: [3.1, 3.4, 4.0, 4.2, 3.9]
|
|
},
|
|
'guanyun': {
|
|
ph: [8.0, 8.1, 8.2, 8.3, 8.2],
|
|
turbidity: [13.0, 12.3, 10.7, 10.0, 8.8],
|
|
salinity: [31.0, 31.3, 31.7, 32.0, 31.8],
|
|
oxygen: [6.9, 7.0, 7.2, 7.3, 7.1],
|
|
chlorophyll: [3.3, 3.6, 4.2, 4.4, 4.1]
|
|
}
|
|
};
|
|
|
|
const data = regionData[region] || regionData['all'];
|
|
|
|
// 更新水质分析图表
|
|
waterQualityChart.setOption({
|
|
series: [
|
|
{ data: data.ph },
|
|
{ data: data.turbidity },
|
|
{ data: data.salinity }
|
|
]
|
|
});
|
|
|
|
// 更新含氧量趋势图表
|
|
oxygenChart.setOption({
|
|
series: [
|
|
{ data: data.oxygen }
|
|
]
|
|
});
|
|
|
|
// 更新叶绿素趋势图表
|
|
chlorophyllChart.setOption({
|
|
series: [
|
|
{ data: data.chlorophyll }
|
|
]
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html> |