Autor | Zpráva | ||
---|---|---|---|
mark Profil |
zdravim, chcem naprogramovat plynuly pohyb obrazku a neviem, prečo mi nefunguje tento skript:
for (i=1; i<=10; i++) {setTimeout("document.getElementById('div').style.top = i + 'px'", i*100);} ... pričom <div id="div"></div> mám, prejaví sa to tým, že obrázok za 100 milisekund skočí o 10px dole, a jeho pohyb nieje plynulý, ako by som chcel a netrvá 1 sekundu (100x10 milisekúnd). Neviete v čom je chyba? poraďte prosím, ďakujem.... |
||
Nox Profil |
#2 · Zasláno: 23. 8. 2008, 21:28:19
Místo této zběsilosti použij setInterval...a plynulé to není samozřejmě když máš tak dlouhý interval 100ms a a tak velký posun 10px
|
||
mark Profil |
#3 · Zasláno: 23. 8. 2008, 21:37:19
Posun som nastavil na 1 px, skúsil som seInterval, windows.setInterval a nefunguje to, zaujívamé je ale to, že keď to nahrubo všetko vypíšem:
setTimeout("document.getElementById('div').style.top = 1 + 'px'", 1*100); setTimeout("document.getElementById('div').style.top = 2 + 'px'", 2*100); setTimeout("document.getElementById('div').style.top = 3 + 'px'", 3*100); ... a namiesto premennej "i" dosadím hodnoty, ako som uviedol v príklade, tak mi to funguje, s cyklom for nie.... DIV som vypísal nasledovne: document.write("<div id='div' style='position: absolute; z-index: 1; top: 0px; left: 0px; width: 44px; height: 44px; background: url(img.PNG)'></div>"); |
||
mark Profil |
#4 · Zasláno: 23. 8. 2008, 21:38:36
*window.setInterval a *setInterval
|
||
Nox Profil |
#5 · Zasláno: 23. 8. 2008, 22:01:10
function Pohni(div,kolik,limit){ div.style.top=parseInt(div.style.top)-(-kolik)+"px"; if((kolik>0 && parseInt(div.style.top)>=limit) || (kolik<0 && parseInt(div.style.top)<=limit)){ clearInterval(move); } } move=setInterval("Pohni(document.getElementById('div'),1,100)",8); |
||
mark Profil |
#6 · Zasláno: 23. 8. 2008, 22:13:59
waaaaaw, ono to funguje:)) veeľmi pekne ďakujem.......:)
|
||
Nox Profil |
#7 · Zasláno: 23. 8. 2008, 22:28:10
to jsem rád:) nemáš zač
|
||
ah01 Profil |
#8 · Zasláno: 23. 8. 2008, 23:27:46 · Upravil/a: ah01
Nox
Funguje to, ale moc pěkné to není. 1) Ono je paradoxně výhodnější použít onTimeout (viz http://ejohn.org/blog/how-javascript-timers-work/) 2) Zadávat do setInterval nebo kamkoli jinam volání funkce jako řetězec, je dost velká prasárna (omlouvám se za to slovo, neber si to osobně, je to tu vidět dost často, tak na to chci zase jednou upozornit) 3) Používat globální proměnou (move) je dost nevýhodné, můžeš hýbat jen jedním objektem v jeden čas. Nebudu zde uvádět fungující řešení, ale jen napíšu kostru, jak je vhodné podobné úkoly řešit. Můžeš si zkusit přepsat své řešení tímto způsobem. Můžeš to brát třeba jako zdokonalování svých JS dovedností ;-) function animace(div, speed, ... další potřebné parametry ) { function step() { jeden krok animace // např. posuň div o jeden krok if(! už je konec ? ) { setTimeout(step, speed); // pokud ne, jdi za chvíli na další krok } } step(); // spuštění animace } Možná se to nezdá, ale takovýto krátký kód ukazuje mnoho důležitých vlastností JS – funkcionální programování, closure, scope. Pro inspiraci se můžeš podívat na http://jslab.net/pub/jpw/closure.html |
||
Nox Profil |
#9 · Zasláno: 24. 8. 2008, 10:11:56 · Upravil/a: Nox
ah01
1) Díky, mrknu (a dalším to taky pomůže) 2) Možná máš pravdu, ikdyž bych se rád dozvěděl proč to tedy podle tebe je prasárna 3) Prostě se použije globální pole a je po problému, stejně si engine určitě vytváří nějaký identifikátor timeoutu, aby s ním mohl pracovat (navazuju v dalším odstavci) Nestudoval jsem, ale tipoval bych že budou enginy lépe optimalizované pro jedno spuštění intervalu a pak jeho provádění, než neustálé rušení a spouštění timeoutů, ale nečetl sem o tom, je to jen má domněnka Já zase nejsem moc fanda rekurzivních funkcí:) Každopádně děkuju za tvůj příspěvek Edit: Tak ten první článek moc nechápu, hlavně mi přijde že ten graf říká něco úplně jiného než ten článek, ale zkusím o tom ještě někdy něco pohledat V tom druhém, je to podobné co si tu psal, ale pořád si nejsem jistý proč to dělat tímto způsobem (definovat funkci ve funkci a pak ji ještě rekurzivně opakovat) (ale neznal jsem tu syntaxi onload = ...zase něco nového) |
||
mark Profil |
#10 · Zasláno: 24. 8. 2008, 14:05:21
asi hodinu som študoval kód od Noxa, kým som mu celkom pochopil a upravil som si ho na mieru, aby sa mi to pohybovalo všetkými možnými smermi, s ľubovoľnými intervalmi, stanovil som si 2 limity - top a left a 2 intervaly_posunov, tiež top a left a taktiež som upravil na to aj podmienku;)
document.write("<div id='div' style='position: absolute; z-index: 1; top: 200px; left: 150px; width: 44px; height: 44px; background: url(img.PNG)'></div>"); function pohyb(div,interval_top,interval_left,limit_top,limit_left){ div.style.top=parseInt(div.style.top)+interval_top+"px"; div.style.left=parseInt(div.style.left)+interval_left+"px"; if((interval_top>0 && parseInt(div.style.top)>=limit_top) || (interval_top<0 && parseInt(div.style.top)<=limit_top) || (interval_left>0 && parseInt(div.style.left)>=limit_left) || (interval_left<0 && parseInt(div.style.left)<=limit_left)){ clearInterval(move); } } move=setInterval("pohyb(document.getElementById('div'),2,1,400,250)",10) a teraz ked čítam príspevok od ah01, dostávam sa do neistoty, nechápem s Noxom, prečo by to mala byť velká prasárna? Ako kód od Noxa, tak aj ten môj upravený, mi fungujú bez problémov a posúva sa to plynule .....:) |
||
Nox Profil |
#11 · Zasláno: 24. 8. 2008, 14:43:35
mark
Ono funkční neznamená vždy korektní nebo nejlepší - ah01 chtěl říct (když si drze dovolím mluvit za něj:) ), že to moje funguje, ale dalo by se to udělat rozhodně lépe, nejspíš bude mít pravdu (ikdyž důvody proč tomu tak je by mě zajímaly taky, ale to už sem psal v předchozím příspěvku) |
||
los Profil * |
#12 · Zasláno: 24. 8. 2008, 15:05:24
Je to nevhodné hlavne kvôli tomu, že vôbec nie je potrebné dynamicky vyhodnocovať reťazec, kvôli zavolaniu funkcie - je to zložitejšie (objekty sa musia prenášať pomocou globálnych premenných), pomalšie (pri každom zavolaní sa to musí rozparsovať), neprehľadnejšie (pri dlhších funkciách). Dá sa to prirovnať zavolaniu funkcie eval v takej situácií, kde to nie je vôbec nutné - funguje to, ale neexistuje žiaden rozumný dôvod, prečo to tak robiť.
|
||
mark Profil |
#13 · Zasláno: 24. 8. 2008, 19:52:20
keď mňa lepší kód nenapadne, dokonca ma nenapadol ani ten, čo mi poradil Nox. :o)
Okrem toho som sa ešte chcel spýtať na jednu drobnosť. Keď mám kód: document.write("<div style='position: relative; top: (premenna)px;'>"); , neviete, ako dosadiť do top: premennú? problém je v tom, že zápis je ohraničený ako "uvodzovkami", tak aj 'apostrofmi'. Poraďte prosím, ďakujem.... |
||
ah01 Profil |
#14 · Zasláno: 24. 8. 2008, 23:32:56 · Upravil/a: ah01
Nox
Pokusím se to více rozvést. volba setInterval vs. setTimeout Pokud vznikne nějaká událost (kliknutí myší, stisk klávesy nebo doběhnutí časovače), vloží se do fronty událostí, odkud si je postupně interpret JS odebírá a zpracovává je. K jejich zpracování zpravidla dojde ihned, ale může pochopitelně dojít k prodlení v případě, že ve frontě ještě budou starší nezpracované událost. setInterval pravidelně vytváří události o uběhnutí zadaného časového intervalu. Z toho plyne, že zadaný interval určuje, jak často dochází ke vzniku události, nevypovídá ale nic o tom, kdy tyto události budou zpracovány. V krajním případě může nastat situace, že se ve frontě nahromadí třeba 3 události od setInterval, které se pak zpracují ihned za sebou, což není to, co bychom od setInterval požadovali. Šance že k tomu dojde je samozřejmě vyšší u krátkých intervalů, což je právě případ různých animací a efektů. Při použití setTimeout k tomu dojít nemůže. používání eval (zadávání kódu v podobě řetězce) Používání eval, a jeho ekvivalentů, tedy new Function, setInterval a setTimeout je velké zlo (z anglického eval is evil). Psát jakýkoliv kód jako řetězec a pak ho spouštět vyhodnocením je velmi nebezpečné. Můžou tím snadno vzniknout chyby, které se velmi těžko hledají. V 99% případů to ukazuje na špatný návrh aplikace a je to zbytečné. Místo toho řetězce můžu předat funkci, která bude zavolaná po uběhnutí času. move = setInterval(function(){ pohyb(document.getElementById('div'), 2, 1, 400, 250); }, 10); Navíc můžu takto předat i reference na jiné objekty, což by jinak nebylo možné (zmiňuje to los). onload = function(){ var div = document.getElementById('div'); move = setInterval(function(){ pohyb(div, 2, 1, 400, 250); }, 10); } „Prostě se použije globální pole a je po problému“ Používat globální pole není v tomto případě třeba. Je to zbytečná komplikace. „Já zase nejsem moc fanda rekurzivních funkcí“ Toto v principu není rekurzivní funkce. K opětovnému zavolání step dojde až po uplynutí setTimeout. Uvedený způsob má několik výhod: • používá setTimeout, takže se vyhneš problémům se setInterval, • nepotřebuješ žádnou globální proměnou, vše potřebné umístíš do fce. animace a díky closure to máš dostupné i v rámci fce step, • díky předchozímu bodu můžeš tuto funkci volat kolikrát chceš, bez jakékoliv možnosti kolize. |
||
ah01 Profil |
#15 · Zasláno: 24. 8. 2008, 23:36:20
mark
document.write("<div style='position: relative; top: " + premenna+ "px;'>"); |
||
los Profil * |
#16 · Zasláno: 25. 8. 2008, 00:08:35
> V krajním případě může nastat situace, že se ve frontě nahromadí třeba 3 události od setInterval, které se pak zpracují ihned za sebou
Obsluha jedného časovača nastaveného pomocou setInterval sa nehromadí vo fronte. V prípade, že sa obsluha nestihne vykonať v danom intervale, preskočí sa. |
||
mark Profil |
#17 · Zasláno: 25. 8. 2008, 20:44:17
ďakujem...:)
|
||
Časová prodleva: 16 let
|
0