Skip to content

Commit 469a9ef

Browse files
committed
fix: Color correctly represents speed
1 parent 35b4eec commit 469a9ef

File tree

14 files changed

+377
-153
lines changed

14 files changed

+377
-153
lines changed

example/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# example
22

3+
## 0.3.2
4+
5+
### Patch Changes
6+
7+
- Updated dependencies
8+
- cesium-wind-layer@0.4.2
9+
310
## 0.3.1
411

512
### Patch Changes

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "example",
33
"private": true,
4-
"version": "0.3.1",
4+
"version": "0.3.2",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

example/src/components/ControlPanel.tsx

Lines changed: 7 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { WindLayer, WindLayerOptions } from 'cesium-wind-layer';
44
import { QuestionCircleOutlined } from '@ant-design/icons';
55
import ColorTableInput from './ColorTableInput';
66
import styled from 'styled-components';
7-
import { GithubOutlined } from '@ant-design/icons';
87
import { ZoomInOutlined } from '@ant-design/icons';
98
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
109

@@ -151,64 +150,6 @@ const ControlPanelContainer = styled.div`
151150
}
152151
`;
153152

154-
const GithubBadge = styled.a`
155-
display: flex;
156-
align-items: center;
157-
gap: 8px;
158-
padding: 8px 12px;
159-
background: #ffffff;
160-
color: #24292e;
161-
border-radius: 6px;
162-
transition: all 0.3s;
163-
text-decoration: none;
164-
font-size: 14px;
165-
border: 1px solid #e1e4e8;
166-
167-
&:hover {
168-
background: #f6f8fa;
169-
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
170-
border-color: #d0d7de;
171-
}
172-
173-
.github-icon {
174-
font-size: 16px;
175-
color: #24292e;
176-
}
177-
178-
.repo-name {
179-
color: #0969da;
180-
font-weight: 500;
181-
}
182-
183-
.stats {
184-
display: flex;
185-
align-items: center;
186-
gap: 4px;
187-
margin-left: auto;
188-
189-
img {
190-
height: 16px;
191-
}
192-
}
193-
`;
194-
195-
const GithubLink = () => (
196-
<GithubBadge
197-
href="https://github.com/hongfaqiu/cesium-wind-layer"
198-
target="_blank"
199-
rel="noopener noreferrer"
200-
>
201-
<GithubOutlined className="github-icon" />
202-
<span className="repo-name">cesium-wind-layer</span>
203-
<div className="stats">
204-
<img
205-
src="https://img.shields.io/github/stars/hongfaqiu/cesium-wind-layer?style=flat&logo=github"
206-
alt="GitHub stars"
207-
/>
208-
</div>
209-
</GithubBadge>
210-
);
211-
212153
const TitleActions = styled.div`
213154
display: flex;
214155
align-items: center;
@@ -227,6 +168,7 @@ const TitleButton = styled.button`
227168
cursor: pointer;
228169
color: rgba(0, 0, 0, 0.45);
229170
transition: all 0.3s;
171+
border-radius: 4px;
230172
231173
&:hover {
232174
color: rgba(0, 0, 0, 0.85);
@@ -236,6 +178,11 @@ const TitleButton = styled.button`
236178
&:active {
237179
background: rgba(0, 0, 0, 0.08);
238180
}
181+
182+
// Prevent click event from bubbling up to parent
183+
&:focus {
184+
outline: none;
185+
}
239186
`;
240187

241188
interface ControlPanelProps {
@@ -378,7 +325,7 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
378325
'Factor to adjust the speed of particles. Controls the movement speed of particles.'
379326
)}
380327
>
381-
<Slider min={0.1} max={20} step={0.1} />
328+
<Slider min={0.1} max={2} step={0.1} />
382329
</CompactFormItem>
383330

384331
<CompactFormItem
@@ -445,10 +392,6 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
445392
unCheckedChildren="Global"
446393
/>
447394
</CompactFormItem>
448-
449-
<div style={{ marginTop: 8 }}>
450-
<GithubLink />
451-
</div>
452395
</Space>
453396
</Form>
454397
</CardContent>

example/src/components/SpeedQuery.tsx

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Typography, Space, Divider } from 'antd';
3+
import styled from 'styled-components';
4+
import { WindLayer } from 'cesium-wind-layer';
5+
import { Viewer, ScreenSpaceEventHandler, ScreenSpaceEventType, Cartographic, Math as CesiumMath } from 'cesium';
6+
import { GithubOutlined } from '@ant-design/icons';
7+
8+
const { Text } = Typography;
9+
10+
const Container = styled.div`
11+
background-color: rgba(255, 255, 255, 0.98);
12+
display: flex;
13+
align-items: center;
14+
justify-content: space-between;
15+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
16+
backdrop-filter: blur(8px);
17+
border-radius: 4px;
18+
margin: 4px;
19+
padding: 4px 8px;
20+
z-index: 1000;
21+
transition: all 0.3s ease;
22+
min-height: 32px;
23+
24+
&:hover {
25+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
26+
}
27+
28+
@media (max-width: 768px) {
29+
margin: 4px;
30+
padding: 4px 6px;
31+
flex-direction: column;
32+
align-items: flex-start;
33+
gap: 4px;
34+
}
35+
`;
36+
37+
const QueryInfo = styled(Space)`
38+
flex: 1;
39+
font-size: 13px;
40+
41+
@media (max-width: 768px) {
42+
width: 100%;
43+
}
44+
`;
45+
46+
const DataItem = styled(Text)`
47+
display: inline-flex;
48+
align-items: center;
49+
gap: 2px;
50+
padding: 1px 4px;
51+
border-radius: 3px;
52+
background: rgba(0, 0, 0, 0.02);
53+
transition: all 0.3s ease;
54+
font-size: 13px;
55+
56+
&:hover {
57+
background: rgba(0, 0, 0, 0.04);
58+
}
59+
`;
60+
61+
const GithubLink = styled.a`
62+
display: flex;
63+
align-items: center;
64+
gap: 4px;
65+
color: #24292e;
66+
text-decoration: none;
67+
padding: 2px 6px;
68+
border-radius: 3px;
69+
transition: all 0.3s ease;
70+
background: rgba(0, 0, 0, 0.02);
71+
white-space: nowrap;
72+
font-size: 13px;
73+
74+
&:hover {
75+
background: rgba(0, 0, 0, 0.06);
76+
transform: translateY(-1px);
77+
}
78+
79+
.stats {
80+
display: flex;
81+
align-items: center;
82+
gap: 4px;
83+
84+
img {
85+
height: 16px;
86+
transition: transform 0.3s ease;
87+
}
88+
}
89+
90+
&:hover .stats img {
91+
transform: scale(1.05);
92+
}
93+
94+
@media (max-width: 768px) {
95+
width: 100%;
96+
justify-content: space-between;
97+
border-top: 1px solid rgba(0, 0, 0, 0.06);
98+
padding-top: 4px;
99+
background: transparent;
100+
}
101+
`;
102+
103+
const DirectionArrow = styled.span<{ $angle: number }>`
104+
display: inline-block;
105+
transform: rotate(${props => props.$angle}deg);
106+
transition: transform 0.3s ease;
107+
font-family: "Segoe UI Symbol", "Noto Color Emoji", sans-serif;
108+
`;
109+
110+
interface WindData {
111+
speed: number;
112+
u: number;
113+
v: number;
114+
direction?: number;
115+
}
116+
117+
interface SpeedQueryProps {
118+
windLayer: WindLayer | null;
119+
viewer: Viewer | null;
120+
}
121+
122+
export const SpeedQuery: React.FC<SpeedQueryProps> = ({ windLayer, viewer }) => {
123+
const [queryResult, setQueryResult] = useState<WindData | null>(null);
124+
const [location, setLocation] = useState<{ lon: number; lat: number } | null>(null);
125+
126+
const calculateWindDirection = (u: number, v: number): number => {
127+
// 使用 atan2 计算角度,注意参数顺序:atan2(y, x)
128+
// v 代表南北方向(y轴),u 代表东西方向(x轴)
129+
let angle = Math.atan2(v, u) * 180 / Math.PI;
130+
131+
// 转换为地理坐标系的角度:
132+
// 1. atan2 得到的角度是数学坐标系(东为0°,逆时针为正)
133+
// 2. 转换为地理方向:逆时针旋转90度(或顺时针旋转270度)
134+
// 3. 加360°并取模确保在0-360范围内
135+
angle = (450 - angle) % 360;
136+
137+
return angle;
138+
};
139+
140+
const getCardinalDirection = (angle: number): string => {
141+
const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
142+
const index = Math.round(angle / 45) % 8;
143+
return directions[index];
144+
};
145+
146+
useEffect(() => {
147+
if (!viewer || !windLayer) return;
148+
149+
const handler = new ScreenSpaceEventHandler(viewer.scene.canvas);
150+
const handleClick = (movement: any) => {
151+
const cartesian = viewer.camera.pickEllipsoid(movement.position);
152+
if (cartesian) {
153+
const cartographic = Cartographic.fromCartesian(cartesian);
154+
const lon = CesiumMath.toDegrees(cartographic.longitude);
155+
const lat = CesiumMath.toDegrees(cartographic.latitude);
156+
157+
try {
158+
const result = windLayer.getDataAtLonLat(lon, lat);
159+
setLocation({ lon, lat });
160+
161+
if (result && typeof result.u === 'number' && typeof result.v === 'number') {
162+
const direction = calculateWindDirection(result.u, result.v);
163+
setQueryResult({ ...result, direction });
164+
} else {
165+
setQueryResult(null);
166+
}
167+
} catch (error) {
168+
console.error('Failed to get wind data:', error);
169+
setQueryResult(null);
170+
}
171+
}
172+
};
173+
174+
// 支持移动端触摸
175+
handler.setInputAction(handleClick, ScreenSpaceEventType.LEFT_CLICK);
176+
handler.setInputAction(handleClick, ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
177+
178+
return () => {
179+
handler.destroy();
180+
};
181+
}, [viewer, windLayer]);
182+
183+
return (
184+
<Container>
185+
<QueryInfo>
186+
{!location && (
187+
<Text style={{ fontSize: '13px' }}>
188+
<span style={{ opacity: 0.7 }}>👆</span> Click to query wind info
189+
</Text>
190+
)}
191+
192+
{location && (
193+
<Space split={<Divider type="vertical" style={{ margin: '0 4px' }} />}>
194+
<DataItem>
195+
📍 {location.lon.toFixed(1)}°, {location.lat.toFixed(1)}°
196+
</DataItem>
197+
198+
{!queryResult && (
199+
<Text type="secondary" style={{ fontSize: '13px' }}>No data</Text>
200+
)}
201+
202+
{queryResult && (
203+
<>
204+
<DataItem>
205+
💨 {queryResult.speed.toFixed(1)} m/s
206+
</DataItem>
207+
<DataItem>
208+
<DirectionArrow $angle={(queryResult.direction || 0) - 90}></DirectionArrow>
209+
{' '}{queryResult.direction?.toFixed(0)}° ({getCardinalDirection(queryResult.direction || 0)})
210+
</DataItem>
211+
<DataItem>
212+
UV: {queryResult.u.toFixed(1)}, {queryResult.v.toFixed(1)}
213+
</DataItem>
214+
</>
215+
)}
216+
</Space>
217+
)}
218+
</QueryInfo>
219+
220+
<GithubLink
221+
href="https://github.com/hongfaqiu/cesium-wind-layer"
222+
target="_blank"
223+
rel="noopener noreferrer"
224+
>
225+
<GithubOutlined style={{ fontSize: '14px' }} />
226+
<span>cesium-wind-layer</span>
227+
<div className="stats">
228+
<img
229+
src="https://img.shields.io/github/stars/hongfaqiu/cesium-wind-layer?style=flat&logo=github"
230+
alt="GitHub stars"
231+
/>
232+
</div>
233+
</GithubLink>
234+
</Container>
235+
);
236+
};

0 commit comments

Comments
 (0)