diff --git a/web/src/features/dev/debug/radial.ts b/web/src/features/dev/debug/radial.ts index 15fa333..05cc57c 100644 --- a/web/src/features/dev/debug/radial.ts +++ b/web/src/features/dev/debug/radial.ts @@ -10,9 +10,10 @@ export const debugRadial = () => { { icon: 'palette', label: 'Paint' }, { iconWidth: 35, iconHeight: 35, icon: 'https://icon-library.com/images/white-icon-png/white-icon-png-18.jpg', label: 'External icon'}, { icon: 'warehouse', label: 'Garage' }, - { icon: 'palette', label: 'Quite long \ntext' }, + { icon: 'palette', label: 'Quite Long Text' }, + { icon: 'palette', label: 'Fahrzeuginteraktionen' }, + { icon: 'palette', label: 'Fahrzeuginteraktionen' }, { icon: 'palette', label: 'Paint' }, - { icon: 'warehouse', label: 'Garage' }, ], }, }, diff --git a/web/src/features/menu/radial/index.tsx b/web/src/features/menu/radial/index.tsx index aa9409d..d18bba6 100644 --- a/web/src/features/menu/radial/index.tsx +++ b/web/src/features/menu/radial/index.tsx @@ -22,12 +22,14 @@ const useStyles = createStyles((theme) => ({ '&:hover': { fill: theme.fn.primaryColor(), + cursor: 'pointer', '> g > text, > g > svg > path': { fill: '#fff', }, }, '> g > text': { fill: theme.colors.dark[0], + strokeWidth: 0, }, }, backgroundCircle: { @@ -39,6 +41,7 @@ const useStyles = createStyles((theme) => ({ stroke: theme.colors.dark[6], strokeWidth: 4, '&:hover': { + cursor: 'pointer', fill: theme.colors[theme.primaryColor][theme.fn.primaryShade() - 1], }, }, @@ -54,14 +57,37 @@ const useStyles = createStyles((theme) => ({ }, })); -// includes More... button -const PAGE_ITEMS = 8; +const calculateFontSize = (text: string): number => { + if (text.length > 20) return 10; + if (text.length > 15) return 12; + return 13; +}; + +const splitTextIntoLines = (text: string, maxCharPerLine: number = 15): string[] => { + const words = text.split(' '); + const lines: string[] = []; + let currentLine = words[0]; + + for (let i = 1; i < words.length; i++) { + if (currentLine.length + words[i].length + 1 <= maxCharPerLine) { + currentLine += ' ' + words[i]; + } else { + lines.push(currentLine); + currentLine = words[i]; + } + } + lines.push(currentLine); + return lines; +}; + +const PAGE_ITEMS = 6; const degToRad = (deg: number) => deg * (Math.PI / 180); const RadialMenu: React.FC = () => { const { classes } = useStyles(); const { locale } = useLocales(); + const newDimension = 350 * 1.1025; const [visible, setVisible] = useState(false); const [menuItems, setMenuItems] = useState([]); const [menu, setMenu] = useState<{ items: RadialMenuItem[]; sub?: boolean; page: number }>({ @@ -119,74 +145,83 @@ const RadialMenu: React.FC = () => { }} > - - {/*Fixed issues with background circle extending the circle when there's less than 3 items*/} + + {/* Fixed issues with background circle extending the circle when there's less than 3 items */} {menuItems.map((item, index) => { - // Always draw full circle to avoid elipse circles with 2 or less items const pieAngle = 360 / (menuItems.length < 3 ? 3 : menuItems.length); const angle = degToRad(pieAngle / 2 + 90); - const gap = 0; + const gap = 1; const radius = 175 * 0.65 - gap; const sinAngle = Math.sin(angle); const cosAngle = Math.cos(angle); + const iconYOffset = splitTextIntoLines(item.label, 15).length > 3 ? 3 : 0; const iconX = 175 + sinAngle * radius; - const iconY = 175 + cosAngle * radius; + const iconY = 175 + cosAngle * radius + iconYOffset; // Apply the Y offset to iconY const iconWidth = Math.min(Math.max(item.iconWidth || 50, 0), 100); const iconHeight = Math.min(Math.max(item.iconHeight || 50, 0), 100); - return ( - <> - { - const clickIndex = - menu.page === 1 ? index : PAGE_ITEMS * (menu.page - 1) - (menu.page - 1) + index; - if (!item.isMore) fetchNui('radialClick', clickIndex); - else { - await changePage(true); - } - }} - > - - - {typeof item.icon === 'string' && isIconUrl(item.icon) ? ( - - ) : ( - - )} - - {item.label.includes(' \n') - ? item.label.split(' \n').map((value) => ( - - {value} - - )) - : item.label} - - + { + const clickIndex = menu.page === 1 ? index : PAGE_ITEMS * (menu.page - 1) - (menu.page - 1) + index; + if (!item.isMore) fetchNui('radialClick', clickIndex); + else { + await changePage(true); + } + }} + > + + + {typeof item.icon === 'string' && isIconUrl(item.icon) ? ( + + ) : ( + + )} + 2 ? 15 : 28)} + fill="#fff" + textAnchor="middle" + fontSize={calculateFontSize(item.label)} + pointerEvents="none" + lengthAdjust="spacingAndGlyphs" + > + {splitTextIntoLines(item.label, 15).map((line, index) => ( + + {line} + + ))} + - + ); })} { } }} > - +