mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-18 15:36:02 +01:00
refactor(web/menu): radial menu visibility handling
This commit is contained in:
20
web/src/features/dev/debug/radial.ts
Normal file
20
web/src/features/dev/debug/radial.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { debugData } from '../../../utils/debugData';
|
||||||
|
import type { MenuItem } from '../../menu/radial';
|
||||||
|
|
||||||
|
export const debugRadial = () => {
|
||||||
|
debugData<{ items: MenuItem[]; sub?: boolean }>([
|
||||||
|
{
|
||||||
|
action: 'openRadialMenu',
|
||||||
|
data: {
|
||||||
|
items: [
|
||||||
|
// TODO: Fix wheel being broken when there's only one item
|
||||||
|
{ icon: 'palette', label: 'Paint' },
|
||||||
|
{ icon: 'warehouse', label: 'Garage' },
|
||||||
|
{ icon: 'palette', label: 'Quite long text' },
|
||||||
|
{ icon: 'palette', label: 'Paint' },
|
||||||
|
{ icon: 'warehouse', label: 'Garage' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
@@ -9,6 +9,7 @@ import { debugCircleProgressbar, debugProgressbar } from './debug/progress';
|
|||||||
import { debugTextUI } from './debug/textui';
|
import { debugTextUI } from './debug/textui';
|
||||||
import { debugSkillCheck } from './debug/skillcheck';
|
import { debugSkillCheck } from './debug/skillcheck';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { debugRadial } from './debug/radial';
|
||||||
|
|
||||||
const Dev: React.FC = () => {
|
const Dev: React.FC = () => {
|
||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
@@ -46,6 +47,9 @@ const Dev: React.FC = () => {
|
|||||||
<Button fullWidth onClick={() => debugMenu()}>
|
<Button fullWidth onClick={() => debugMenu()}>
|
||||||
Open list menu
|
Open list menu
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button fullWidth onClick={() => debugRadial()}>
|
||||||
|
Open radial menu
|
||||||
|
</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Button fullWidth onClick={() => debugCustomNotification()}>
|
<Button fullWidth onClick={() => debugCustomNotification()}>
|
||||||
Send notification
|
Send notification
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useState } from 'react';
|
|||||||
import { useNuiEvent } from '../../../hooks/useNuiEvent';
|
import { useNuiEvent } from '../../../hooks/useNuiEvent';
|
||||||
import { debugData } from '../../../utils/debugData';
|
import { debugData } from '../../../utils/debugData';
|
||||||
import { fetchNui } from '../../../utils/fetchNui';
|
import { fetchNui } from '../../../utils/fetchNui';
|
||||||
|
import ScaleFade from '../../../transitions/ScaleFade';
|
||||||
|
|
||||||
const radius = 60;
|
const radius = 60;
|
||||||
|
|
||||||
@@ -18,29 +19,11 @@ function getTransform(index: number, totalItems: number) {
|
|||||||
return `translate(${x}px, ${y}px)`;
|
return `translate(${x}px, ${y}px)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MenuItem {
|
export interface MenuItem {
|
||||||
icon: IconProp;
|
icon: IconProp;
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugData<{ items: MenuItem[]; sub?: boolean }>([
|
|
||||||
{
|
|
||||||
action: 'openRadialMenu',
|
|
||||||
data: {
|
|
||||||
items: [
|
|
||||||
// TODO: Fix wheel being broken when there's only one item
|
|
||||||
{ icon: 'palette', label: 'Paint' },
|
|
||||||
{ icon: 'warehouse', label: 'Garage' },
|
|
||||||
{ icon: 'palette', label: 'Quite long text' },
|
|
||||||
{ icon: 'palette', label: 'Paint' },
|
|
||||||
{ icon: 'warehouse', label: 'Garage' },
|
|
||||||
],
|
|
||||||
|
|
||||||
sub: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const useStyles = createStyles((theme) => ({
|
const useStyles = createStyles((theme) => ({
|
||||||
wrapper: {
|
wrapper: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -103,58 +86,60 @@ const RadialMenu: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box className={classes.wrapper}>
|
<Box className={classes.wrapper}>
|
||||||
<svg width="350px" height="350px" transform="rotate(90)">
|
<ScaleFade visible={visible}>
|
||||||
{/*Fixed issues with background circle extending the circle when there's less than 3 items*/}
|
<svg width="350px" height="350px" transform="rotate(90)">
|
||||||
{menu.items.length >= 3 && (
|
{/*Fixed issues with background circle extending the circle when there's less than 3 items*/}
|
||||||
<g transform="translate(175, 175)">
|
{menu.items.length >= 3 && (
|
||||||
<circle r={175} className={classes.backgroundCircle} />
|
<g transform="translate(175, 175)">
|
||||||
</g>
|
<circle r={175} className={classes.backgroundCircle} />
|
||||||
)}
|
</g>
|
||||||
{menu.items.map((item, index) => {
|
)}
|
||||||
const pieAngle = 360 / menu.items.length;
|
{menu.items.map((item, index) => {
|
||||||
const angle = degToRad(pieAngle / 2 + 90);
|
const pieAngle = 360 / menu.items.length;
|
||||||
const radius = 175 * 0.65;
|
const angle = degToRad(pieAngle / 2 + 90);
|
||||||
const iconX = 175 + Math.sin(angle) * radius;
|
const radius = 175 * 0.65;
|
||||||
const iconY = 175 + Math.cos(angle) * radius;
|
const iconX = 175 + Math.sin(angle) * radius;
|
||||||
|
const iconY = 175 + Math.cos(angle) * radius;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<g transform={`rotate(-${index * pieAngle} 175 175)`} className={classes.sector}>
|
<g transform={`rotate(-${index * pieAngle} 175 175)`} className={classes.sector}>
|
||||||
<path
|
<path
|
||||||
d={`M175.01,175.01 l175,0 A175.01,175.01 0 0,0 ${175 + 175 * Math.cos(-degToRad(pieAngle))}, ${
|
d={`M175.01,175.01 l175,0 A175.01,175.01 0 0,0 ${175 + 175 * Math.cos(-degToRad(pieAngle))}, ${
|
||||||
175 + 175 * Math.sin(-degToRad(pieAngle))
|
175 + 175 * Math.sin(-degToRad(pieAngle))
|
||||||
} z`}
|
} z`}
|
||||||
/>
|
|
||||||
<g transform={`rotate(${index * pieAngle - 90} ${iconX} ${iconY})`} pointerEvents="none">
|
|
||||||
<FontAwesomeIcon
|
|
||||||
x={iconX - 12.5}
|
|
||||||
y={iconY - 17.5}
|
|
||||||
icon={item.icon}
|
|
||||||
width={25}
|
|
||||||
height={25}
|
|
||||||
fixedWidth
|
|
||||||
/>
|
/>
|
||||||
<text x={iconX} y={iconY + 25} fill="#fff" textAnchor="middle" pointerEvents="none">
|
<g transform={`rotate(${index * pieAngle - 90} ${iconX} ${iconY})`} pointerEvents="none">
|
||||||
{item.label}
|
<FontAwesomeIcon
|
||||||
</text>
|
x={iconX - 12.5}
|
||||||
|
y={iconY - 17.5}
|
||||||
|
icon={item.icon}
|
||||||
|
width={25}
|
||||||
|
height={25}
|
||||||
|
fixedWidth
|
||||||
|
/>
|
||||||
|
<text x={iconX} y={iconY + 25} fill="#fff" textAnchor="middle" pointerEvents="none">
|
||||||
|
{item.label}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</>
|
||||||
</>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
<g transform="translate(175, 175)" onClick={() => setVisible(false)}>
|
||||||
<g transform="translate(175, 175)">
|
<circle r={30} className={classes.centerCircle} />
|
||||||
<circle r={30} className={classes.centerCircle} />
|
</g>
|
||||||
</g>
|
<FontAwesomeIcon
|
||||||
<FontAwesomeIcon
|
icon="xmark"
|
||||||
icon="xmark"
|
className={classes.centerIcon}
|
||||||
className={classes.centerIcon}
|
color="#fff"
|
||||||
color="#fff"
|
width={28}
|
||||||
width={28}
|
height={28}
|
||||||
height={28}
|
x={175 - 28 / 2}
|
||||||
x={175 - 28 / 2}
|
y={175 - 28 / 2}
|
||||||
y={175 - 28 / 2}
|
/>
|
||||||
/>
|
</svg>
|
||||||
</svg>
|
</ScaleFade>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user