Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[JavaScript] Object met setInterval reageert niet op event

Pagina: 1
Acties:
  • 402 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hoi tweakers,

Hoewel ik mij altijd verre van javascript animaties heb gehouden heb ik onlangs
fade scriptje geschreven dat een HTML element geheel of gedeeltelijk kan laten
infaden of outfaden (zie hieronder).

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 /* 
 * Usage: var myFade = new Fade(“MyElementId”,{from:0,to:1},5)
 * @param {String} el Reference to the element that will be faded
 * @param {Object} opacity (Optional, defaults to {from:0,to:1})The opacity start and end opacity levels 
 * @param {Number} duration (Optional, defaults to 1)The number of seconds that the animation should last
 */

function Fade(el,opacity,duration){
  if(!el){return;};
  this.init(el,opacity,duration);
}
Fade.prototype={
  init:function(el,opacity,duration){
    this.element = document.getElementById(el);
    if(!this.element){return;}
    if(opacity){
      this.opacityFrom = (opacity.from || opacity.from == 0)?opacity.from:0;
      this.opacityTo = (opacity.to || opacity.to == 0)?opacity.to:1;
    } else {
      this.opacityFrom = 0;
      this.opacityTo = 1;
    }
    this.opacityCurrent = this.opacityFrom;
    this.duration = (duration)?duration:1;
    this.interval = Math.abs((this.duration*1000)/((this.opacityTo - this.opacityFrom)/0.01));
    this.fadeMode = (this.opacityFrom<this.opacityTo)?"in":"out";
  },
  fire:function(){
    this.startFade();
  },
  startFade:function(){
    var _self = this;
    this.timer = setInterval(function(){_self.run()},this.interval);
  }, 
  run:function(){
    if(this.fadeMode == "in"){
      if(this.opacityCurrent <= this.opacityTo){
        this.setElementOpacity(this.element,this.opacityCurrent);
        this.opacityCurrent = this.opacityCurrent + 0.01;
      } else {
        this.timer = clearInterval(this.timer);
      }
    }else{
      if(this.opacityCurrent >= this.opacityTo){
        this.setElementOpacity(this.element,this.opacityCurrent);
        this.opacityCurrent = this.opacityCurrent - 0.01;
      } else {
        this.timer = clearInterval(this.timer);
      }
    }
  },
  setElementOpacity:function(element,value){
    if(!this.element){
      throw Error.argumentNull('element');
    }
    if(element.filters){
      var filters = element.filters;
      var createFilter = true;
      if(filters.length !== 0){
        var alphaFilter = filters['DXImageTransform.Microsoft.Alpha'];
        if(alphaFilter){
          createFilter = false;
          alphaFilter.opacity = value * 100;
        }
      }
      if (createFilter){
        element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='  + (value * 100) + ')';
      }
    }
    else {
      element.style.opacity = value;
    }
  }
};


Het eerste probleem waar ik tegen aanliep was het gebruik van setInterval en het gebruik van this. Mede dankzij jullie heb ik hiervoor een oplossing gevonden (zie function startFade op regel 31-34).

Nu wil het volgende. Wanneer ik een instance van deze class maak en de method startFade aanroep dan gaat alles goed. Zie hieronder:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style>
#overLay{
    position:absolute;
    top:0px;
    left:0px;
    width:100%;
    height:100%;
    background-color:black;
}
</style>
<body>
  <div id="overLay"> </div>
  <script type="text/javascript">
    var fade = new Fade("overLay",{from:1,to:0},2);
    fade.startFade();
  </script>
</body>
</html>


Fijn dat dat werkt maar ik wil de animatie aanroepen bij een event. Zoals hieronder werkt het dus niet!!!

code:
1
2
3
4
5
6
7
<div id="overLay"></div>
<button id="knop">klik hier!</button
<script type="text/javascript">
  var fade = new Fade("overLay",{from:1,to:0},2);
  var el = document.getElementById("knop");
  DOMhelp.addEvent(el,'click',fade.startFade, false);
</script>


Ik snap niet waaorm, maar vermoed dat het te maken heeft met de setInterval aanroep in startFade.

Het werkt wel als ik function(){fade.startFade()} gebruik bij de addEvent. Dat begrijp ik niet.
Het lijkt er op alsof de fade.startFade met de haakjes () aangeroepen MOET worden, maar waarom?

code:
1
2
3
4
5
6
7
<div id="overLay"></div>
<button id="knop">klik hier!</button
<script type="text/javascript">
  var fade = new Fade("overLay",{from:1,to:0},2);
  var el = document.getElementById("knop");
  DOMhelp.addEvent(el,'click',function(){fade.startFade()}, false);
</script>


Hoewel de laatste genoemde methode dus werkt, vind ik het niet erg wenseljik omdat
deze het allemaal minder bruikbaar maakt voor iemand dit dit script niet zelf heeft geschreven.

Heeft er iemand een idee waarom de ene aanroep wel werkt en de andere niet?

Verwijderd

Dat er haakjes gebruikt moeten worden lijkt mij juist wel duidelijk, het gaat er immers om dat je wilt dat de functie ook daadwerkelijk word uitgevoerd. Wat ik eigenlijk niet zo goed begrijp is dat dit:
code:
1
DOMhelp.addEvent(el,'click',fade.startFade(), false);
niet werkt en aangeeft dat _self.run() op regel 33 geen object is... dus dat this niet verwijst naar je ge-protypede object... heb ook al lopen klooien met Fade.run() op die regel maar dat pikt ie ook niet omdat Fade binnen die prototype niet bestaat... Wellicht dat je je object kunt herschrijven naar een wellicht "eenvoudiger" format... begin anders hier: http://blog.phpbuero.de/ te lezen bij: The “Module Pattern” Vol. I - Singletons en dan de rest van de artikelen...

[ Voor 0% gewijzigd door Verwijderd op 10-01-2008 22:56 . Reden: quotes om 'eenvoudiger'... zo makkelijk is het n.l. niet :p ]


Verwijderd

Topicstarter
DOMhelp is gewoon verzameling functies die handig zijn bij het scripten en rekening houden met verschillende browsers en implementaties.

Thnx voor de link, ik ga eens kijken of ik er wat van kan leren..

Ik heb voorlopig nog maar even geaccepteerd dat ik een event als volgt moet koppelen:
code:
1
DOMhelp.addEvent(el,'click',function(){fade.startFade()}, false);


DOMhelp.addEvent ziet er als volgt uit
code:
1
2
3
4
5
6
7
8
9
10
11
addEvent: function(elm, evType, fn, useCapture){
        if (elm.addEventListener){
            elm.addEventListener(evType, fn, useCapture);
            return true;
        } else if (elm.attachEvent) {
            var r = elm.attachEvent('on' + evType, fn);
            return r;
        } else {
            elm['on' + evType] = fn;
        }
    },

Verwijderd

Het verschil is dit:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
// nu assign je de methode direct als event handler aan el
// deze zal dan ook in de context van el worden uitgevoerd (this=el)
// vandaar dat je de error van _self.run krijgt
DOMhelp.addEvent(el,'click',fade.startFade, false);

// nu voer je de methode al uit (wel in de goede context)
// en assign je de returnvalue als event handler (onzin dus)
DOMhelp.addEvent(el,'click',fade.startFade(), false);

// dit is voor jou de enige goed manier: je assignt een (anonymous) function
// en in die function roep je de methode aan in de goede context.
DOMhelp.addEvent(el,'click',function() { fade.startFade() }, false);

Verwijderd

Topicstarter
verhelderend

thnx