mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: hull traverse visualizer
This commit is contained in:
1 parent
4f47d6ce85
commit
ed64ee8228
8 files changed
+160
No files matched your search
@@ -861,6 +861,16 @@
|
|||||||
"tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)",
|
"tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)",
|
||||||
"tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.",
|
"tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.",
|
||||||
|
|
||||||
|
"visualizers": {
|
||||||
|
"rotator": {
|
||||||
|
"hull": "Hull",
|
||||||
|
"turret": "Turret",
|
||||||
|
"hard": "Hard",
|
||||||
|
"medium": "Medium",
|
||||||
|
"soft": "Soft"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"poses": {
|
"poses": {
|
||||||
"hull_down": "Hull down",
|
"hull_down": "Hull down",
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"markdown-to-jsx": "^7.5.0",
|
"markdown-to-jsx": "^7.5.0",
|
||||||
"nanostores": "^0.11.3",
|
"nanostores": "^0.11.3",
|
||||||
|
"quicklime": "^1.2.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-device-detect": "^2.2.3",
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 195 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
+13
@@ -0,0 +1,13 @@
|
|||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: translate(-50%, -50%) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: translate(-50%, -50%) rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hull-traverse-visualizer {
|
||||||
|
animation: spin linear infinite;
|
||||||
|
}
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
import { Card, Checkbox, Flex, Tabs, Text } from '@radix-ui/themes';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||||
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
interface HullTraverseVisualizerProps {
|
||||||
|
stats: TankCharacteristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HullTraverseVisualizerEventData {
|
||||||
|
hull: boolean;
|
||||||
|
turret: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
||||||
|
|
||||||
|
export function HullTraverseVisualizer({ stats }: HullTraverseVisualizerProps) {
|
||||||
|
const hull = useRef<HTMLDivElement>(null);
|
||||||
|
const turret = useRef<HTMLImageElement>(null);
|
||||||
|
const [terrain, setTerrain] = useState<Terrain>('Hard');
|
||||||
|
const [rotateHull, setRotateHull] = useState(true);
|
||||||
|
const [rotateTurret, setRotateTurret] = useState(true);
|
||||||
|
const { strings } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
||||||
|
<div
|
||||||
|
ref={hull}
|
||||||
|
className="hull-traverse-visualizer"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
animationDuration: `${
|
||||||
|
rotateHull ? 1 / (stats[`hullTraverse${terrain}Terrain`] / 360) : 0
|
||||||
|
}s`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: '12rem',
|
||||||
|
height: '12rem',
|
||||||
|
objectFit: 'contain',
|
||||||
|
filter: 'drop-shadow(0px 0px 4px black)',
|
||||||
|
}}
|
||||||
|
src="/assets/images/tankopedia/visualizers/hull-traverse/hull.png"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
ref={turret}
|
||||||
|
className="hull-traverse-visualizer"
|
||||||
|
style={{
|
||||||
|
width: '27rem',
|
||||||
|
height: '27rem',
|
||||||
|
objectFit: 'contain',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
filter: 'drop-shadow(0px 0px 4px black)',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
animationDuration: `${
|
||||||
|
rotateTurret ? 1 / (stats.turretTraverseSpeed / 360) : 0
|
||||||
|
}s`,
|
||||||
|
}}
|
||||||
|
src="/assets/images/tankopedia/visualizers/hull-traverse/turret.png"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
position="absolute"
|
||||||
|
bottom="0"
|
||||||
|
left="50%"
|
||||||
|
style={{
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tabs.Root
|
||||||
|
value={terrain}
|
||||||
|
onValueChange={(terrain) => setTerrain(terrain as Terrain)}
|
||||||
|
>
|
||||||
|
<Tabs.List>
|
||||||
|
<Tabs.Trigger value="Hard">
|
||||||
|
{strings.website.tools.tankopedia.visualizers.rotator.hard}
|
||||||
|
</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="Medium">
|
||||||
|
{strings.website.tools.tankopedia.visualizers.rotator.medium}
|
||||||
|
</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="Soft">
|
||||||
|
{strings.website.tools.tankopedia.visualizers.rotator.soft}
|
||||||
|
</Tabs.Trigger>
|
||||||
|
</Tabs.List>
|
||||||
|
</Tabs.Root>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
position="absolute"
|
||||||
|
top="4"
|
||||||
|
left="50%"
|
||||||
|
gap="5"
|
||||||
|
style={{
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
userSelect: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
gap="2"
|
||||||
|
onClick={() => setRotateHull((state) => !state)}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
<Checkbox checked={rotateHull} />
|
||||||
|
<Text size="2">
|
||||||
|
{strings.website.tools.tankopedia.visualizers.rotator.hull}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
gap="2"
|
||||||
|
onClick={() => setRotateTurret((state) => !state)}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
<Checkbox checked={rotateTurret} />
|
||||||
|
<Text size="2">
|
||||||
|
{strings.website.tools.tankopedia.visualizers.rotator.turret}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
+3
@@ -31,6 +31,7 @@ import { useLocale } from '../../../../../hooks/useLocale';
|
|||||||
import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition';
|
import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition';
|
||||||
import { Duel } from '../../../../../stores/duel';
|
import { Duel } from '../../../../../stores/duel';
|
||||||
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
||||||
|
import { HullTraverseVisualizer } from './components/HullTraverseVisualizer';
|
||||||
import { Info } from './components/Info';
|
import { Info } from './components/Info';
|
||||||
import { InfoWithDelta } from './components/InfoWithDelta';
|
import { InfoWithDelta } from './components/InfoWithDelta';
|
||||||
|
|
||||||
@@ -753,6 +754,8 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
value="hullTraverseSoftTerrain"
|
value="hullTraverseSoftTerrain"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<HullTraverseVisualizer stats={stats} />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex direction="column" gap="2">
|
<Flex direction="column" gap="2">
|
||||||
|
|||||||
Reference in new issue
Block a user