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.
MaritimeExpo/ExpeditionTask/风向杆可视化测试页面.html

374 lines
13 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>
<!-- 主要CDN -->
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.min.js"></script> -->
<script src="/js/echarts5.4.3/echarts.min.js"></script>
<!-- 备用CDN -->
<!-- <script>
// 如果主要CDN加载失败使用备用CDN
if (typeof echarts === 'undefined') {
document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"><\/script>');
}
</script> -->
<style>
body {
font-family: 'Arial', sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
padding: 25px;
backdrop-filter: blur(10px);
}
h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 25px;
font-size: 28px;
font-weight: 600;
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
}
#windChart {
width: 100%;
height: 650px;
border: 1px solid #e1e8ed;
border-radius: 10px;
background: #fafbfc;
}
.description {
margin-top: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #3498db;
}
.description p {
margin: 8px 0;
color: #555;
font-size: 14px;
line-height: 1.5;
}
.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); }
}
.controls {
margin-bottom: 20px;
text-align: center;
}
.controls button {
background: #3498db;
color: white;
border: none;
padding: 10px 20px;
margin: 0 5px;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s;
}
.controls button:hover {
background: #2980b9;
}
</style>
</head>
<body>
<div class="container">
<h1>🌬️ 风向杆可视化图</h1>
<div class="controls">
<button onclick="refreshData()">🔄 刷新数据</button>
<button onclick="toggleAnimation()">⏯️ 切换动画</button>
</div>
<div id="windChart">
<div class="loading">
<div class="spinner"></div>
<div>图表加载中...</div>
</div>
</div>
<div class="description">
<p><strong>图表说明:</strong></p>
<p><strong>横坐标</strong>时间轴显示24小时的时间序列</p>
<p><strong>纵坐标</strong>高度轴从250米到3850米</p>
<p><strong>风向杆</strong>方向表示风向0°=北90°=东180°=南270°=西)</p>
<p><strong>颜色图例</strong>:右侧颜色条表示风速大小(绿色=低速,橙色=中速,红色=高速)</p>
</div>
</div>
<script>
let chartInstance = null;
let animationEnabled = true;
// 初始化图表
function initChart() {
const chartDom = document.getElementById('windChart');
// 检查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;
}
chartInstance = echarts.init(chartDom);
updateChart();
// 响应窗口大小变化
window.addEventListener('resize', function() {
if (chartInstance) {
chartInstance.resize();
}
});
}
// 生成模拟数据
function generateData() {
const times = [];
const heights = [];
const data = [];
// 生成时间序列24个时间点
const now = new Date();
for (let i = 23; i >= 0; i--) {
const time = new Date(now.getTime() - i * 60 * 60 * 1000);
times.push(time.toLocaleTimeString('zh-CN', {hour: '2-digit', minute: '2-digit'}));
}
// 生成高度序列从250m到3850m每100m一个点
for (let h = 250; h <= 3850; h += 100) {
heights.push(h);
}
// 生成风向风速数据
for (let i = 0; i < times.length; i++) {
for (let j = 0; j < heights.length; j++) {
// 风向0-360度添加一些连续性
const baseDirection = Math.sin(i * 0.3 + j * 0.1) * 180 + 180;
const direction = (baseDirection + Math.random() * 30 - 15) % 360;
// 风速0-20 m/s高度越高风速越大
const baseSpeed = (heights[j] / 3850) * 15 + Math.random() * 5;
const speed = Math.min(20, Math.max(0, baseSpeed));
data.push([i, j, Math.round(direction), Math.round(speed * 10) / 10]);
}
}
return { times, heights, data };
}
// 更新图表
function updateChart() {
if (!chartInstance) return;
const { times, heights, data } = generateData();
const option = {
title: {
text: '🌬️ 风向风速分布图',
left: 'center',
textStyle: {
fontSize: 18,
fontWeight: 'bold',
color: '#2c3e50'
}
},
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(255,255,255,0.95)',
borderColor: '#ccc',
borderWidth: 1,
textStyle: {
color: '#333'
},
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);
return `
<div style="font-weight: bold; margin-bottom: 5px;">${time}</div>
<div>高度: <b>${height}m</b></div>
<div>风向: <b>${direction}° ${directionText}</b></div>
<div>风速: <b>${speed} m/s</b></div>
`;
}
},
grid: {
left: '70px',
right: '100px',
bottom: '70px',
top: '70px',
containLabel: false
},
xAxis: {
type: 'category',
data: times,
name: '时间',
nameLocation: 'middle',
nameGap: 35,
axisLabel: {
interval: 2,
rotate: 45,
fontSize: 10
},
axisLine: {
lineStyle: {
color: '#7f8c8d'
}
}
},
yAxis: {
type: 'category',
data: heights.map(h => h + 'm'),
name: '高度 (m)',
nameLocation: 'middle',
nameGap: 50,
axisLine: {
lineStyle: {
color: '#7f8c8d'
}
},
inverse: true
},
visualMap: {
type: 'piecewise',
min: 0,
max: 20,
orient: 'vertical',
right: 15,
top: 'center',
textStyle: {
color: '#2c3e50',
fontSize: 11
},
pieces: [
{min: 0, max: 5, label: '0-5 m/s', color: '#2ecc71'},
{min: 5, max: 10, label: '5-10 m/s', color: '#f39c12'},
{min: 10, max: 15, label: '10-15 m/s', color: '#e67e22'},
{min: 15, max: 20, label: '15-20 m/s', color: '#e74c3c'}
],
name: '风速\n(m/s)',
nameTextStyle: {
fontSize: 12,
fontWeight: 'bold'
}
},
series: [{
name: '风向',
type: 'custom',
renderItem: function(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 color = api.visual('color');
const length = speed * 2 + 8;
const radian = (direction - 90) * Math.PI / 180;
const endPoint = [
point[0] + Math.cos(radian) * length,
point[1] + Math.sin(radian) * length
];
return {
type: 'line',
shape: {
x1: point[0],
y1: point[1],
x2: endPoint[0],
y2: endPoint[1]
},
style: {
stroke: color,
lineWidth: 1.8,
lineCap: 'round'
},
silent: false
};
},
data: data,
encode: {
x: [0],
y: [1]
},
animation: animationEnabled,
animationDuration: 1000,
animationEasing: 'cubicOut'
}]
};
chartInstance.setOption(option, true);
}
// 获取风向文本描述
function getDirectionText(direction) {
const directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
const index = Math.round(direction / 45) % 8;
return directions[index];
}
// 刷新数据
function refreshData() {
if (chartInstance) {
updateChart();
}
}
// 切换动画
function toggleAnimation() {
animationEnabled = !animationEnabled;
if (chartInstance) {
updateChart();
}
}
// 页面加载完成后初始化图表
document.addEventListener('DOMContentLoaded', function() {
// 延迟初始化以确保所有资源加载完成
setTimeout(initChart, 100);
});
</script>
</body>
</html>