Skip to content

Commit

Permalink
fix: Color correctly represents speed
Browse files Browse the repository at this point in the history
  • Loading branch information
hongfaqiu committed Oct 27, 2024
1 parent 35b4eec commit 469a9ef
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 153 deletions.
7 changes: 7 additions & 0 deletions example/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# example

## 0.3.2

### Patch Changes

- Updated dependencies
- [email protected]

## 0.3.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "example",
"private": true,
"version": "0.3.1",
"version": "0.3.2",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
71 changes: 7 additions & 64 deletions example/src/components/ControlPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { WindLayer, WindLayerOptions } from 'cesium-wind-layer';
import { QuestionCircleOutlined } from '@ant-design/icons';
import ColorTableInput from './ColorTableInput';
import styled from 'styled-components';
import { GithubOutlined } from '@ant-design/icons';
import { ZoomInOutlined } from '@ant-design/icons';
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';

Expand Down Expand Up @@ -151,64 +150,6 @@ const ControlPanelContainer = styled.div`
}
`;

const GithubBadge = styled.a`
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: #ffffff;
color: #24292e;
border-radius: 6px;
transition: all 0.3s;
text-decoration: none;
font-size: 14px;
border: 1px solid #e1e4e8;
&:hover {
background: #f6f8fa;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
border-color: #d0d7de;
}
.github-icon {
font-size: 16px;
color: #24292e;
}
.repo-name {
color: #0969da;
font-weight: 500;
}
.stats {
display: flex;
align-items: center;
gap: 4px;
margin-left: auto;
img {
height: 16px;
}
}
`;

const GithubLink = () => (
<GithubBadge
href="https://github.com/hongfaqiu/cesium-wind-layer"
target="_blank"
rel="noopener noreferrer"
>
<GithubOutlined className="github-icon" />
<span className="repo-name">cesium-wind-layer</span>
<div className="stats">
<img
src="https://img.shields.io/github/stars/hongfaqiu/cesium-wind-layer?style=flat&logo=github"
alt="GitHub stars"
/>
</div>
</GithubBadge>
);

const TitleActions = styled.div`
display: flex;
align-items: center;
Expand All @@ -227,6 +168,7 @@ const TitleButton = styled.button`
cursor: pointer;
color: rgba(0, 0, 0, 0.45);
transition: all 0.3s;
border-radius: 4px;
&:hover {
color: rgba(0, 0, 0, 0.85);
Expand All @@ -236,6 +178,11 @@ const TitleButton = styled.button`
&:active {
background: rgba(0, 0, 0, 0.08);
}
// Prevent click event from bubbling up to parent
&:focus {
outline: none;
}
`;

interface ControlPanelProps {
Expand Down Expand Up @@ -378,7 +325,7 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
'Factor to adjust the speed of particles. Controls the movement speed of particles.'
)}
>
<Slider min={0.1} max={20} step={0.1} />
<Slider min={0.1} max={2} step={0.1} />
</CompactFormItem>

<CompactFormItem
Expand Down Expand Up @@ -445,10 +392,6 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
unCheckedChildren="Global"
/>
</CompactFormItem>

<div style={{ marginTop: 8 }}>
<GithubLink />
</div>
</Space>
</Form>
</CardContent>
Expand Down
236 changes: 236 additions & 0 deletions example/src/components/SpeedQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import React, { useState, useEffect } from 'react';
import { Typography, Space, Divider } from 'antd';
import styled from 'styled-components';
import { WindLayer } from 'cesium-wind-layer';
import { Viewer, ScreenSpaceEventHandler, ScreenSpaceEventType, Cartographic, Math as CesiumMath } from 'cesium';
import { GithubOutlined } from '@ant-design/icons';

const { Text } = Typography;

const Container = styled.div`
background-color: rgba(255, 255, 255, 0.98);
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
backdrop-filter: blur(8px);
border-radius: 4px;
margin: 4px;
padding: 4px 8px;
z-index: 1000;
transition: all 0.3s ease;
min-height: 32px;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
@media (max-width: 768px) {
margin: 4px;
padding: 4px 6px;
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
`;

const QueryInfo = styled(Space)`
flex: 1;
font-size: 13px;
@media (max-width: 768px) {
width: 100%;
}
`;

const DataItem = styled(Text)`
display: inline-flex;
align-items: center;
gap: 2px;
padding: 1px 4px;
border-radius: 3px;
background: rgba(0, 0, 0, 0.02);
transition: all 0.3s ease;
font-size: 13px;
&:hover {
background: rgba(0, 0, 0, 0.04);
}
`;

const GithubLink = styled.a`
display: flex;
align-items: center;
gap: 4px;
color: #24292e;
text-decoration: none;
padding: 2px 6px;
border-radius: 3px;
transition: all 0.3s ease;
background: rgba(0, 0, 0, 0.02);
white-space: nowrap;
font-size: 13px;
&:hover {
background: rgba(0, 0, 0, 0.06);
transform: translateY(-1px);
}
.stats {
display: flex;
align-items: center;
gap: 4px;
img {
height: 16px;
transition: transform 0.3s ease;
}
}
&:hover .stats img {
transform: scale(1.05);
}
@media (max-width: 768px) {
width: 100%;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.06);
padding-top: 4px;
background: transparent;
}
`;

const DirectionArrow = styled.span<{ $angle: number }>`
display: inline-block;
transform: rotate(${props => props.$angle}deg);
transition: transform 0.3s ease;
font-family: "Segoe UI Symbol", "Noto Color Emoji", sans-serif;
`;

interface WindData {
speed: number;
u: number;
v: number;
direction?: number;
}

interface SpeedQueryProps {
windLayer: WindLayer | null;
viewer: Viewer | null;
}

export const SpeedQuery: React.FC<SpeedQueryProps> = ({ windLayer, viewer }) => {
const [queryResult, setQueryResult] = useState<WindData | null>(null);
const [location, setLocation] = useState<{ lon: number; lat: number } | null>(null);

const calculateWindDirection = (u: number, v: number): number => {
// 使用 atan2 计算角度,注意参数顺序:atan2(y, x)
// v 代表南北方向(y轴),u 代表东西方向(x轴)
let angle = Math.atan2(v, u) * 180 / Math.PI;

// 转换为地理坐标系的角度:
// 1. atan2 得到的角度是数学坐标系(东为0°,逆时针为正)
// 2. 转换为地理方向:逆时针旋转90度(或顺时针旋转270度)
// 3. 加360°并取模确保在0-360范围内
angle = (450 - angle) % 360;

return angle;
};

const getCardinalDirection = (angle: number): string => {
const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
const index = Math.round(angle / 45) % 8;
return directions[index];
};

useEffect(() => {
if (!viewer || !windLayer) return;

const handler = new ScreenSpaceEventHandler(viewer.scene.canvas);
const handleClick = (movement: any) => {
const cartesian = viewer.camera.pickEllipsoid(movement.position);
if (cartesian) {
const cartographic = Cartographic.fromCartesian(cartesian);
const lon = CesiumMath.toDegrees(cartographic.longitude);
const lat = CesiumMath.toDegrees(cartographic.latitude);

try {
const result = windLayer.getDataAtLonLat(lon, lat);
setLocation({ lon, lat });

if (result && typeof result.u === 'number' && typeof result.v === 'number') {
const direction = calculateWindDirection(result.u, result.v);
setQueryResult({ ...result, direction });
} else {
setQueryResult(null);
}
} catch (error) {
console.error('Failed to get wind data:', error);
setQueryResult(null);
}
}
};

// 支持移动端触摸
handler.setInputAction(handleClick, ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(handleClick, ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

return () => {
handler.destroy();
};
}, [viewer, windLayer]);

return (
<Container>
<QueryInfo>
{!location && (
<Text style={{ fontSize: '13px' }}>
<span style={{ opacity: 0.7 }}>👆</span> Click to query wind info
</Text>
)}

{location && (
<Space split={<Divider type="vertical" style={{ margin: '0 4px' }} />}>
<DataItem>
📍 {location.lon.toFixed(1)}°, {location.lat.toFixed(1)}°
</DataItem>

{!queryResult && (
<Text type="secondary" style={{ fontSize: '13px' }}>No data</Text>
)}

{queryResult && (
<>
<DataItem>
💨 {queryResult.speed.toFixed(1)} m/s
</DataItem>
<DataItem>
<DirectionArrow $angle={(queryResult.direction || 0) - 90}></DirectionArrow>
{' '}{queryResult.direction?.toFixed(0)}° ({getCardinalDirection(queryResult.direction || 0)})
</DataItem>
<DataItem>
UV: {queryResult.u.toFixed(1)}, {queryResult.v.toFixed(1)}
</DataItem>
</>
)}
</Space>
)}
</QueryInfo>

<GithubLink
href="https://github.com/hongfaqiu/cesium-wind-layer"
target="_blank"
rel="noopener noreferrer"
>
<GithubOutlined style={{ fontSize: '14px' }} />
<span>cesium-wind-layer</span>
<div className="stats">
<img
src="https://img.shields.io/github/stars/hongfaqiu/cesium-wind-layer?style=flat&logo=github"
alt="GitHub stars"
/>
</div>
</GithubLink>
</Container>
);
};
Loading

0 comments on commit 469a9ef

Please sign in to comment.