Seite 1 von 1
Tortenmenü, yumi!
Verfasst: 26.12.2013 01:00
von Lambda
Ich benötige die Ausrichtung verschieden breiter Menü-Elemente um einen Punkt herum. Es können beliebig viele und beliebig breite sein, daher sollte es keine Überlappungen geben. Zeitlich bin ich gerade etwas ausgelastet daher würde ich mich freuen wenn jemand eine schicke Lösung formen könnte.
Sandkasten-Code:
Code: Alles auswählen
OpenWindow(0, 0, 0, 400, 300, "", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, 400, 300)
Procedure.f lendirx(Length.f, Direction.f)
ProcedureReturn Cos(Direction*#PI/180)*Length
EndProcedure
Procedure.f lendiry(Length.f, Direction.f)
ProcedureReturn -Sin(Direction*#PI/180)*Length
EndProcedure
Structure ITEM
x.f
y.f
a.f
c.i
Size.SIZE
EndStructure
Global NewList Item.ITEM(), i
For i=0 To 10
AddElement(Item())
Item()\Size\cx = 80
Item()\Size\cy = 20
Item()\c = RGB(Random(255),Random(255),Random(255))
Next
StartDrawing(CanvasOutput(0))
ForEach Item()
Item()\a = (360/ListSize(Item()))*ListIndex(Item())
Next
Define *Pre.ITEM
ForEach Item()
Item()\x = lendirx(120, Item()\a)
Item()\y = lendiry(60, Item()\a)
*Pre = @Item()
Next
ForEach Item()
Box(200+Item()\x, 150+Item()\y, 80, 20, Item()\c)
Next
ForEach Item()
DrawText(200+Item()\x, 150+Item()\y,Str(Item()\a))
Next
StopDrawing()
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
Re: Tortenmenü, yumi!
Verfasst: 26.12.2013 20:08
von STARGÅTE
Wenn es keine Überlappung geben darf, und auf jedenfall N Elemente verteilt werden sollen, musst du aber zwangsweise einen Fit-Parameter zur Verfügung stellen, welcher?
- Soll der Radius vergrößert werden?
Nur synchron? oder zwei unabhängige Radien?
- Soll die Schrift verkleinert werden?
Alle zusammen oder unterschiedliche Schriftgrößen?
- Darf die Reihenfolge der Menüpunkte vertauscht werden?
Breite Elemente eignen sich ja besser links und rechts, statt oben und unten.
Re: Tortenmenü, yumi!
Verfasst: 26.12.2013 21:28
von Lambda
Der Radius kann natürlich verändert werden, auch etwas oval.

Die Reihenfolge wäre wichtig, da die Elemente dann in allen Sprachen die selbe Reihenfolge einhalten sollten.
Re: Tortenmenü, yumi!
Verfasst: 28.12.2013 13:24
von Lambda
Findet sich noch jemand?
Re: Tortenmenü, yumi!
Verfasst: 28.12.2013 14:17
von Danilo
Für was brauchst Du das denn genau? Vielleicht ist ein
Carousel control geeigneter für ein Menu?
"Es können beliebig viele sein", also auch Tausende, ist schon etwas sehr allgemein gehalten. Dann würde das Tortenbild riesig werden.
Für ein (übersichtliches) Menu sollten doch maximal 20-25 Einträge meist ausreichen?
Re: Tortenmenü, yumi!
Verfasst: 28.12.2013 16:12
von Lambda
"Beliebig viele" war eher darauf bezogen, dass die Anzahl ständig variiert und mal eine gerade als auch ungerade Anzahl (bestenfalls symmetrisch) verteilt werden muss. Ja, mehr als 20 pro Menü sind es nicht

.
Wären es simple Symbole mit fester Größe wäre das kein Ding, genaueres Beispiel wäre das Menü aus "Die Sims", genau ein solches benötige ich.

Re: Tortenmenü, yumi!
Verfasst: 28.12.2013 17:04
von STARGÅTE
Aber in dem Bild ist ja eindeutig zu sehen, dass die beiden klein Einträge obne und unten angelegt wurden und die großen an die Seite. Also eine sortierung!
Das möchtest du ja nicht haben.
Man müsste also in deinem Modell zunächst mal alle Einträge anlegen und dann alle Winkel von 0-360° durchlaufen und den Winkel mit der geringsten Überschneidung finden.
Danach vergrößert man den Radius, biss die Überschneidung weg ist.
Mein erster Lösungsweg wäre also iterativ, weiß aber nicht ob dir das reicht?
Re: Tortenmenü, yumi!
Verfasst: 28.12.2013 18:15
von Danilo
Code: Alles auswählen
Structure ITEMRECT
x.i
y.i
width.i
height.i
EndStructure
Structure ITEM
text.s
textColor.i
rect.ITEMRECT
EndStructure
Procedure DrawItems(x,y,List items.ITEM(),linespacing=0)
itemCount = ListSize( items() )
If itemCount = 0
ProcedureReturn
EndIf
ForEach items()
items()\rect\width = TextWidth( items()\text )+4
items()\rect\height = TextHeight( items()\text )+4+linespacing
Next
FirstElement( items() )
If itemCount = 1
items()\rect\x = x - items()\rect\width * 0.5
items()\rect\y = y - items()\rect\height * 0.5
ElseIf itemCount = 2
items()\rect\x = x - items()\rect\width * 0.5
items()\rect\y = y - items()\rect\height - 1
NextElement( items() )
items()\rect\x = x - items()\rect\width * 0.5
items()\rect\y = y + 1
Else
mod = ((itemCount - 2) % 2)
left = (itemCount - 2) / 2 + mod
right = itemCount - 2 - left
height = left * (items()\rect\height)
items()\rect\x = x - items()\rect\width * 0.5
items()\rect\y = y - items()\rect\height - 4 - (height * 0.5)
isLeft = 1 : new_y = y - height * 0.5
line = 1
items = left
winkel.f = 180/(items+1)
For i = 1 To itemCount - 2
NextElement( items() )
If isLeft
x_off = Cos(Radian(-90+(line)*winkel)) * height * 0.5
items()\rect\x = x - items()\rect\width - 1 - x_off
items()\rect\y = new_y
isLeft ! 1
Else
items()\rect\x = x + 1 + x_off ;+ items()\rect\height * 0.5
items()\rect\y = new_y
isLeft ! 1
new_y + items()\rect\height + 2
line + 1
EndIf
Next
If NextElement( items() )
If left = right
;new_y + items()\rect\height + 2
items()\rect\x = x - items()\rect\width * 0.5
items()\rect\y = new_y
Else
items()\rect\x = x + 1 + x_off ;+ items()\rect\height * 0.5
items()\rect\y = new_y
EndIf
EndIf
EndIf
ForEach items()
DrawingMode(#PB_2DDrawing_Gradient)
ResetGradientColors()
BackColor(RGB(0,0,255))
FrontColor(RGB(255,0,0))
LinearGradient(items()\rect\x, items()\rect\y, items()\rect\x+items()\rect\width, items()\rect\y+items()\rect\height)
Box(items()\rect\x, items()\rect\y, items()\rect\width, items()\rect\height-linespacing)
DrawingMode(#PB_2DDrawing_Transparent)
DrawText( items()\rect\x+2, items()\rect\y+2, items()\text, items()\textColor)
Next
EndProcedure
Procedure GenerateEntries(count,List items.ITEM())
ClearList( items() )
If count
For i=1 To count
AddElement(Items())
Items()\text = "Menu "+Str(i)+" "
For j = 0 To Random(50)
items()\text + Chr(Random(25)+'a')
Next
Items()\textColor = RGB(255,255,255)
Next
EndIf
EndProcedure
NewList Items.ITEM()
OpenWindow(0, 0, 0, 800, 600, "", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, WindowWidth(0)-100, WindowHeight(0))
SpinGadget(1,WindowWidth(0)-90,10,80,20,1,50)
SetGadgetState(1,8)
SetGadgetText(1,Str(GetGadgetState(1)))
LoadFont(1,"Arial",20)
GenerateEntries(GetGadgetState(1),Items())
If StartDrawing( CanvasOutput(0) )
DrawingFont(FontID(1))
DrawItems( OutputWidth()*0.5, OutputHeight()*0.5, Items(), 2 )
StopDrawing()
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
If EventGadget()=1
count = GetGadgetState(1)
SetGadgetText(1,Str(count))
GenerateEntries(count,Items())
If StartDrawing( CanvasOutput(0) )
Box(0,0,OutputWidth(),OutputHeight(),RGB(255,255,255))
DrawingFont(FontID(1))
DrawItems( OutputWidth()*0.5, OutputHeight()*0.5, Items(), 5 )
StopDrawing()
EndIf
EndIf
EndSelect
ForEver
Re: Tortenmenü, yumi!
Verfasst: 29.12.2013 16:44
von Lambda
Exzellent Danilo!

Danke dir, sogar mit aufgehübschten Beispiel. ^^