Search code examples
flashanimated-gifopenlaszlolzx

Using animated GIFs in OpenLaszlo 5.0 in DHTML and SWF10/11 runtime


The Flash Player does not offer native support for animated GIF files. In the DHTML runtime, you can just use an animated GIF like any other image resource. But how can an image be used as a resource for a view in the SWF10 or SWF11 runtime?


Solution

  • Luckily there are a number of existing open source ActionScript libraries with support for playing and generating animated GIFs. We are going to use the as3gif project. We first have to compile the ActionScript source code of as3gif into an SWC library, which then can be used with OpenLaszlo. Download the ZIP file with version 0.6 of as3gif. Extract the ZIP file in your $LPS_HOME folder. You should have a subfolder "GIFPlayer 0.6".

    $LPS_HOME/GIFPlayer 0.6/

    Go into that folder, and use the Flex SDK compc command to compile the ActionScript classes into an SWC file. For OpenLaszlo 4.9 or 5.0 (as of September 2012), the compc command can be found in $LPS_HOME/WEB-INF/bin/compc. If you use the flex4.6 branch of OpenLaszlo, the path to the compc command is either WEB-INF/flexsdk/4.5.1/bin/compc for the SWF10 runtime, or WEB-INF/flexsdk/4.6.0/bin/compc for the SWF11 runtime.

    $LPS_HOME/WEB-INF/bin/compc -optimize=true -static-link-runtime-shared-libraries=true -source-path+=. -output=bin/as3gif_0.6.swc -include-classes org.bytearray.gif.decoder.GIFDecoder org.bytearray.gif.encoder.GIFEncoder org.bytearray.gif.encoder.LZWEncoder org.bytearray.gif.encoder.NeuQuant org.bytearray.gif.errors.FileTypeError org.bytearray.gif.events.FileTypeEvent org.bytearray.gif.events.FrameEvent org.bytearray.gif.events.GIFPlayerEvent org.bytearray.gif.events.TimeoutEvent org.bytearray.gif.frames.GIFFrame org.bytearray.gif.player.GIFPlayer

    After the compilation, you will find the generated SWC file in the subfolder bin:

    bin/as3gif_0.6.swc

    Copy the SWC file into your $LPS_HOME/WEB-INF/flexlib folder. The class which we are going to use to display an animated GIF is the org.bytearray.gif.player.GIFPlayer class.

    Here is an example of an OpenLaszlo class supporting GIFs in both runtimes:

    <canvas>
    <!-- Copyright (c) Raju Bitter / MIT license http://www.opensource.org/licenses/mit-license.php -->
    
      <class name="gifview" extends="view" width="200" height="200">
        <passthrough when="$as3">
          import flash.events.IOErrorEvent;
          import flash.net.URLRequest;
          import org.bytearray.gif.player.GIFPlayer;
          import org.bytearray.gif.events.GIFPlayerEvent;
        </passthrough>
        <attribute name="gifsrc" type="string" value="" />
        <attribute name="__gifplayer" type="object" value="null" />
        <handler name="oninit">
          if (this.gifsrc != '') {
             this.ongifsrc.sendEvent();
          }
        </handler>
        <handler name="ongifsrc">
          if ($dhtml) {
            this.setSource(this.gifsrc);
          } else {
        if (this.__player == null) {
              this.__player = new GIFPlayer();
              this.__player.addEventListener(GIFPlayerEvent.COMPLETE, onGIFLoadComplete);
              this.__player.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
            }
            this.__player.load(new URLRequest(this.gifsrc));
            this.getDisplayObject().addChild(this.__player);
          }
        </handler>
        <method name="onGIFLoadComplete" args="evt"><![CDATA[
          Debug.info("GIF loaded successfully!");
          Debug.info("Total frames: " + this.__player.totalFrames);
          for (var i=1; i <= this.__player.totalFrames; i++) {
            Debug.info("Delay for frame #" + i + ": " + this.__player.getDelay(i));
          }
        ]]></method>
        <method name="onIOError" args="evt">
          Debug.error("Error loading GIF!");
          Debug.inspect(evt);
        </method>
        <!-- Custom unload method -->
        <method name="unload">
           if ($dhtml) {
             super.unload();
           } else {
             this.getDisplayObject().removeChildAt(0);
             // Dispose image resources
         this.__player.dispose();
             this.setAttribute('__player', null);
           }
        </method>
        <method name="stopGIFAnim">
          if ($as3) {
            this.__player.stop();
            Debug.info("Stopped animation at frame " + this.__player.currentFrame);
          } else {
             Debug.warn("Not supported in this runtime");
          }
        </method>
        <method name="startGIFAnim">
          if ($as3) {
            this.__player.play();
          } else {
             Debug.warn("Not supported in this runtime");
          }
        </method>
      </class>
    
      <gifview x="100" y="10" id="gv" gifsrc="animated.gif" />
    
      <button text="Start anim" onclick="gv.startGIFAnim()" />
      <button y="50" text="Stop anim" onclick="gv.stopGIFAnim()" />
      <button y="100" text="Unload GIF" onclick="gv.unload()" />
      <button y="150" text="Load again" onclick="gv.setAttribute('gifsrc', 'animated.gif')" />
    
    </canvas>
    

    The ActionScript class supports starting and stopping animation, and gives you access to the delay for each frame of the GIF.

    OpenLaszlo application with an animated GIF loaded into the SWF11 runtime