Eli seuravanlainen koodi, jonka pitäis periaatteessa liuttaa laatikkoa. Ongelma on siinä, että se tekee tuon 1s jälkene ton koko siirron, eli for pyörii sillä välinkin kun tuo sen sisä osa odottaa. Miten korjata tämä niin, että tuo for menee tuon setTimeoutin tahtiin noita kierroksia? y on se kohta mille kohdalle sen pitäisi liukua tuon laatikon.
for(var i = 0; i < y; i++){ setTimeout(function() { pos = (i-55); $("#info").css({"top": pos,"position": "relative"}); },1000); }
Asetat tuossa y kappaletta timeoutteja tapahtumaan samanaikaisesti 1 sek kuluttua.
Kokeile laittaa riville 5 vaikka
},i*1000);
Edit: Siis tietenkin i*1000, ei y*1000
Eli tarkottaneeko tuo, että tuo tekee ton sydeemin, jos mulla nyt vaikka y on 226 niin 226 sekunnin päästä?
setTimeout
ei tosiaan jää odottamaan, mikä on hyvä asia koska JavaScriptin blokatessa koko sivu on jumissa. Silmukka suoritetaan loppuun ennen timeoutteja.
Tästä aiheutuu sellainen bugi, että kun timeoutteja aletaan suorittaa silmukan päätyttyä, i
:n arvo on y
ja kaikki timeoutit käyttävät tätä arvoa. Eli Grezin korjauksen jälkeenkin elementti hyppää heti lopulliseen paikkaansa. Funktioiden pitää tallentaa i
:n arvo timeoutin asetushetkellä. Sen voi tehdä näin:
for(var i = 0; i < y; i++){ setTimeout((function(i) { return function() { // HUOM: ilman var-sanaa tehdään globaali pos-muuttuja var pos = (i-55); $("#info").css({"top": pos,"position": "relative"}); }; })(i), i*50); }
Muitakin ratkaisuja on, kuten vaikka jonkin kirjaston käyttö.
Edit: Jos vastaavia silmukoita tekee paljon, apufunktio voi selkeyttää koodia:
function asyncLoop(i, max, delay, f) { if (i >= max) return; setTimeout(function() { asyncLoop(i + 1, max, delay, f); }, delay); f(i); } asyncLoop(0, y, 50, function(i) { var pos = i - 55; $("#info").css({"top": pos,"position": "relative"}); });
Koodipätkien toimintaa on helppo testata sanomalla console.log(i)
tuolla sisemmässä funktiossa.
Arvailen et sulla on käytössä jQuery, josta löytyy itsestään jQuery.animate
. Infoboksille ensin CSS:llä { position: relative; top: -55px; }
tai mitä haluatkaan ja sitten eiko
$('#info').animate({ top: (y - 55) + 'px'}, 1000);
Sisäisesti tuo käyttää setIntervalia
setTimeoutin
sijaan. Näiden eroista voi lukea @ stackoverflow - setTimeout or setInterval.
Aa okei. Kokeilinkin tuota tuossa aikasemmin, mutta jostain syystä se ei toiminut, mutta nyt toimii, kiitos!
Silloin kun tiedät, että valmis toiminto on jo olemassa muttet osaa käyttää sitä, niin opettele käyttämään sitä, äläkä ala purkata omiasi. Varsinkin kun et edes saanut omaasikaan toimimaan vaan aloit arpoa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.