homeweather-fe/src/lib/WindDirection.svelte

130 lines
2.9 KiB
Svelte

<script lang="ts">
const originPoint = -90;
const WIND_DIRS = {
N: originPoint,
NNE: originPoint + 45 / 2,
NE: originPoint + 45,
ENE: originPoint + 45 + 45 / 2,
E: originPoint + 90,
ESE: originPoint + 90 + 45 / 2,
SE: originPoint + 90 + 45,
SSE: originPoint + 90 + 45 + 45 / 2,
S: originPoint + 180,
SSW: originPoint + 180 + 45 / 2,
SW: originPoint + 180 + 45,
WSW: originPoint + 180 + 45 + 45 / 2,
W: originPoint - 90,
WNW: originPoint - (90 - 45 / 2),
NW: originPoint - (90 - 45),
NNW: originPoint - (90 - 45 - 45 / 2),
};
function calcPos(dir: string) {
const pad = 16;
const rem = 192 - pad;
const offset = pad * 0.4;
const angle = WIND_DIRS[dir];
const x = Math.cos(angle * (Math.PI / 180)) * (rem / 2) + rem / 2 + offset;
const y = Math.sin(angle * (Math.PI / 180)) * (rem / 2) + rem / 2 + offset;
return `translate(${x}px, ${y}px)`;
}
export let direction: string = 'N';
</script>
<div class="wind-radial-wrapper">
<div class="wind-radial-cardinals">
{#each Object.keys(WIND_DIRS) as dir}
<span
class="wind-cardinal wind-cardinal--{dir.toLowerCase()}"
style={`--pos: ${calcPos(dir)}`}>{dir}</span
>
{/each}
</div>
<div class="wind-radial">
<div
class="wind-direction"
style={`--angle: ${WIND_DIRS[direction || 'N']}deg`}
/>
</div>
</div>
<style lang="scss">
.wind {
&-radial {
position: relative;
width: 8rem;
height: 8rem;
&-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 12rem;
height: 12rem;
}
&-cardinals {
position: absolute;
width: 12rem;
height: 12rem;
}
}
&-direction {
position: absolute;
width: 1px;
height: 1px;
top: 50%;
left: 50%;
transform: rotate(var(--angle));
&::before {
content: '';
display: block;
position: absolute;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid #fff;
left: -5px;
top: -10px;
@media (prefers-color-scheme: light) {
border-right: 10px solid #000;
}
}
&::after {
content: '';
display: block;
position: absolute;
background-color: #fff;
width: 4rem;
height: 4px;
top: -2px;
@media (prefers-color-scheme: light) {
background-color: #000;
}
}
}
&-cardinal {
position: absolute;
width: 8px;
height: 8px;
display: flex;
align-items: center;
justify-content: center;
transform: var(--pos);
transform-origin: center center;
user-select: none;
&:nth-child(2n) {
color: rgb(184, 184, 184);
}
}
}
</style>