如何在OpenLaszlo中创建一个比lz.timer类更精确的计时器,该类可以暂停和循环?

如何在OpenLaszlo中创建一个比lz.timer类更精确的计时器,该类可以暂停和循环?,openlaszlo,lzx,Openlaszlo,Lzx,OpenLaszlo中的lz.Timer类有时会延迟256ms,如何创建一个能够更准确地触发的类?我设计的以下OpenLaszlo定时器类将更准确地触发,并且还具有一个很好的循环功能,带有暂停和重置,以便于使用。此代码适用于OpenLaszlo 4.9.0 SWF10和DHTML运行时: <library> <!--- Class: <loopingtimer> Extends: <node> This class is a loop

OpenLaszlo中的lz.Timer类有时会延迟256ms,如何创建一个能够更准确地触发的类?

我设计的以下OpenLaszlo定时器类将更准确地触发,并且还具有一个很好的循环功能,带有暂停和重置,以便于使用。此代码适用于OpenLaszlo 4.9.0 SWF10和DHTML运行时:

<library>

  <!---
  Class: <loopingtimer>
  Extends: <node>

  This class is a looping timer that can be used to call a method to peform
  an action repeatedly after a specified number of milliseconds.

  Override the abstract method reactToTimeChange(theTime) to do something
  useful in your application, theTime will be the time elapsed since the
  timer's last firing, it will be close to the 'timer_resolution' set but
  will be off from about 47ms-78ms in FireFox 2 and 47ms-94ms in IE6
  (see note below for explanation).

  NOTE:

  This class originally used the LzTimer class but it was firing up to 256ms
  late, so this has been replaced with a setTimeout() method and embedded
  JavaScript which is more accurate, but still fires about 59ms late on
  average.

  For this reason the firing times of this class are approximate but will
  probably fire 47ms to 78ms (about 59ms) on average late. As a workaround
  for this problem the timer uses the system time to calculate how much time
  has actually elapsed since the last timer firing and passes the actual time
  elapsed ('theTime') in milliseconds to the abstract 'reactToTimeChange()'
  method.

  -->
  <class name="loopingtimer" extends="node">

    <switch>
      <when property="$as3">
        <passthrough>
          import flash.utils.setTimeout;
        </passthrough>
      </when>
    </switch>

    <!-- *** ATTRIBUTES *** -->

    <!-- Public Attributes -->

    <!---
    @param numnber timer_resolution: number of milliseconds between timer
    firings (default: 40ms)

    Note: OpenLaszlo seems to typically have a lower limit of 47-78
    milliseconds between firings, so setting below this may be useless.
    -->
    <attribute name="timer_resolution" type="number" value="40" />

    <!-- Private Attributes -->

    <!--- @keywords private -->
    <!---
    @param number formertime: used internally to calculate the number of
    elapsed milliseconds since playback was started
    -->
    <attribute name="formertime" type="number" value="0" />

    <!--- @keywords private -->
    <!---
    Used internally for tracking virtual current time in milliseconds
    for pause functionality.
    -->
    <attribute name="currenttime" type="number" value="0" />

    <!--- @keywords private -->
    <!--- @param string timer_state: 'PAUSED' | 'COUNTING' -->
    <attribute name="timer_state" type="string" value="PAUSED" />


    <!-- *** METHODS *** -->


    <!-- Public Methods -->


    <!--- @keywords abstract -->
    <!---
    ABSTRACT METHOD: overwrite to do something useful in your program

    @param number theTime: the time in milliseconds elapsed since playback
    was  started
    -->
    <method name="reactToTimeChange" args="theTime">
      if ($debug){
        Debug.write('WARNING: reactToTimeChange(): This is an abstract method that should be overridden to do something useful in your application');
        Debug.write('reactToTimeChange(): Time elapsed since last firing in milliseconds: '+theTime);
      }
    </method>

    <!--- Start Timer (Note: This will reset timer to 0) -->
    <method name="startTimer">
      this.setAttribute('timer_state', 'COUNTING');
      var now = new Date();
      var rawTime = now.getTime();
      this.setAttribute('formertime', rawTime);

      this.doForTime();
    </method>

    <!--- Pauses timer at current time -->
    <method name="pauseTimer">
      this.setAttribute('timer_state', 'PAUSED');
    </method>

    <!--- Resumes timer from time it is paused at -->
    <method name="unpauseTimer">
      this.setAttribute('timer_state', 'COUNTING');
      var now = new Date();
      var rawTime = now.getTime();
      this.setAttribute('formertime', rawTime-this.currenttime);
      this.repeat();
    </method>

    <!--- Stop Timer - stops timer and resets to 0  -->
    <method name="stopTimer">
      this.pauseTimer();
      this.resetTimer();
    </method>

    <!--- Resets Timer to 0 -->
    <method name="resetTimer">
      this.setAttribute('formertime', 0);
      this.setAttribute('currenttime', 0);
    </method>

    <!---
    Seeks to the given time in milliseconds.

    @param number(int) iTimeMs: the time to seek to
    -->
    <method name="seekToTime" args="iTimeMs">
      this.setAttribute('currenttime', Math.floor(iTimeMs));
    </method>

    <!-- Private Methods -->


    <!--- @keywords private -->
    <!---
    Called Internally By Timer

    @param number theTime: the actual time in milliseconds that has passed
    since the last timer firing (will usually be 16-100ms more than timer
    firing interval)
    -->
    <method name="doForTime">

      // Prevent Timer Incrementing When Paused
      if (this.timer_state == 'PAUSED')
        return;

      var now = new Date();

      var rawTime = now.getTime();

      if (this.formertime != 0)
        var currentTime = rawTime - this.formertime;

      this.setAttribute('currenttime', currentTime);

      // Call Abstract Method:
      this.reactToTimeChange(currentTime);

      this.repeat();

    </method>

    <!--- @keywords private -->
    <!---
    Used internally for timer looping.
    -->
    <method name="repeat">

      // This function uses an embedded JavaScript function which
      // can be called via the standard JavaScript setTimeout()
      // method which results in more accurate timer firing then the
      // standard OpenLaszlo LzTimer() class. LzTimer() fired up to
      // 256ms late, while setTimeout() usually fires from
      // only 47ms-78ms

      var f = function(){
        doForTime();
      }

      setTimeout(f, this.timer_resolution);
    </method>

  </class>

</library>

导入flash.utils.setTimeout;
如果($debug){
write('警告:reactToTimeChange():这是一个抽象方法,应该重写它,以便在应用程序中执行有用的操作');
write('reactToTimeChange():自上次触发以来经过的时间(毫秒):'+时间);
}
this.setAttribute('timer_state','COUNTING');
var now=新日期();
var rawTime=now.getTime();
this.setAttribute('formertime',rawTime);
这个。doForTime();
this.setAttribute('timer_state','PAUSED');
this.setAttribute('timer_state','COUNTING');
var now=新日期();
var rawTime=now.getTime();
this.setAttribute('formertime',rawTime this.currenttime);
这个。重复();
这是pauseTimer();
这是resetTimer();
此.setAttribute('formertime',0);
此.setAttribute('currenttime',0);
this.setAttribute('currenttime',Math.floor(ITIMES));
//暂停时防止计时器递增
如果(this.timer_state=='PAUSED')
返回;
var now=新日期();
var rawTime=now.getTime();
如果(this.formertime!=0)
var currentTime=rawTime-this.formertime;
此.setAttribute('currenttime',currenttime);
//调用抽象方法:
此。反应时间变化(currentTime);
这个。重复();
//此函数使用嵌入式JavaScript函数,该函数
//可以通过标准JavaScript setTimeout()调用
//方法,使计时器触发比
//标准OpenLaszlo LzTimer()类。LzTimer()激发到
//延迟256ms,而setTimeout()通常从
//只有47ms-78ms
var f=函数(){
doForTime();
}
setTimeout(f,这是计时器的分辨率);

我设计的以下OpenLaszlo定时器类将更精确地触发,并且具有良好的循环功能,具有暂停和重置功能,便于使用。此代码适用于OpenLaszlo 4.9.0 SWF10和DHTML运行时:

<library>

  <!---
  Class: <loopingtimer>
  Extends: <node>

  This class is a looping timer that can be used to call a method to peform
  an action repeatedly after a specified number of milliseconds.

  Override the abstract method reactToTimeChange(theTime) to do something
  useful in your application, theTime will be the time elapsed since the
  timer's last firing, it will be close to the 'timer_resolution' set but
  will be off from about 47ms-78ms in FireFox 2 and 47ms-94ms in IE6
  (see note below for explanation).

  NOTE:

  This class originally used the LzTimer class but it was firing up to 256ms
  late, so this has been replaced with a setTimeout() method and embedded
  JavaScript which is more accurate, but still fires about 59ms late on
  average.

  For this reason the firing times of this class are approximate but will
  probably fire 47ms to 78ms (about 59ms) on average late. As a workaround
  for this problem the timer uses the system time to calculate how much time
  has actually elapsed since the last timer firing and passes the actual time
  elapsed ('theTime') in milliseconds to the abstract 'reactToTimeChange()'
  method.

  -->
  <class name="loopingtimer" extends="node">

    <switch>
      <when property="$as3">
        <passthrough>
          import flash.utils.setTimeout;
        </passthrough>
      </when>
    </switch>

    <!-- *** ATTRIBUTES *** -->

    <!-- Public Attributes -->

    <!---
    @param numnber timer_resolution: number of milliseconds between timer
    firings (default: 40ms)

    Note: OpenLaszlo seems to typically have a lower limit of 47-78
    milliseconds between firings, so setting below this may be useless.
    -->
    <attribute name="timer_resolution" type="number" value="40" />

    <!-- Private Attributes -->

    <!--- @keywords private -->
    <!---
    @param number formertime: used internally to calculate the number of
    elapsed milliseconds since playback was started
    -->
    <attribute name="formertime" type="number" value="0" />

    <!--- @keywords private -->
    <!---
    Used internally for tracking virtual current time in milliseconds
    for pause functionality.
    -->
    <attribute name="currenttime" type="number" value="0" />

    <!--- @keywords private -->
    <!--- @param string timer_state: 'PAUSED' | 'COUNTING' -->
    <attribute name="timer_state" type="string" value="PAUSED" />


    <!-- *** METHODS *** -->


    <!-- Public Methods -->


    <!--- @keywords abstract -->
    <!---
    ABSTRACT METHOD: overwrite to do something useful in your program

    @param number theTime: the time in milliseconds elapsed since playback
    was  started
    -->
    <method name="reactToTimeChange" args="theTime">
      if ($debug){
        Debug.write('WARNING: reactToTimeChange(): This is an abstract method that should be overridden to do something useful in your application');
        Debug.write('reactToTimeChange(): Time elapsed since last firing in milliseconds: '+theTime);
      }
    </method>

    <!--- Start Timer (Note: This will reset timer to 0) -->
    <method name="startTimer">
      this.setAttribute('timer_state', 'COUNTING');
      var now = new Date();
      var rawTime = now.getTime();
      this.setAttribute('formertime', rawTime);

      this.doForTime();
    </method>

    <!--- Pauses timer at current time -->
    <method name="pauseTimer">
      this.setAttribute('timer_state', 'PAUSED');
    </method>

    <!--- Resumes timer from time it is paused at -->
    <method name="unpauseTimer">
      this.setAttribute('timer_state', 'COUNTING');
      var now = new Date();
      var rawTime = now.getTime();
      this.setAttribute('formertime', rawTime-this.currenttime);
      this.repeat();
    </method>

    <!--- Stop Timer - stops timer and resets to 0  -->
    <method name="stopTimer">
      this.pauseTimer();
      this.resetTimer();
    </method>

    <!--- Resets Timer to 0 -->
    <method name="resetTimer">
      this.setAttribute('formertime', 0);
      this.setAttribute('currenttime', 0);
    </method>

    <!---
    Seeks to the given time in milliseconds.

    @param number(int) iTimeMs: the time to seek to
    -->
    <method name="seekToTime" args="iTimeMs">
      this.setAttribute('currenttime', Math.floor(iTimeMs));
    </method>

    <!-- Private Methods -->


    <!--- @keywords private -->
    <!---
    Called Internally By Timer

    @param number theTime: the actual time in milliseconds that has passed
    since the last timer firing (will usually be 16-100ms more than timer
    firing interval)
    -->
    <method name="doForTime">

      // Prevent Timer Incrementing When Paused
      if (this.timer_state == 'PAUSED')
        return;

      var now = new Date();

      var rawTime = now.getTime();

      if (this.formertime != 0)
        var currentTime = rawTime - this.formertime;

      this.setAttribute('currenttime', currentTime);

      // Call Abstract Method:
      this.reactToTimeChange(currentTime);

      this.repeat();

    </method>

    <!--- @keywords private -->
    <!---
    Used internally for timer looping.
    -->
    <method name="repeat">

      // This function uses an embedded JavaScript function which
      // can be called via the standard JavaScript setTimeout()
      // method which results in more accurate timer firing then the
      // standard OpenLaszlo LzTimer() class. LzTimer() fired up to
      // 256ms late, while setTimeout() usually fires from
      // only 47ms-78ms

      var f = function(){
        doForTime();
      }

      setTimeout(f, this.timer_resolution);
    </method>

  </class>

</library>

导入flash.utils.setTimeout;
如果($debug){
write('警告:reactToTimeChange():这是一个抽象方法,应该重写它,以便在应用程序中执行有用的操作');
write('reactToTimeChange():自上次触发以来经过的时间(毫秒):'+时间);
}
this.setAttribute('timer_state','COUNTING');
var now=新日期();
var rawTime=now.getTime();
this.setAttribute('formertime',rawTime);
这个。doForTime();
this.setAttribute('timer_state','PAUSED');
this.setAttribute('timer_state','COUNTING');
var now=新日期();
var rawTime=now.getTime();
this.setAttribute('formertime',rawTime this.currenttime);
这个。重复();
这是pauseTimer();
这是resetTimer();
此.setAttribute('formertime',0);
此.setAttribute('currenttime',0);
this.setAttribute('currenttime',Math.floor(ITIMES));
//暂停时防止计时器递增
如果(this.timer_state=='PAUSED')
返回;
var now=新日期();
var rawTime=now.getTime();
如果(this.formertime!=0)
var currentTime=rawTime-this.formertime;
此.setAttribute('currenttime',currenttime);
//调用抽象方法:
此。反应时间变化(currentTime);
这个。重复();
//此函数使用嵌入式JavaScript函数,该函数
//可以通过标准JavaScript setTimeout()调用
//方法,使计时器触发比
//标准OpenLaszlo LzTimer()类。LzTimer()激发到
//延迟256ms,而setTimeout()通常从
//只有47ms-78ms
var f=函数(){
doForTime();
}
setTimeout(f,这是计时器的分辨率);

两个运行时都是这样吗?我认为SWF和DHTML的行为应该有所不同,在DHTML中,它应该取决于特定于浏览器的实现。该类的原始版本是在OpenLaszlo 4.x发布之前在OpenLaszlo 3.3.3中创建的,因此没有DHTML运行时对其进行测试,因此这些数字是在IE和Windows XP上的FireFox 2上以SWF模式测试的,你必须在今天更新的浏览器和操作系统上测试它,以更新今天的数字。当时IE对lz.timer的平均响应速度最差,为256ms,这两个运行时的平均响应速度是多少?我认为SWF和DHTML的行为应该有所不同,在DHTML中,它应该取决于特定于浏览器的实现。该类的原始版本是在OpenLaszlo 4.x发布之前在OpenLaszlo 3.3.3中创建的,因此没有DHTML运行时对其进行测试,因此这些数字是在IE和Windows XP上的FireFox 2上以SWF模式测试的,你必须在今天更新的浏览器和操作系统上测试它,以更新今天的数字。当时IE的平均响应率最差,为256