Jump to content

Pretty Complicated Accordion Menu


h4x7o0r

Recommended Posts

Hey there guys,

I spent already enough days just to figure it out how can i create a nice vertical accordion animated menu.

Here's a link with the live animation (just because it's pretty complicated to explain, vertical one) :

http://goo.gl/rmoLSz

So here's what i tried so far. This is the way rooms are organized :

Arenas = {} 
  
Arenas.Paianjen= {} 
Arenas.Paianjen.unique = 1  
Arenas.Paianjen.x = coloana1 
Arenas.Paianjen.y = randul1 
Arenas.Paianjen.mouseY = randul1 
Arenas.Paianjen.size = lungime 
Arenas.Paianjen.height = inaltime 
Arenas.Paianjen.moveLock = false 
Arenas.Paianjen.Element = getElementByID("Paianjen") 
  
Arenas.Bondar= {} 
Arenas.Bondar.unique = 2 
Arenas.Bondar.x = coloana1 
Arenas.Bondar.y = randul1 
Arenas.Bondar.mouseY = randul1 
Arenas.Bondar.size = lungime 
Arenas.Bondar.height = inaltime 
Arenas.Bondar.moveLock = false 
Arenas.Bondar.Element = getElementByID("Bondar") 
  
Arenas.Hiena= {} 
Arenas.Hiena.unique = 3 
Arenas.Hiena.x = coloana1 
Arenas.Hiena.y = randul1 
Arenas.Hiena.mouseY = randul1 
Arenas.Hiena.size = lungime 
Arenas.Hiena.height = inaltime 
Arenas.Hiena.moveLock = false 
Arenas.Hiena.Element = getElementByID("Hiena") 
  
Arenas.Amfibie= {} 
Arenas.Amfibie.unique = 4 
Arenas.Amfibie.x = coloana1 
Arenas.Amfibie.y = randul1 
Arenas.Amfibie.mouseY = randul1 
Arenas.Amfibie.size = lungime 
Arenas.Amfibie.height = inaltime 
Arenas.Amfibie.moveLock = false 
Arenas.Amfibie.Element = getElementByID("Amfibie") 
  
for i, arena in pairs(Arenas) do 
    local r, g, b = getColorFromString(getElementData(arena.Element, "color")) 
    arena.Color = tocolor(r, g, b, 255) 
  
dxDrawRectangle ( arena.x, arena.y, arena.size, arena.height, arena.Color, true) 
  
hover = mouseCheck(mx, my, arena.x, arena.x+arena.size, arena.mouseY, arena.mouseY+arena.height) 
  
    if hover == true and arena.moveLock == false then 
        --animation when mouse is over arena 
          arena.moveLock = true 
    elseif hover == false and arena.moveLock == true then  
        --animation when mouse isn't over arena 
        arena.moveLock = false 
    end 
end 
  
function mouseCheck(mx, my, x1, x2, y1, y2) 
if mx < x1 or mx > x2 then return false end 
if my < y1 or my > y2 then return false end 
return true 
end 
  
  

These are the variables needed for the animation:

  
DefaultArenaHeight : 70 --Default arena height when mouse isn't over 
MaxArenaHeight = 200 --Maximum arena height when mouse is over and arena's increasing it's height 
NumArenas : 4 -- Number of all arenas 
DiffArenas : MaxArenaHeight - DefaultArenaHeight  -- Difference between maximum height and default height, so 200 - 70 = 130  
RaportArenas: DiffArenas / NumArenas -- Here's the shrinking value for all arenas but the one mouse is OVER it. 
  

What i need is to know how can i create the conditions in order to replicate this accordion effect ?

i think i need to "detect" somehow when the cursor is hovering over an arena, that arena then has to change it's size (from 70 => 200) while the other ones are decreasing the height ( 70 -> RaportArenas ).

Also the arenas above the one mouse is over, they should be moving up while shrinking, as for the arenas under the one the mouse is hovering on, they sould move down while shrinking. Kinda complicated to explain.

Hope isn't that ambiguous, i tried to simplify as much as i could.

Thanks in advance.

Link to comment

Look at the Wiki, it has all of the functions and events.

getCursorPosition and onClientCursorMove

Alternatively, you can use GUI Elements to help you - and just set their alpha to 0. This is what I do when I don't feel like building up an system to detect when the mouse is over some DX drawn stuff.

This way you can utilize all of the GUI functions and events. Then you can use interpolateBetween to generate a smooth accordion effect.

Link to comment

Thanks mate, i'm getting already cursor position. Your idea with GUI's seems great but at this moment, my problem isn't animation.

I wanna use some IF statements to determine a rule, like when mouse is over an arena , that arena to increase its height while arenas above the decrease + move up and also arenas beyond decrease + move down.

I don't know how to exclude the arena when mouse is over it because, for example hover == true wont work in this case. (mouse will be over an arena still when i need to shrink and move others, that's why hover==false isn't executed).

Link to comment

Tried something, not tested but hoping to give you a general idea.

Arenas = {} 
Arenas.selected = nil 
  
-- ... 
  
addEventHandler("onClientRender",root, function() 
    local isAnyArenaSelected = false 
     
    for i, arena in pairs(Arenas) do 
        local r, g, b = getColorFromString(getElementData(arena.Element, "color")) 
        arena.Color = tocolor(r, g, b, 255) 
  
        dxDrawRectangle ( arena.x, arena.y, arena.size, arena.height, arena.Color, true) 
         
        local mx, my = getCursorPosition() 
        hover = mouseCheck(mx, my, arena.x, arena.x+arena.size, arena.mouseY, arena.mouseY+arena.height) 
  
        if hover == true then 
            isAnyArenaSelected = true 
            if not Arenas.selected then 
                -- preset animation when mouse is over arena 
                selectArena(arena) 
            end 
        end 
    end 
     
    if not isAnyArenaSelected and Arenas.selected then 
        -- preset animation when mouse isn't over any arena and there is still one selected 
        selectArena( nil ) 
    end 
end) 
  
function selectArena(arena) 
    Arenas.selected = arena 
    -- this function prepares all new positions and sizes when an arena is (de)selected 
    for i, a in pairs(Arenas) do 
        if arena == nil then 
            -- no arena selected, move back to default size and position 
            arena.next_y = ... 
            arena.next_height = defaultArenaHeight 
        elseif a == arena then 
            -- this is the selected arena, maximum height 
            arena.next_y = ... 
            arena.next_height = MaxArenaHeight 
        else 
            -- this is an arena that needs to be minimized 
            arena.next_y = ... 
            arena.next_height = defaultArenaHeight * NumArenas - MaxArenaHeight 
        end 
    end 
end 
  
setTimer(function() 
    -- this timer moves y and height up to their next_ value 
    for i, arena in pairs(Arenas) do 
        if (arena.next_y and arena.y ~= arena.next_y) then 
            if arena.y < arena.next_y then 
                arena.y += 1 
            else 
                arena.y += -1 
            end 
        end 
        if (arena.next_height and arena.height ~= arena.next_height) then 
            if arena.height < arena.next_height then 
                arena.height += 1 
            else 
                arena.height += -1 
            end 
        end 
    end 
end, 100, 0) 
-- 100 can be used to change the animation speed 
  

If you're still having trouble I would recommend adding one feature at the time to your script. Use GUI Images and use clicks (OnClientGUIClick) instead of hovering to keep it simple and have something that works. Afterwards you can modify that to use onClientMouseEnter/Leave for hover or back to dxDraw functions.

Link to comment

This is made out of 4 images.. (Note they are 5 values, for 4 images, value 1 is if none is selected)

  
ImageStart = {             Image1 = {                 {0.2, 0, 1, 1, "Image1.jpg"},                 {0.2, 0, 1, 1, "Image1.jpg"},                 {0.2, 0, 1, 1, "Image1.jpg"},                 {0.2, 0, 1, 1, "Image1.jpg"},                 {0.2, 0, 1, 1, "Image1.jpg"}             },             Image2 = {                 {0.4, 0, 1, 1, "Image2.jpg"},                 {0.7, 0, 1, 1, "Image2.jpg"},                 {0.3, 0, 1, 1, "Image2.jpg"},                 {0.3, 0, 1, 1, "Image2.jpg"},                 {0.3, 0, 1, 1, "Image2.jpg"}             },             Image3 = {                 {0.6, 0, 1, 1, "Image3.jpg"},                 {0.8, 0, 1, 1, "Image3.jpg"},                 {0.8, 0, 1, 1, "Image3.jpg"},                 {0.4, 0, 1, 1, "Image3.jpg"},                 {0.4, 0, 1, 1, "Image3.jpg"}             },             Image4 = {                 {0.8, 0, 1, 1, "Image4.jpg"},                 {0.9, 0, 1, 1, "Image4.jpg"},                 {0.9, 0, 1, 1, "Image4.jpg"},                 {0.9, 0, 1, 1, "Image4.jpg"},                 {0.5, 0, 1, 1, "Image4.jpg"}             }  }

PD: Couldnt make the lua syntax work

Edited by Guest
Link to comment

Thanks a lot guys for your time trying to help me.

SDK, yeah that's a good view over the entire script, thanks a lot i'll try to fix this and adapt to my needs.

HyPeX, well sincerely i have no clue what's this all code about but thanks anyway for your time.

Link to comment
Thanks a lot guys for your time trying to help me.

SDK, yeah that's a good view over the entire script, thanks a lot i'll try to fix this and adapt to my needs.

HyPeX, well sincerely i have no clue what's this all code about but thanks anyway for your time.

Its just Positions of image,

First table (Image1) contains the 5 variable positions wich the Image1 could be. (At 1st table its if no image is extended, at second if first one is extended, at third, and so on until the 5th line, wich is equal to 4 images.)

The values itself are pretty easy:

local x,y = guiGetScreenSize() 
1 = 0.2*x 
2 = 0*y 
3 = 1*x 
4 = 1*y 
5 = filepath 

Link to comment

Thanks for your reply .:HyPeX:. but i think it's not what i need but i appreciate your effort.

Anyone who can create this for me for a fair price ? Need a pretty skilled scripter as long as some other scripters already tried to help me with this and failed.

Thanks in advance.

Link to comment
  • Moderators
All you need is "time", which is missing in your code.

speed <=> time <=> distance

s2table1.gif

and some old school math of course.

Without time you can't manage an animation correctly.

Time can give us everything we need to know.

You can also choose for calculating only with time.

Use: (in ms)

getTickCount() 

Example:

  
  
  
local timeNow = getTickCount() 
  
local futureTime = timeNow+ 1000 
local progress = (futureTime-timeNow)/3000  
outputChatBox("progress: " .. progress) 
  
local futureTime = timeNow+ 2000 
local progress = (futureTime-timeNow)/3000  
outputChatBox("progress: " .. progress) 
  
local futureTime = timeNow+ 3000 
local progress = (futureTime-timeNow)/3000  
outputChatBox("progress: " .. progress) 
  
-- playback -- 
local futureTime = timeNow+ 1200 
local progress = (futureTime-timeNow)/3000  
outputChatBox("progress: " .. 1-progress) 
  

And don't say to me that this has nothing to do with it, because this how you animate things.......

Link to comment
And don't say to me that this has nothing to do with it, because this how you animate things.......

Thanks for you reply but either u haven't read the posts above either you didn't get what i asked for.

As i said before:

"What i need is to know how can i create the conditions in order to replicate this accordion effect ?"

I can create animations by myself but the if statements involved for creating the functionality is what i'm missing.

Anyways that seems too complicated for me so if someone wants to create what i need for a fair price, just pm me.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...