Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: js delay ongelma

dartvaneri [06.04.2012 19:46:55]

#

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);
}

Grez [06.04.2012 19:52:05]

#

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

dartvaneri [06.04.2012 20:06:53]

#

Eli tarkottaneeko tuo, että tuo tekee ton sydeemin, jos mulla nyt vaikka y on 226 niin 226 sekunnin päästä?

jlaire [06.04.2012 20:17:50]

#

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.

tsuriga [06.04.2012 21:40:39]

#

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.

dartvaneri [06.04.2012 21:50:46]

#

Aa okei. Kokeilinkin tuota tuossa aikasemmin, mutta jostain syystä se ei toiminut, mutta nyt toimii, kiitos!

The Alchemist [09.04.2012 08:53:21]

#

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.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta