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.

2262 lines
75 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!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="/models/chart.umd.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background: #000;
font-family: Arial, sans-serif;
}
#container {
width: 100vw;
height: 100vh;
position: relative;
background: #000;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
font-size: 14px;
z-index: 100;
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 18px;
z-index: 200;
}
.hidden {
display: none;
}
</style>
<style>
/* 面板基础样式修改 */
.panel {
position: absolute;
top: 20px;
width: 320px;
color: #e0f0ff;
z-index: 10;
height: calc(100vh - 40px);
display: flex;
flex-direction: column;
}
.left-panel {
left: 20px;
}
.right-panel {
right: 20px;
}
.panel-header {
border-bottom: 1px solid rgba(64, 156, 255, 0.4);
padding-bottom: 15px;
margin-bottom: 10px;
text-align: center;
}
.panel-header h3 {
margin: 0;
font-size: 22px;
font-weight: 600;
background: linear-gradient(90deg, #4fc3f7, #4abdf3);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(79, 195, 247, 0.3);
}
.panel-content {
height: 100%;
overflow-y: auto;
padding-right: 5px;
display: flex;
flex-direction: column;
}
.panel-content::-webkit-scrollbar {
width: 2px;
}
.panel-content::-webkit-scrollbar-thumb {
background: rgba(64, 156, 255, 0.5);
border-radius: 2px;
}
.panel-content::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
}
.info-section,
.realtime-indicators,
.unit-status,
.environment-stats,
.power-generation,
.alert-stats {
margin-bottom: 25px;
background: rgba(25, 55, 95, 0.3);
border-radius: 10px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.2);
}
.info-section h4,
.realtime-indicators h4,
.unit-status h4,
.environment-stats h4,
.power-generation h4,
.alert-stats h4 {
margin: 0 0 15px 0;
font-size: 18px;
font-weight: 600;
color: #4fc3f7;
text-align: center;
position: relative;
padding-bottom: 8px;
}
.info-section h4::after,
.realtime-indicators h4::after,
.unit-status h4::after,
.environment-stats h4::after,
.power-generation h4::after,
.alert-stats h4::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 2px;
background: linear-gradient(90deg, transparent, #4fc3f7, transparent);
}
.info-item,
.indicator-item,
.status-item,
.env-item,
.gen-item,
.alert-item {
display: flex;
flex-wrap: wrap;
margin-bottom: 15px;
padding-bottom: 15px;
border-bottom: 1px solid rgba(64, 156, 255, 0.2);
}
.info-item:last-child,
.indicator-item:last-child,
.status-item:last-child,
.env-item:last-child,
.gen-item:last-child,
.alert-item:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.info-item label,
.indicator-item label,
.status-item label,
.env-item label,
.gen-item label,
.alert-item label {
flex: 1;
font-size: 15px;
color: #cce0ff;
font-weight: 400;
}
.info-item .value,
.indicator-item .value,
.status-item .value,
.env-item .value,
.gen-item .value,
.alert-item .value {
font-weight: 700;
font-size: 16px;
text-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
}
.value.warning {
color: #ff9800;
text-shadow: 0 0 8px rgba(255, 152, 0, 0.7);
}
.value.critical {
color: #f44336;
text-shadow: 0 0 8px rgba(244, 67, 54, 0.7);
}
.value.normal {
color: #66bb6a;
text-shadow: 0 0 8px rgba(102, 187, 106, 0.7);
}
.progress-bar {
width: 100%;
height: 10px;
background: rgba(0, 0, 0, 0.3);
border-radius: 5px;
margin-top: 8px;
overflow: hidden;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}
.progress-fill {
height: 100%;
border-radius: 5px;
transition: width 1s ease-in-out;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.2);
}
.status-grid {
background: linear-gradient(90deg, #00B42A, #66bb6a);
}
.status-stopped {
background: linear-gradient(90deg, #86909C, #b0bec5);
}
.status-standby {
background: linear-gradient(90deg, #1890ff, #4fc3f7);
}
.status-maintenance {
background: linear-gradient(90deg, #FF7D00, #ffa726);
}
.status-offline {
background: linear-gradient(90deg, #faad14, #ffca28);
}
.status-fault {
background: linear-gradient(90deg, #F53F3F, #ef5350);
}
.chart-placeholder {
margin-top: 20px;
background: rgba(25, 55, 95, 0.3);
border-radius: 10px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.2);
}
.chart-placeholder h4 {
margin: 0 0 15px 0;
font-size: 18px;
font-weight: 600;
color: #4fc3f7;
text-align: center;
position: relative;
padding-bottom: 8px;
}
.chart-placeholder h4::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 2px;
background: linear-gradient(90deg, transparent, #4fc3f7, transparent);
}
/* 数值卡片样式 */
.value-card {
background: rgba(25, 55, 95, 0.4);
border-radius: 8px;
padding: 12px;
margin-bottom: 15px;
border: 1px solid rgba(64, 156, 255, 0.3);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.value-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
border-color: rgba(64, 156, 255, 0.6);
}
.value-card .label {
font-size: 14px;
color: #a0d2ff;
margin-bottom: 5px;
}
.value-card .value {
font-size: 24px;
font-weight: 700;
text-align: center;
}
/* 状态指示器 */
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 8px;
}
.status-indicator.grid {
background: #00B42A;
}
.status-indicator.stopped {
background: #86909C;
}
.status-indicator.standby {
background: #1890ff;
}
.status-indicator.maintenance {
background: #FF7D00;
}
.status-indicator.offline {
background: #faad14;
}
.status-indicator.fault {
background: #F53F3F;
}
</style>
<style>
/* 修改关键指标网格布局 */
.key-indicators-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 10px;
}
.indicator-card {
background-image: url(/assets/img/caidan-160_128.png);
background-size: 100% 100%;
/* background: rgba(25, 55, 95, 0.6);
border-radius: 8px; */
padding: 15px;
/* border: 1px solid rgba(64, 156, 255, 0.3); */
display: flex;
align-items: center;
/* background-image: url('/assets/img/common/a.png');
background-size: 100% 100%; */
}
.card-icon {
width: 40px;
height: 40px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
/* margin-right: 12px; */
}
.card-info {
flex: 1;
}
.card-label {
font-size: 12px;
color: #a0d2ff;
margin: 0 0 5px 0;
}
.card-value {
font-size: 18px;
font-weight: bold;
color: #4fc3f7;
margin: 0;
}
/* 修改图表区域样式 */
.chart-section {
margin-bottom: 10px;
background: rgba(25, 55, 95, 0.6);
border-radius: 8px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.3);
/* flex-shrink: 0; */
display: flex;
flex-direction: column;
}
.chart-section h4 {
margin: 0 0 15px 0;
font-size: 16px;
font-weight: 600;
color: #4fc3f7;
text-align: center;
padding-bottom: 8px;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
flex-shrink: 0;
}
.chart-container {
/* height: 120px; */
position: relative;
flex: 1;
}
/* 环境参数网格 */
.environment-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 10px;
}
.env-card {
background: rgba(25, 55, 95, 0.6);
border-radius: 8px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.3);
text-align: center;
}
.env-label {
font-size: 12px;
color: #a0d2ff;
margin: 0 0 5px 0;
}
.env-value {
font-size: 18px;
font-weight: bold;
color: #4fc3f7;
margin: 0 0 5px 0;
}
.env-status {
font-size: 12px;
margin: 0;
}
.text-success {
color: #66bb6a;
}
/* 统计数据网格 */
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 25px;
}
.stat-item {
/* background: rgba(25, 55, 95, 0.6); */
/* border-radius: 8px; */
padding: 18px;
/* border: 1px solid rgba(64, 156, 255, 0.3); */
text-align: center;
/* background-image: url('/assets/img/icon/dz.png'); */
background-image: url('/assets/img/flood/base-active.png');
background-size: 100% 100%;
}
.stat-label {
font-size: 12px;
color: #a0d2ff;
margin: 0 0 5px 0;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #4fc3f7;
margin: 0;
}
/* 预警统计 */
.alert-summary {
background: rgba(25, 55, 95, 0.6);
border-radius: 8px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.3);
margin-bottom: 10px;
flex: 1;
display: flex;
flex-direction: column;
}
.alert-summary h4 {
margin: 0 0 15px 0;
font-size: 16px;
font-weight: 600;
color: #4fc3f7;
text-align: center;
padding-bottom: 8px;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
flex-shrink: 0;
}
.alert-stats-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
flex-shrink: 0;
margin-top: 20px;
}
.alert-stat {
text-align: center;
background-image: url('/assets/img/common/bottomItemBg.png');
background-size: 100% 100%;
}
.alert-count {
font-size: 24px;
font-weight: bold;
margin: 15px 0 5px 0;
}
.alert-count.critical {
color: #f44336;
}
.alert-count.warning {
color: #ff9800;
}
.alert-count.normal {
color: #66bb6a;
}
.alert-type {
font-size: 12px;
color: #fffa18;
margin: 20px;
}
</style>
<style>
/* 运行统计区域 */
.stats-section {
margin-bottom: 25px;
background: rgba(25, 55, 95, 0.6);
border-radius: 8px;
padding: 15px;
border: 1px solid rgba(64, 156, 255, 0.3);
}
.stats-section h4 {
margin: 0 0 15px 0;
font-size: 16px;
font-weight: 600;
color: #4fc3f7;
text-align: center;
padding-bottom: 8px;
border-bottom: 1px solid rgba(64, 156, 255, 0.3);
}
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.stat-card {
background: rgba(16, 36, 62, 0.4);
border-radius: 6px;
padding: 12px;
text-align: center;
border: 1px solid rgba(64, 156, 255, 0.2);
}
.stat-title {
font-size: 12px;
color: #a0d2ff;
margin: 0 0 5px 0;
}
.stat-number {
font-size: 20px;
font-weight: bold;
color: #4fc3f7;
margin: 0 0 3px 0;
}
.stat-unit {
font-size: 14px;
color: #81d4fa;
}
.stat-desc {
font-size: 11px;
color: #81d4fa;
margin: 0;
}
/* 图表统计信息 */
.chart-stats {
display: flex;
justify-content: space-around;
margin-top: 15px;
padding-top: 12px;
border-top: 1px solid rgba(64, 156, 255, 0.2);
}
.chart-stats .stat-item {
text-align: center;
}
.chart-stats .stat-label {
font-size: 12px;
color: #a0d2ff;
display: block;
margin-bottom: 5px;
}
.chart-stats .stat-value {
font-size: 16px;
font-weight: bold;
color: #e8ffdc;
}
/* 状态详情 */
.status-details {
margin-top: 15px;
padding-top: 12px;
border-top: 1px solid rgba(64, 156, 255, 0.2);
}
.status-item {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
}
.status-item:last-child {
margin-bottom: 0;
}
.status-label {
font-size: 13px;
color: #cce0ff;
display: flex;
align-items: center;
}
.status-dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 8px;
}
.status-value {
font-size: 13px;
font-weight: bold;
color: #4fc3f7;
}
</style>
<style>
/* 预警统计详情 */
.alert-details {
/* margin-top: 20px; */
padding-top: 15px;
border-top: 1px solid rgba(64, 156, 255, 0.2);
flex: 1;
display: flex;
flex-direction: column;
}
.alert-details h5 {
font-size: 14px;
color: #4fc3f7;
margin: 0 0 12px 0;
text-align: center;
flex-shrink: 0;
}
.alert-list {
flex: 1;
overflow-y: auto;
padding-right: 5px;
}
/* 隐藏滚动条但保持滚动功能 */
.alert-list::-webkit-scrollbar {
width: 0;
background: transparent;
}
.alert-list::-webkit-scrollbar-thumb {
background: transparent;
}
/* Firefox */
.alert-list {
scrollbar-width: none;
}
/* IE/Edge */
.alert-list {
-ms-overflow-style: none;
}
.alert-item {
background: rgba(16, 36, 62, 0.4);
border-radius: 6px;
padding: 10px;
margin-bottom: 10px;
border-left: 3px solid;
}
.alert-item:last-child {
margin-bottom: 0;
}
.alert-item.critical {
border-left-color: #f44336;
}
.alert-item.warning {
border-left-color: #ff9800;
}
.alert-item.normal {
border-left-color: #66bb6a;
}
.alert-header {
display: flex;
align-items: center;
margin-bottom: 5px;
}
.alert-icon {
font-size: 14px;
margin-right: 8px;
}
.alert-item.critical .alert-icon {
color: #f44336;
}
.alert-item.warning .alert-icon {
color: #ff9800;
}
.alert-item.normal .alert-icon {
color: #66bb6a;
}
.alert-title {
flex: 1;
font-size: 13px;
font-weight: 600;
color: #e0f0ff;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.alert-time {
font-size: 11px;
color: #81d4fa;
}
.alert-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.alert-desc {
font-size: 12px;
color: #a0d2ff;
flex: 1;
margin: 0 10px 0 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.alert-status {
flex-shrink: 0;
}
.status-tag {
font-size: 10px;
padding: 2px 6px;
border-radius: 10px;
font-weight: 600;
}
.status-tag.critical {
background: rgba(244, 67, 54, 0.2);
color: #f44336;
}
.status-tag.warning {
background: rgba(255, 152, 0, 0.2);
color: #ff9800;
}
.status-tag.normal {
background: rgba(102, 187, 106, 0.2);
color: #66bb6a;
}
.alert-footer {
text-align: center;
margin-top: 12px;
flex-shrink: 0;
}
.view-all-alerts {
font-size: 12px;
color: #4fc3f7;
text-decoration: none;
}
.view-all-alerts:hover {
text-decoration: underline;
}
</style>
<style>
.chart_title {
height: 5vh;
background: url('./assets/img/common/homeTitle.png') no-repeat;
background-position: center;
background-position-x: center;
background-position-y: center;
background-size: 108% 120%;
display: flex;
justify-content: center;
align-items: center;
}
.chart_title .title span {
font-size: 2.4vh;
letter-spacing: 0.2vh;
font-family: YouSheBiaoTiHei;
font-weight: 400;
color: #ffffff;
}
.tourButton {
background-image: url('./assets/img/common/b.png');
background-size: 100% 100%;
}
/* 风机详情面板样式 */
.detail-panel {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
width: 350px;
background: rgba(25, 55, 95, 0.85);
border: 1px solid rgba(64, 156, 255, 0.6);
border-radius: 10px;
color: #e0f0ff;
z-index: 1000;
backdrop-filter: blur(5px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
padding: 15px;
}
.detail-panel.hidden {
display: none;
}
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10px;
border-bottom: 1px solid rgba(64, 156, 255, 0.4);
margin-bottom: 15px;
}
.detail-header h3 {
margin: 0;
font-size: 18px;
color: #4fc3f7;
font-weight: 600;
}
.close-btn {
background: none;
border: none;
color: #a0d2ff;
font-size: 20px;
cursor: pointer;
padding: 0;
width: 25px;
height: 25px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.close-btn:hover {
background: rgba(244, 67, 54, 0.2);
color: #f44336;
}
.detail-content {
padding: 5px 0;
}
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding: 8px 10px;
background: rgba(16, 36, 62, 0.5);
border-radius: 6px;
border: 1px solid rgba(64, 156, 255, 0.15);
}
.detail-item:last-child {
margin-bottom: 0;
}
.detail-item label {
font-size: 13px;
color: #cce0ff;
font-weight: 500;
}
.detail-item .value {
font-size: 15px;
font-weight: 700;
color: #4fc3f7;
}
/* 状态颜色 */
.status-grid {
color: #00B42A;
}
.status-stopped {
color: #86909C;
}
.status-standby {
color: #1890ff;
}
.status-maintenance {
color: #FF7D00;
}
.status-fault {
color: #F53F3F;
}
/* 响应式设计 */
@media (max-width: 768px) {
.detail-panel {
width: 300px;
left: 50%;
right: auto;
transform: translateX(-50%);
}
}
</style>
<!-- 在页面的 <style> 部分添加以下样式 -->
<style>
.loading {
text-align: center;
padding: 50px;
font-size: 18px;
color: #666;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
margin-bottom: 15px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.wind-barb-legend {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
margin: 10px 0;
font-size: 11px;
}
.legend-item {
text-align: center;
}
.legend-barb {
display: inline-block;
margin-bottom: 3px;
}
</style>
</head>
<body>
<div id="container">
<div id="loading">正在加载海上风电机组场景...</div>
</div>
<!-- 左侧面板 -->
<div id="left-panel" class="panel left-panel">
<div class="panel-content">
<!-- 关键指标卡片 -->
<!-- <div class="chart-section">
<div class="chart_title">
<span>风廓线雷达</span>
</div>
<div class="key-indicators-grid">
</div>
</div> -->
<!-- 替换原有的空 key-indicators-grid 为完整的激光测风雷达模块 -->
<!-- 替换原有的风廓线雷达模块 -->
<div class="chart-section" style="display: flex; flex-direction: column; flex: 1;">
<div class="chart_title">
<span>风廓线雷达</span>
</div>
<div class="chart-container" style="flex: 1; position: relative;">
<div id="windRadarChart" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;">
<div class="loading"
style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%;">
<div class="spinner"
style="border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 2s linear infinite; margin-bottom: 15px;">
</div>
<div>风向杆图表加载中...</div>
</div>
</div>
</div>
</div>
<!-- 实时功率图表 -->
<div class="chart-section">
<div class="chart_title">
<span>XBT</span>
</div>
<div class="chart-container">
<canvas id="realtimePowerChart"></canvas>
</div>
<div class="chart-stats">
<div class="stat-item">
<span class="stat-label">波周期</span>
<span class="stat-value">7.7 s</span>
</div>
<div class="stat-item">
<span class="stat-label">波向</span>
<span class="stat-value">85°</span>
</div>
<div class="stat-item">
<span class="stat-label">采样频率</span>
<span class="stat-value">2.5 Hz</span>
</div>
</div>
</div>
<div class="chart-section" style="flex: 1;display: flex;flex-direction: column;">
<div class="chart_title">
<span>XCTD</span>
</div>
<div class="chart-container">
<canvas id="unitStatusChart"></canvas>
</div>
<div class="status-details">
<div class="status-item">
<span class="status-label">
<span class="status-dot status-grid"></span>
表层(0m)
</span>
<span class="status-value">29.08 ℃ / 53.20 mS/cm</span>
</div>
<div class="status-item">
<span class="status-label">
<span class="status-dot status-maintenance"></span>
中层(100m)
</span>
<span class="status-value">16.2 ℃ / 42.10 mS/cm</span>
</div>
<div class="status-item">
<span class="status-label">
<span class="status-dot status-fault"></span>
深层(1000m)
</span>
<span class="status-value">4.82 ℃ / 37.55 mS/cm</span>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧面板 -->
<div id="right-panel" class="panel right-panel">
<div class="panel-content">
<!-- 环境参数 -->
<div class="chart-section">
<div class="chart_title">
<span>拖曳式磁力仪</span>
</div>
<div class="key-indicators-grid">
<div class="indicator-card">
<div class="card-icon bg-warning/10">
<img src="/assets/img/icon/总场次.png" alt="">
</div>
<div class="card-info">
<p class="card-label">总场</p>
<p class="card-value" style="color: #e48527;">48492.31</p>
<p class="env-status">nT</p>
</div>
</div>
<div class="indicator-card">
<div class="card-icon bg-warning/10">
<img src="/assets/img/icon/修正带.png" alt="">
</div>
<div class="card-info">
<p class="card-label">日变修正</p>
<p class="card-value" style="color: #f4ea2a;">-12.4</p>
<p class="env-status">nT</p>
</div>
</div>
<div class="indicator-card">
<div class="card-icon bg-warning/10">
<img src="/assets/img/icon/大气噪声.png" alt="">
</div>
<div class="card-info">
<p class="card-label">噪声RMS</p>
<p class="card-value">0.13 </p>
<p class="env-status">nT </p>
</div>
</div>
<!-- <div class="indicator-card">
<div class="card-icon bg-warning/10">
<img src="/assets/img/icon/海浪.png" alt="">
</div>
<div class="card-info">
<p class="card-label">DO (3m)</p>
<p class="card-value">7.05 mg/L</p>
<p class="env-status">正常</p>
</div>
</div> -->
</div>
</div>
<!-- 发电效率分析 -->
<div class="chart-section" style="flex: 1;min-height: 300px;">
<div class="chart_title">
<span>海水采样器</span>
</div>
<div class="chart-container" style="height: auto; flex: 1;">
<div id="efficiencyChartMini" style="width: 100%; height: 100%;"></div>
</div>
</div>
<!-- 预警统计 -->
<div class="alert-summary" style="flex: 1; display: flex; flex-direction: column;">
<div class="chart_title">
<span>侧扫声呐</span>
</div>
<!-- 详细预警信息 -->
<div class="alert-details" style="flex: 1; display: flex; flex-direction: column;">
<img src="/assets/img/声呐图.png" alt="" style="flex: 1; display: flex; flex-direction: column;">
</div>
</div>
</div>
</div>
<!-- 在你的HTML文件中添加 -->
<!-- <div style="position: absolute; bottom: 20px; right: 350px; z-index: 100;">
<div id="tourButton" onclick="toggleAutoTour()" class="tourButton"
style="padding: 20px; color: white; border: none; border-radius: 5px; cursor: pointer;">
开始漫游
</div>
</div> -->
<!-- 将原有的开始漫游按钮区域替换为经纬度显示 -->
<div style="position: absolute; bottom: 20px; right: 350px; z-index: 100;">
<div class="chart-section"
style="background: none;background-image: url('/assets/img/moshi-2-300_100.png');background-size: 100% 100%;">
<div style="text-align: center;padding: 10px 20px 40px;">
<div style="margin-bottom: 8px;">
<span
style="color: #81d4fa; font-size: 16px; font-weight: bold; margin-left: 5px;">
114.0807°E</span>
</div>
<div>
<span style="color: #81d4fa; font-size: 16px; font-weight: bold; margin-left: 5px;">
13.5604°N</span>
</div>
</div>
</div>
</div>
<!-- Three.js 核心库 -->
<script src="js/three.min.js"></script>
<!-- 引入RGBELoader -->
<script src="js/RGBELoader.js"></script>
<!-- <script src="https://unpkg.com/three@0.132.2/examples/js/loaders/RGBELoader.js"></script> -->
<!-- 本地Three.js扩展库 -->
<script src="js/OrbitControls.js"></script>
<!-- Water.js 水面效果 -->
<script src="js/Water.js"></script>
<!-- Sky.js 天空效果 -->
<script src="js/Sky.js"></script>
<!-- GLTF加载器 -->
<script src="js/GLTFLoader.js"></script>
<!-- DRACO解码器 - 使用本地版本 -->
<script src="js/DRACOLoader.js"></script>
<script src="draco/draco_decoder.js"></script>
<script src="draco/draco_wasm_wrapper.js"></script>
<script src="js/fflate.min.js"></script>
<script src="js/FBXLoader.js"></script>
<script src="js/echarts.min.js"></script>
<!-- 主程序 -->
<script src="device_main.js"></script>
<script>
// 初始化波浪参数图表
function initRealtimePowerChart() {
const ctx = document.getElementById('realtimePowerChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['0m', '10m', '20m', '50m', '100m', '200m'],
datasets: [{
label: '温度 (℃)',
data: [29.15, 24.12, 21.97, 21.04, 19.88, 18.33],
borderColor: '#40a9ff',
backgroundColor: 'rgba(64, 169, 255, 0.1)',
borderWidth: 2,
pointRadius: 3,
pointBackgroundColor: '#40a9ff',
pointBorderColor: '#ffffff',
pointBorderWidth: 1,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: function (context) {
return `温度: ${context.parsed.y}`;
}
}
}
},
scales: {
y: {
title: {
display: true,
text: '温度 (℃)',
color: 'rgba(255, 255, 255, 0.7)'
},
ticks: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
size: 10
}
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
x: {
ticks: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
size: 10
}
},
grid: {
display: false
}
}
}
}
});
}
// 初始化温度剖面图表
function initUnitStatusChart() {
const ctx = document.getElementById('unitStatusChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['0m', '50m', '100m', '200m', '500m', '1000m'],
datasets: [{
label: '温度 (℃)',
data: [29.08, 20.5, 16.2, 12.8, 10.5, 4.82],
borderColor: '#00B42A', // 绿色
backgroundColor: 'rgba(0, 180, 42, 0.1)',
borderWidth: 2,
pointRadius: 3,
pointBackgroundColor: '#00B42A',
pointBorderColor: '#ffffff',
pointBorderWidth: 1,
fill: false,
yAxisID: 'y'
}, {
label: '电导率 (mS/cm)',
data: [53.20, 45.8, 42.1, 41.3, 39.2, 37.55],
borderColor: 'red', // 蓝色
backgroundColor: 'rgba(79, 195, 247, 0.1)',
borderWidth: 2,
pointRadius: 3,
pointBackgroundColor: '#4fc3f7',
pointBorderColor: '#ffffff',
pointBorderWidth: 1,
fill: false,
yAxisID: 'y1'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
labels: {
color: '#ffffff',
font: {
size: 10
}
}
},
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: function (context) {
if (context.datasetIndex === 0) {
return `温度: ${context.parsed.y}`;
} else {
return `电导率: ${context.parsed.y} mS/cm`;
}
}
}
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
title: {
display: true,
text: '温度 (℃)',
color: 'rgba(255, 255, 255, 0.7)'
},
ticks: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
size: 10
}
},
grid: {
color: 'rgba(255, 255, 255, 0.1)'
}
},
y1: {
type: 'linear',
display: true,
position: 'right',
title: {
display: true,
text: '电导率 (mS/cm)',
color: 'rgba(255, 255, 255, 0.7)'
},
ticks: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
size: 10
}
},
grid: {
drawOnChartArea: false,
color: 'rgba(255, 255, 255, 0.1)'
}
},
x: {
ticks: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
size: 10
}
},
grid: {
display: false
}
}
}
}
});
}
// 替换原有的 initEfficiencyChartMini 函数
function initEfficiencyChartMini() {
// 基于准备好的dom初始化echarts实例
const myChart = echarts.init(document.getElementById('efficiencyChartMini'));
// 配置选项
const option = {
// title: {
// text: '海水化学参数垂直剖面图',
// subtext: '深度作为纵坐标,参数值作为横坐标',
// left: 'center',
// textStyle: {
// fontSize: 22,
// color: '#18ffd6'
// },
// subtextStyle: {
// fontSize: 16,
// color: '#666'
// }
// },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
formatter: function (params) {
let result = `<div style="font-weight:bold;margin-bottom:5px;">深度: ${params[0].name}</div>`;
params.forEach(param => {
result += `<div style="display:flex;align-items:center;margin:3px 0;">
<span style="display:inline-block;width:10px;height:10px;background:${param.color};margin-right:5px;"></span>
${param.seriesName}: ${param.value} ${param.axisId === 'xAxis1' ? 'µg L⁻¹' :
param.axisId === 'xAxis2' ? 'mg L⁻¹' :
param.axisId === 'xAxis3' ? 'µmol L⁻¹' : 'µmol L⁻¹'}
</div>`;
});
return result;
}
},
// legend: {
// data: ['叶绿素-a', '溶解氧', '硝酸盐', '磷酸盐'],
// top: 50,
// textStyle: {
// fontSize: 14
// }
// },
grid: {
left: '22%',
right: '23%',
bottom: '25%',
top: '25%',
containLabel: false
},
xAxis: [
{
id: 'xAxis1',
type: 'value',
name: '叶绿素-a\n(µg L⁻¹)',
position: 'top',
axisLine: {
lineStyle: {
color: '#0ecf3b'
}
},
axisLabel: {
formatter: '{value}',
color: '#0ecf3b'
},
nameTextStyle: {
color: '#0ecf3b',
fontSize: 10,
fontWeight: 'bold'
},
min: 0,
max: 0.5,
splitLine: {
show: false
}
},
{
id: 'xAxis2',
type: 'value',
name: '溶解氧\n(mg L⁻¹)',
position: 'top',
offset: 40,
axisLine: {
lineStyle: {
color: '#4fc3f7'
}
},
axisLabel: {
formatter: '{value}',
color: '#4fc3f7'
},
nameTextStyle: {
color: '#4fc3f7',
fontSize: 10,
fontWeight: 'bold'
},
min: 2,
max: 8,
splitLine: {
show: false
}
},
{
id: 'xAxis3',
type: 'value',
name: '硝酸盐\n(µmol L⁻¹)',
position: 'bottom',
axisLine: {
lineStyle: {
color: '#FF9800'
}
},
axisLabel: {
formatter: '{value}',
color: '#FF9800'
},
nameTextStyle: {
color: '#FF9800',
fontSize: 10,
fontWeight: 'bold'
},
min: 0,
max: 35,
splitLine: {
show: false
}
},
{
id: 'xAxis4',
type: 'value',
name: '磷酸盐\n(µmol L⁻¹)',
position: 'bottom',
offset: 40,
axisLine: {
lineStyle: {
color: '#e64ff7'
}
},
axisLabel: {
formatter: '{value}',
color: '#e64ff7'
},
nameTextStyle: {
color: '#e64ff7',
fontSize: 10,
fontWeight: 'bold'
},
min: 0,
max: 2.5,
splitLine: {
show: false
}
}
],
yAxis: {
type: 'category',
data: ['3 m', '75 m', '200 m', '500 m', '1000 m'],
axisLine: {
lineStyle: {
color: '#18ffd6'
}
},
axisLabel: {
color: '#18ffd6',
fontSize: 12
},
name: '深度',
nameLocation: 'middle',
nameGap: 50,
nameTextStyle: {
fontSize: 12,
fontWeight: 'bold'
},
inverse: true // 使深度从上到下增加
},
series: [
{
name: '叶绿素-a',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
data: [
{ value: 0.28, name: '3 m' },
{ value: 0.42, name: '75 m' },
{ value: 0.12, name: '200 m' },
{ value: 0.02, name: '500 m' },
{ value: 0.01, name: '1000 m' }
],
lineStyle: {
width: 3,
color: '#0ecf3b'
},
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#0ecf3b'
},
smooth: true
},
{
name: '溶解氧',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 0,
data: [
{ value: 7.05, name: '3 m' },
{ value: 5.12, name: '75 m' },
{ value: 4.05, name: '200 m' },
{ value: 2.80, name: '500 m' },
{ value: 4.00, name: '1000 m' }
],
lineStyle: {
width: 3,
color: '#4fc3f7'
},
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#4fc3f7'
},
smooth: true
},
{
name: '硝酸盐',
type: 'line',
xAxisIndex: 2,
yAxisIndex: 0,
data: [
{ value: 0.4, name: '3 m' },
{ value: 4.5, name: '75 m' },
{ value: 16.8, name: '200 m' },
{ value: 27.5, name: '500 m' },
{ value: 32.0, name: '1000 m' }
],
lineStyle: {
width: 3,
color: '#FF9800'
},
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#FF9800'
},
smooth: true
},
{
name: '磷酸盐',
type: 'line',
xAxisIndex: 3,
yAxisIndex: 0,
data: [
{ value: 0.08, name: '3 m' },
{ value: 0.25, name: '75 m' },
{ value: 1.05, name: '200 m' },
{ value: 1.72, name: '500 m' },
{ value: 2.10, name: '1000 m' }
],
lineStyle: {
width: 3,
color: '#e64ff7'
},
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#e64ff7'
},
smooth: true
}
],
// toolbox: {
// feature: {
// saveAsImage: {
// title: '保存为图片'
// },
// dataView: {
// title: '数据视图',
// readOnly: true,
// lang: ['数据视图', '关闭', '刷新']
// }
// },
// right: 20,
// top: 20
// }
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
// 响应窗口大小变化
window.addEventListener('resize', function () {
myChart.resize();
});
}
// 页面加载后初始化所有图表
document.addEventListener('DOMContentLoaded', function () {
initRealtimePowerChart();
initUnitStatusChart();
initEfficiencyChartMini();
// 等待一段时间确保echarts加载完成
//setTimeout(initWindBarbChart, 500);
});
</script>
<!-- 修改风向杆图表初始化代码 -->
<script>
// 在页面加载完成后初始化风向杆图表
document.addEventListener('DOMContentLoaded', function () {
// 等待一段时间确保echarts加载完成
setTimeout(initWindBarbChart, 500);
});
// 添加窗口大小调整处理函数
function handleResize() {
if (window.windBarbChartInstance) {
window.windBarbChartInstance.resize();
}
}
// 监听窗口大小变化
window.addEventListener('resize', handleResize);
function initWindBarbChart() {
const chartDom = document.getElementById('windRadarChart');
// 检查echarts是否已加载
if (typeof echarts === 'undefined') {
chartDom.innerHTML = `
<div class="loading">
<div style="color: #e74c3c; font-size: 24px;">⚠️</div>
<div>ECharts库加载失败</div>
<div style="font-size: 12px; margin-top: 10px;">请检查网络连接或刷新页面重试</div>
</div>
`;
return;
}
// 显示加载状态
chartDom.innerHTML = `
<div class="loading">
<div class="spinner"></div>
<div>正在生成风向杆数据...</div>
</div>
`;
// 延迟一小段时间后渲染图表,模拟数据加载
setTimeout(() => {
// 使用 echarts.init 初始化图表并保存实例
const myChart = echarts.init(chartDom);
// 保存图表实例到全局变量,以便在窗口大小调整时使用
window.windBarbChartInstance = myChart;
// 风速颜色映射
const windSpeedColors = [
{ min: 0, max: 2, color: '#98FB98', label: '0-2 m/s' }, // 浅绿色 - 微风
{ min: 2, max: 5, color: '#7EC8E3', label: '2-5 m/s' }, // 浅蓝色 - 轻风
{ min: 5, max: 10, color: '#FFD700', label: '5-10 m/s' }, // 黄色 - 和风
{ min: 10, max: 15, color: '#FFA500', label: '10-15 m/s' }, // 橙色 - 清风
{ min: 15, max: 20, color: '#FF6347', label: '15-20 m/s' }, // 番茄红 - 强风
{ min: 20, max: 25, color: '#DC143C', label: '20-25 m/s' }, // 深红 - 大风
{ min: 25, max: 50, color: '#8B0000', label: '25-50 m/s' } // 暗红 - 狂风
];
// 根据风速获取颜色
function getColorForWindSpeed(speed) {
for (const range of windSpeedColors) {
if (speed >= range.min && speed < range.max) {
return range.color;
}
}
return windSpeedColors[windSpeedColors.length - 1].color; // 默认返回最高风速颜色
}
// 绘制风矢杆
function drawWindBarb(ctx, direction, speed, barbLength, isExample = false) {
const radian = (direction - 180) * Math.PI / 180; // 指向风的来向
// 根据风速获取颜色
const color = getColorForWindSpeed(speed);
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineWidth = 1.5;
ctx.lineCap = 'round';
if (speed === 0) {
// 静风 - 画圆圈
ctx.beginPath();
ctx.arc(0, 0, 4, 0, 2 * Math.PI);
ctx.stroke();
return;
}
// 绘制主杆
ctx.beginPath();
ctx.moveTo(0, 0);
const endX = Math.cos(radian) * barbLength;
const endY = Math.sin(radian) * barbLength;
ctx.lineTo(endX, endY);
ctx.stroke();
// 绘制风羽
let remainingSpeed = speed;
let position = 0;
const spacing = isExample ? 6 : 4;
// 绘制三角旗 (20 m/s)
const triangles = Math.floor(remainingSpeed / 20);
remainingSpeed %= 20;
for (let i = 0; i < triangles; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const triangleSize = isExample ? 8 : 6;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * triangleSize,
posY + Math.sin(perpendicular) * triangleSize
);
ctx.lineTo(
posX + Math.cos(radian) * triangleSize + Math.cos(perpendicular) * triangleSize,
posY + Math.sin(radian) * triangleSize + Math.sin(perpendicular) * triangleSize
);
ctx.closePath();
ctx.fill();
position += 2;
}
// 绘制长羽 (4 m/s)
const longFeathers = Math.floor(remainingSpeed / 4);
remainingSpeed %= 4;
for (let i = 0; i < longFeathers; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const featherLength = isExample ? 10 : 8;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * featherLength,
posY + Math.sin(perpendicular) * featherLength
);
ctx.stroke();
position += 1;
}
// 绘制短羽 (2 m/s)
const shortFeathers = Math.floor(remainingSpeed / 2);
for (let i = 0; i < shortFeathers; i++) {
const posX = Math.cos(radian) * (position * spacing);
const posY = Math.sin(radian) * (position * spacing);
const perpendicular = radian + Math.PI / 2;
const featherLength = isExample ? 6 : 5;
ctx.beginPath();
ctx.moveTo(posX, posY);
ctx.lineTo(
posX + Math.cos(perpendicular) * featherLength,
posY + Math.sin(perpendicular) * featherLength
);
ctx.stroke();
position += 1;
}
}
// 生成精确数据
function generateData() {
const times = [];
const heights = [];
const data = [];
// 生成时间序列12个时间点
const now = new Date();
for (let i = 7; i >= 0; i--) {
const time = new Date(now.getTime() - i * 2 * 60 * 60 * 1000);
times.push(time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }));
}
// 生成高度序列从250m到3850m每240m一个点
for (let h = 250; h <= 3850; h += 480) {
heights.push(h);
}
// 根据要求生成精确的风向风速数据
for (let i = 0; i < times.length; i++) {
for (let j = 0; j < heights.length; j++) {
const height = heights[j];
let direction, speed;
// 根据高度设置风向风速
if (height === 250) {
// 250m: 东南风135°, 14m/s (3个长羽1个短羽)
direction = 135;
speed = 14;
} else if (height === 490) {
// 490m: 西北风315°, 16m/s (1个长羽)
direction = 315;
speed = 16;
} else if (height >= 730 && height <= 2170) {
// 730m至2170m: 东北风45°, 8m/s (1个长羽1个短羽)
direction = 45;
speed = 8;
} else if (height >= 2410 && height <= 3850) {
// 2410m至3850m: 东风90°, 45m/s (2个三角旗1个长羽1个短羽)
direction = 90;
speed = 45;
} else {
// 其他高度使用默认数据
const directions = [0, 45, 90, 135, 180, 225, 270, 315];
direction = directions[Math.floor(Math.random() * directions.length)];
speed = Math.floor(Math.random() * 20) + 5;
}
data.push([i, j, direction, speed]);
}
}
return { times, heights, data };
}
// 渲染风矢杆项目
function renderWindBarb(params, api) {
const xIndex = api.value(0);
const yIndex = api.value(1);
const direction = api.value(2);
const speed = api.value(3);
const point = api.coord([xIndex, yIndex]);
const barbLength = 25; // 风矢杆长度
const group = {
type: 'group',
children: [],
silent: false
};
// 创建canvas绘制风矢杆
const canvas = document.createElement('canvas');
canvas.width = 60;
canvas.height = 60;
const ctx = canvas.getContext('2d');
ctx.translate(30, 30);
drawWindBarb(ctx, direction, speed, barbLength);
group.children.push({
type: 'image',
style: {
image: canvas,
x: point[0] - 30,
y: point[1] - 30,
width: 60,
height: 60
}
});
return group;
}
// 获取风向文本描述
function getDirectionText(direction) {
const directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
const index = Math.round(direction / 45) % 8;
return directions[index];
}
// 获取风羽描述
function getWindBarbDescription(speed) {
if (speed === 0) return '静风';
let description = '风羽: ';
let remaining = speed;
const triangles = Math.floor(remaining / 20);
remaining %= 20;
if (triangles > 0) description += `${triangles}个三角旗 `;
const longFeathers = Math.floor(remaining / 4);
remaining %= 4;
if (longFeathers > 0) description += `${longFeathers}个长羽 `;
const shortFeathers = Math.floor(remaining / 2);
if (shortFeathers > 0) description += `${shortFeathers}个短羽`;
return description.trim();
}
const { times, heights, data } = generateData();
const option = {
// title: {
// text: '激光测风雷达风向杆图',
// left: 'center',
// textStyle: {
// fontSize: 14,
// fontWeight: 'bold',
// color: '#e0f0ff'
// }
// },
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#40a9ff',
borderWidth: 1,
textStyle: {
color: '#e0f0ff'
},
formatter: function (params) {
const time = times[params.value[0]];
const height = heights[params.value[1]];
const direction = params.value[2];
const speed = params.value[3];
const directionText = getDirectionText(direction);
const barbDescription = getWindBarbDescription(speed);
const colorLabel = windSpeedColors.find(range => speed >= range.min && speed < range.max)?.label || '未知';
return `
<div style="font-weight: bold; margin-bottom: 5px;">${time}</div>
<div>高度: <b>${height}m</b></div>
<div>风向: <b>${Math.round(direction)}° ${directionText}</b></div>
<div>风速: <b>${speed} m/s</b></div>
<div style="margin-top: 5px; font-size: 12px; color: #ccc;">
${barbDescription}
</div>
<div style="font-size: 12px; color: #ccc;">
风速范围: ${colorLabel}
</div>
`;
}
},
grid: {
left: '70px',
right: '100px',
bottom: '70px',
top: '50px',
containLabel: false
},
xAxis: {
type: 'category',
data: times,
name: '时间',
nameLocation: 'middle',
nameGap: 30,
axisLabel: {
color: '#a0d2ff',
fontSize: 10,
interval: 1,
rotate: 45
},
axisLine: {
lineStyle: {
color: '#40a9ff'
}
}
},
yAxis: {
type: 'category',
data: heights.map(h => h + 'm'),
name: '高度 (m)',
nameLocation: 'middle',
nameGap: 50,
axisLabel: {
color: '#a0d2ff',
fontSize: 10
},
axisLine: {
lineStyle: {
color: '#40a9ff'
}
},
inverse: false // 从下往上递增
},
visualMap: {
type: 'piecewise',
min: 0,
max: 50,
orient: 'vertical',
right: 10,
top: 'center',
textStyle: {
color: '#a0d2ff',
fontSize: 9
},
pieces: windSpeedColors,
name: '风速\n(m/s)',
nameTextStyle: {
fontSize: 10,
fontWeight: 'bold',
color: '#e0f0ff'
},
formatter: function (value) {
// 自定义格式化显示
const range = windSpeedColors.find(range =>
value.min === range.min && value.max === range.max
);
return range ? range.label : '';
}
},
series: [{
name: '风矢杆',
type: 'custom',
renderItem: renderWindBarb,
data: data,
encode: {
x: [0],
y: [1]
},
animation: true,
animationDuration: 800
}]
};
myChart.setOption(option);
// 添加窗口大小调整事件监听
window.addEventListener('resize', function () {
myChart.resize();
});
// 创建图例示例
setTimeout(() => {
createLegendExamples();
}, 100);
// 创建图例示例
function createLegendExamples() {
// 创建图例容器
const legendContainer = document.createElement('div');
legendContainer.className = 'wind-barb-legend';
legendContainer.style.cssText = `
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
margin: 10px 0;
font-size: 11px;
`;
// 图例项
const legendItems = [
{ id: 'legend-short-feather', text: '短羽 = 2 m/s' },
{ id: 'legend-long-feather', text: '长羽 = 4 m/s' },
{ id: 'legend-triangle', text: '三角旗 = 20 m/s' },
{ id: 'legend-calm', text: '圆圈 = 静风' }
];
legendItems.forEach(item => {
const legendItem = document.createElement('div');
legendItem.className = 'legend-item';
legendItem.style.cssText = 'text-align: center;';
const legendBarb = document.createElement('div');
legendBarb.className = 'legend-barb';
legendBarb.id = item.id;
legendBarb.style.cssText = 'display: inline-block; margin-bottom: 3px;';
const legendText = document.createElement('div');
legendText.textContent = item.text;
legendItem.appendChild(legendBarb);
legendItem.appendChild(legendText);
legendContainer.appendChild(legendItem);
});
//chartDom.parentNode.appendChild(legendContainer);
// 创建风矢杆示例
createWindBarbExample('legend-short-feather', 0, 2, 0); // 短羽
createWindBarbExample('legend-long-feather', 0, 4, 0); // 长羽
createWindBarbExample('legend-triangle', 0, 20, 0); // 三角旗
createWindBarbExample('legend-calm', 0, 0, 0); // 静风
}
// 创建风矢杆示例
function createWindBarbExample(elementId, direction, speed, exampleDirection) {
const container = document.getElementById(elementId);
if (!container) return;
const canvas = document.createElement('canvas');
canvas.width = 40;
canvas.height = 40;
const ctx = canvas.getContext('2d');
ctx.translate(20, 20);
drawWindBarb(ctx, exampleDirection, speed, 15, true);
container.appendChild(canvas);
}
}, 1000);
}
</script>
</body>
</html>