mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: animations
This commit is contained in:
1 parent
35073c184e
commit
22d794ac65
5 files changed
+290
-126
No files matched your search
@@ -871,7 +871,8 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"ricochet": {
|
"ricochet": {
|
||||||
"max": "Max: %s1°"
|
"safe": "Safe %s1°",
|
||||||
|
"unsafe": "Unsafe %s1°"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
import partytown from "@astrojs/partytown";
|
import partytown from '@astrojs/partytown';
|
||||||
import react from "@astrojs/react";
|
import react from '@astrojs/react';
|
||||||
import sitemap from "@astrojs/sitemap";
|
import sitemap from '@astrojs/sitemap';
|
||||||
import { SUPPORTED_LOCALES } from "@blitzkit/i18n";
|
import { SUPPORTED_LOCALES } from '@blitzkit/i18n';
|
||||||
import { defineConfig } from "astro/config";
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: "en",
|
defaultLocale: 'en',
|
||||||
locales: [...SUPPORTED_LOCALES],
|
locales: [...SUPPORTED_LOCALES],
|
||||||
routing: {
|
routing: {
|
||||||
prefixDefaultLocale: false,
|
prefixDefaultLocale: false,
|
||||||
@@ -16,17 +16,17 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
|
|
||||||
devToolbar: { enabled: false },
|
devToolbar: { enabled: false },
|
||||||
output: "static",
|
output: 'static',
|
||||||
site: "https://blitzkit.app",
|
site: 'https://blitzkit.app',
|
||||||
outDir: "../../dist/website",
|
outDir: '../../dist/website',
|
||||||
prefetch: true,
|
prefetch: true,
|
||||||
|
|
||||||
integrations: [react(), sitemap(), partytown()],
|
integrations: [react(), sitemap(), partytown()],
|
||||||
vite: {
|
vite: {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
".prisma/client/index-browser":
|
'.prisma/client/index-browser':
|
||||||
"../../node_modules/.prisma/client/index-browser.js",
|
'../../node_modules/.prisma/client/index-browser.js',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ssr: {
|
ssr: {
|
||||||
|
|||||||
-114
@@ -1,114 +0,0 @@
|
|||||||
import { asset } from '@blitzkit/core';
|
|
||||||
import { literals } from '@blitzkit/i18n';
|
|
||||||
import { Box, Card, Text } from '@radix-ui/themes';
|
|
||||||
import { Var } from '../../../../../../core/radix/var';
|
|
||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
|
||||||
import type { VisualizerProps } from './HullTraverseVisualizer';
|
|
||||||
|
|
||||||
export function RicochetVisualizer({ stats }: VisualizerProps) {
|
|
||||||
const ricochet = stats.shellRicochet ?? 90;
|
|
||||||
const normalization = stats.shellNormalization;
|
|
||||||
const shell = Duel.use((state) => state.protagonist.shell);
|
|
||||||
const { strings } = useLocale();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
variant="classic"
|
|
||||||
style={{
|
|
||||||
aspectRatio: '2 / 1',
|
|
||||||
}}
|
|
||||||
mb="6"
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="calc(100% * 2 / 3)"
|
|
||||||
position="absolute"
|
|
||||||
top="0"
|
|
||||||
left="0"
|
|
||||||
style={{
|
|
||||||
backgroundColor: Var('gray-11'),
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
background: `
|
|
||||||
conic-gradient(
|
|
||||||
from -90deg at 25% 100%,
|
|
||||||
transparent 0deg ${90 - ricochet - normalization}deg,
|
|
||||||
${Var('jade-a1')} ${90 - ricochet - normalization}deg ${90 - ricochet - normalization}deg,
|
|
||||||
${Var('jade-11')} ${90 + ricochet}deg,
|
|
||||||
${Var('amber-9')} ${90 + ricochet}deg ${90 + ricochet + normalization}deg,
|
|
||||||
${Var('tomato-10')} ${90 + ricochet + normalization}deg,
|
|
||||||
${Var('tomato-11')} 180deg,
|
|
||||||
transparent 180deg
|
|
||||||
)
|
|
||||||
`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
bottom="0"
|
|
||||||
left="25%"
|
|
||||||
width="3rem"
|
|
||||||
height="3rem"
|
|
||||||
style={{
|
|
||||||
transform: `translate(-50%, 50%) rotate(${ricochet + normalization}deg)`,
|
|
||||||
background: `radial-gradient(${Var('gray-a5')}, ${Var('gray-a11')})`,
|
|
||||||
borderRadius: '50%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={asset(`icons/shells/${shell.icon}.webp`)}
|
|
||||||
style={{
|
|
||||||
width: '2rem',
|
|
||||||
height: '2rem',
|
|
||||||
objectFit: 'contain',
|
|
||||||
transform: 'translate(-50%, -50%) rotate(135deg)',
|
|
||||||
position: 'absolute',
|
|
||||||
top: '-10rem',
|
|
||||||
left: '50%',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="calc(100% / 3)"
|
|
||||||
position="absolute"
|
|
||||||
bottom="0"
|
|
||||||
left="0"
|
|
||||||
style={{
|
|
||||||
background: `linear-gradient(${Var('gray-a4')}, ${Var('gray-a1')})`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
opacity: 2 ** -4,
|
|
||||||
backgroundImage: `url(/assets/images/tankopedia/visualizers/ricochet/armor-hash.png)`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: '50%',
|
|
||||||
left: '50%',
|
|
||||||
transform: 'translate(-50%, -50%)',
|
|
||||||
}}
|
|
||||||
color="gray"
|
|
||||||
>
|
|
||||||
{literals(strings.website.tools.tankopedia.visualizers.ricochet.max, [
|
|
||||||
(ricochet + normalization).toFixed(0),
|
|
||||||
])}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
@keyframes penetrating-shell-slide {
|
||||||
|
0% {
|
||||||
|
margin-top: -9rem;
|
||||||
|
}
|
||||||
|
28%,
|
||||||
|
100% {
|
||||||
|
margin-top: 8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ricocheting-shell-slide {
|
||||||
|
0% {
|
||||||
|
margin-top: -18rem;
|
||||||
|
}
|
||||||
|
38% {
|
||||||
|
margin-top: -18rem;
|
||||||
|
}
|
||||||
|
63%,
|
||||||
|
69% {
|
||||||
|
margin-top: 0rem;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
margin-top: 8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ricocheting-shell-slide-container {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-50%) rotate(80deg);
|
||||||
|
}
|
||||||
|
63% {
|
||||||
|
transform: translateX(-50%) rotate(80deg);
|
||||||
|
}
|
||||||
|
69% {
|
||||||
|
transform: translateX(-50%) rotate(100deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(-50%) rotate(100deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ricochet-visualizer-penetrating-shell {
|
||||||
|
position: absolute;
|
||||||
|
animation: penetrating-shell-slide 3s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ricochet-visualizer-ricocheting-shell {
|
||||||
|
position: absolute;
|
||||||
|
animation: ricocheting-shell-slide 3s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ricochet-visualizer-ricocheting-shell-container {
|
||||||
|
animation: ricocheting-shell-slide-container 3s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes surface-impact {
|
||||||
|
0%,
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
15%,
|
||||||
|
30% {
|
||||||
|
opacity: 1;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
45%,
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ricochet-visualizer-surface-impact {
|
||||||
|
animation: surface-impact 3s infinite;
|
||||||
|
}
|
||||||
+198
@@ -0,0 +1,198 @@
|
|||||||
|
import { asset } from '@blitzkit/core';
|
||||||
|
import { literals } from '@blitzkit/i18n';
|
||||||
|
import { Box, Card, Text } from '@radix-ui/themes';
|
||||||
|
import { Var } from '../../../../../../../core/radix/var';
|
||||||
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
|
import { Duel } from '../../../../../../../stores/duel';
|
||||||
|
import type { VisualizerProps } from '../HullTraverseVisualizer';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
export function RicochetVisualizer({ stats }: VisualizerProps) {
|
||||||
|
const ricochet = stats.shellRicochet ?? 90;
|
||||||
|
const shell = Duel.use((state) => state.protagonist.shell);
|
||||||
|
const { strings } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
variant="classic"
|
||||||
|
style={{
|
||||||
|
aspectRatio: '2 / 1',
|
||||||
|
}}
|
||||||
|
mb="6"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
width="100%"
|
||||||
|
height="calc(100% / 3)"
|
||||||
|
position="absolute"
|
||||||
|
bottom="0"
|
||||||
|
left="0"
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(${Var('gray-a4')}, ${Var('gray-a1')})`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
style={{
|
||||||
|
opacity: 2 ** -3,
|
||||||
|
backgroundImage: `url(/assets/images/tankopedia/visualizers/ricochet/armor-hash.png)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
width="100%"
|
||||||
|
height="calc(100% * 2 / 3)"
|
||||||
|
position="absolute"
|
||||||
|
top="0"
|
||||||
|
left="0"
|
||||||
|
style={{
|
||||||
|
backgroundColor: Var('gray-3'),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
style={{
|
||||||
|
background: `
|
||||||
|
conic-gradient(
|
||||||
|
from -90deg at 25% 100%,
|
||||||
|
transparent ${90 - ricochet}deg,
|
||||||
|
${Var('jade-a3')} ${90 - ricochet}deg,
|
||||||
|
${Var('jade-9')} ${90 + ricochet}deg,
|
||||||
|
${Var('tomato-8')} ${90 + ricochet}deg,
|
||||||
|
${Var('tomato-a3')} 180deg,
|
||||||
|
transparent 180deg
|
||||||
|
)
|
||||||
|
`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <Box
|
||||||
|
width="1px"
|
||||||
|
height="100%"
|
||||||
|
position="absolute"
|
||||||
|
left="25%"
|
||||||
|
top="0"
|
||||||
|
style={{
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
backgroundColor: Var('gray-11'),
|
||||||
|
}}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
<Box
|
||||||
|
width="3px"
|
||||||
|
height="20rem"
|
||||||
|
position="absolute"
|
||||||
|
left="25%"
|
||||||
|
bottom="0"
|
||||||
|
style={{
|
||||||
|
transformOrigin: 'bottom center',
|
||||||
|
transform: `translateX(-50%) rotate(${ricochet}deg)`,
|
||||||
|
background: `repeating-linear-gradient(${Var('gray-a4')}, ${Var('gray-12')} 15px, transparent 15px, transparent 30px)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
width="3px"
|
||||||
|
height="20rem"
|
||||||
|
position="absolute"
|
||||||
|
left="25%"
|
||||||
|
bottom="0"
|
||||||
|
style={{
|
||||||
|
transformOrigin: 'bottom center',
|
||||||
|
transform: `translateX(-50%) rotate(-${ricochet}deg)`,
|
||||||
|
background: `repeating-linear-gradient(${Var('gray-10')}, ${Var('gray-a3')} 15px, transparent 15px, transparent 30px)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
className="ricochet-visualizer-surface-impact"
|
||||||
|
position="absolute"
|
||||||
|
bottom="0"
|
||||||
|
left="25%"
|
||||||
|
style={{
|
||||||
|
transform: `translate(-50%, 50%) rotate(${ricochet}deg)`,
|
||||||
|
background: `radial-gradient(${Var('gray-a2')}, ${Var('gray-a9')})`,
|
||||||
|
borderRadius: '50%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
width="2rem"
|
||||||
|
position="absolute"
|
||||||
|
height="2rem"
|
||||||
|
left="25%"
|
||||||
|
bottom="0"
|
||||||
|
style={{
|
||||||
|
transformOrigin: 'bottom center',
|
||||||
|
transform: `translateX(-50%) rotate(${ricochet / 2}deg)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="ricochet-visualizer-penetrating-shell"
|
||||||
|
src={asset(`icons/shells/${shell.icon}.webp`)}
|
||||||
|
style={{
|
||||||
|
objectFit: 'contain',
|
||||||
|
transform: 'rotate(135deg)',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
className="ricochet-visualizer-ricocheting-shell-container"
|
||||||
|
width="2rem"
|
||||||
|
position="absolute"
|
||||||
|
height="2rem"
|
||||||
|
left="25%"
|
||||||
|
bottom="0"
|
||||||
|
style={{
|
||||||
|
transformOrigin: 'bottom center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="ricochet-visualizer-ricocheting-shell"
|
||||||
|
src={asset(`icons/shells/${shell.icon}.webp`)}
|
||||||
|
style={{
|
||||||
|
objectFit: 'contain',
|
||||||
|
transform: 'translateY(50%) rotate(135deg)',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
color="gray"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: '30%',
|
||||||
|
bottom: '40%',
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{literals(
|
||||||
|
strings.website.tools.tankopedia.visualizers.ricochet.safe,
|
||||||
|
[(2 * ricochet).toFixed(0)],
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
color="gray"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
right: '5%',
|
||||||
|
bottom: '12%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{literals(
|
||||||
|
strings.website.tools.tankopedia.visualizers.ricochet.unsafe,
|
||||||
|
[(90 - ricochet).toFixed(0)],
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user