• javascript与as3交互


    文章都是发布在github再转到这边的,这边格式可能会乱掉.博客地址:benqy.com

    写在前面的废话

    公司首页的flash广告,都是由第三方制作的,脚本和flash文件都是由各个广告公司独立制作,然后在我们页面引用.这样的方式肯定不靠谱,页面脚本非常的乱,因此现在想收回脚本控制权,采用的方式是要求广告公司做出的flash素材要按要求实现接口供js调用,并且实现类似事件的机制,在广告的各个状态切换时通知页面脚本.

    以前都没接触过flash,现在只好临阵磨枪,挑一些会用到的学习一下,顺便记下来.

    这篇主要讲讲js和as3之间如何交互,如何实现简单的类似事件的机制.

    模拟事件

    在as3中,无论是调用js的方法,还是暴露接口给js,都是用ExternalInterface这个api.
    暴露接口:ExternalInterface.addCallback(函数名, 函数)
    调用js方法:ExternalInterface.call(方法名, 参数)

    这里所说的模拟事件,就是在falsh素材的各个状态切换时,通知页面.如加载完毕时,触发onload事件,播放时触发onplay,停止时触发onstop等等.

    采用的方案,是在object标签里,添加自定义的属性供as3调用,属性名是flash定死的:flashvars,值的格式类似url里的参数部分,为用&分隔的键值对,如下:

    01

    在as3中,这样读取属性:

    flashvars= LoaderInfo( this.root.loaderInfo ).parameters;
    

    flashvars是一个object变量,定义如下:

    private var flashvars:Object;
    

    读取后,flashvars的值:

    Object {onload: "advnr70wyu5xncanvpwzzo0pory66", onplay: "advf4q8r99cfnryhn2tk2n3s48kf0", onstop: "adv7sgjk0529cd00q6ojuf537"}
    

    对象的key为事件名,值为事件处理函数名,所有事件处理函数都在window.flashCallback命名空间下,并且名字是随机生成的不可重复的guid.

    在as3里,我们判断是否支持调用js函数:

    ExternalInterface.available
    

    以onload事件为例,在素材加载完毕后,如果支持调用js函数,则触发onload事件:

    //素材加载完毕,调用onload
    private function onload():void { 
        if (ExternalInterface.available) {
            textField.text = 'onload';
            if(flashvars.onload){
                ExternalInterface.call("window.flashCallback." + flashvars.onload);
            }
        } 
    } 
    

    上面提到,函数名是随机生成的,类似jquery的$.ajax方法里的callback实现方式,以下是封装过的生成object标签的方法:

    //adv.flash.embed是封装过的生成object标签的方法
    asyncTest('flash标签自定义事件', function () {
      expect(3);
      document.body.appendChild(adv.flash.embed({
        id: 'flashGetSWF',
        source: 'test.swf',
        params: {
          onload: function () {
            this.play();
            ok(true);
          },
          onplay: function () {
            ok(true);
            this.stop();
          },
          onstop: function () {
            ok(true);
            start();
          }
        }
      }));
    });
    

    几个回调函数都是匿名函数,在生成标签之前,会给函数在window.flashCallback下分配一个随机名称.现在只是简单的实现单个事件处理函数的绑定,如果有需要支持多个,只要再做一些简单的封装即可.

    adv.flash.embed的实现要点:

    //遍历自定义参数
    adv.util.forEach(params, function (value, key) {
      var funcVar = value;
      if (adv.util.isFunction(value)) {
        //如果是函数,则生成一个随机的名称,并存储在flashCallback命名空间下
        funcVar = adv.util.guid();
        window.flashCallback[funcVar] = function() {
          var swfObj = adv.flash.getSWF(id);
          //this指向flash对象本身
          value.apply(swfObj, arguments);
        };
      }
      paramArr.push(key + '=' + funcVar);
    });
    

    执行结果:
    02

    暴露接口给js

    as3里,实现这个很简单,先上代码再说:

    public function test() { 
        flashvars= LoaderInfo( this.root.loaderInfo ).parameters;
        //此为调试用
        ExternalInterface.call("window.flashCallback.trace",flashvars);
        //加载素材
        textField.width=200;
        textField.height = 90;
        addChild(textField);
        //素材加载完毕,准备播放
        //暴露api给js
        if(ExternalInterface.available){
            ExternalInterface.addCallback("play", play);
            ExternalInterface.addCallback("stop", stop);
        }
        //触发onload
        onload();
    }
    
    //这个方法被调用时,开始播放
    private function play():Boolean {
        textField.text = 'play';
        if(flashvars.onplay){
            ExternalInterface.call("window.flashCallback." + flashvars.onplay);
        }
        return true;
    }
    
    //这个方法被调用时,停止播放
    private function stop():Boolean {
        textField.text = 'stop';
        if(flashvars.onstop){
            ExternalInterface.call("window.flashCallback." + flashvars.onstop,flashvars);
        }
        return true;
    } 
    

    这里定义了两个方法,play和stop,在构造函数(test)里,判断ExternalInterface是否可用,如果可用,就暴露出这两个方法:

    ExternalInterface.addCallback("play", play);
    ExternalInterface.addCallback("stop", stop);
    

    在js里调用:

    跨浏览器的获取flash对象引用方法

    ...
    getSWF:function(name) {
      if (navigator.appName.indexOf("Microsoft") != -1) {
        return window[name];
      } else {
        return document[name];
      }
    }
    ...
    

    暴露出的as3方法,会直接附加在object对象上,要注意的是,我们要等onload之后才去调用,保证falsh加载完毕:

    asyncTest('js调用flash方法', function () {
      expect(1);
      document.body.appendChild(adv.flash.embed({
        id: 'flashcallSWF',
        source: 'test.swf',
         300,
        height: 190,
        params: {
          onload: function () {
            var result = this.play();
            ok(result);
            start();
          }
        }
      }));
    });
    

    事件函数的this指向flash对象,所以这里不用再获取了

    执行结果:
    03

    完整的as3代码:

    package { 
        import flash.display.LoaderInfo;
        import flash.display.Sprite;
        import flash.external.ExternalInterface;
        import flash.text.TextField;
    
        public class test extends Sprite {
            private var flashvars:Object;
            //用textField文本的改变来代表广告播放的状态转变
            private var textField:TextField = new TextField(); 
            public function test() { 
                flashvars= LoaderInfo( this.root.loaderInfo ).parameters;
                //加载素材
                textField.width=200;
                textField.height = 90;
                addChild(textField);
                //素材加载完毕,准备播放
                //暴露api给js
                if(ExternalInterface.available){
                    ExternalInterface.addCallback("play", play);
                    ExternalInterface.addCallback("stop", stop);
                }
                //触发onload
                onload();
            }
    
            //这个方法被调用时,开始播放
            private function play():Boolean {
                textField.text = 'play';
                if(flashvars.onplay){
                    ExternalInterface.call("window.flashCallback." + flashvars.onplay);
                }
                return true;
            }
    
            //这个方法被调用时,停止播放
            private function stop():Boolean {
                textField.text = 'stop';
                if(flashvars.onstop){
                    ExternalInterface.call("window.flashCallback." + flashvars.onstop,flashvars);
                }
                return true;
            } 
    
            private function onload():void { 
                if (ExternalInterface.available) {
                    textField.text = 'onload';
                    if(flashvars.onload){
                        ExternalInterface.call("window.flashCallback." + flashvars.onload);
                    }
                } 
            } 
        }
    } 
  • 相关阅读:
    c/c++ 标准库 map multimap元素访问
    c/c++ 标准库 map set 删除
    c/c++ 标准库 map set 插入
    c/c++ 标准库 map set 大锅炖
    c/c++ 标准库 pair 介绍
    c/c++ 标准库 set 自定义关键字类型与比较函数
    c/c++ 标准库 插入迭代器 详解
    python基础-内置函数 isinstance() 与 issubclass()
    移动端事件(其他触摸事件)hammer.js
    移动端事件(touchstart+touchmove+touchend)
  • 原文地址:https://www.cnblogs.com/honghongming/p/3532607.html
Copyright © 2020-2023  润新知