【问题标题】:AS3 Mouse Over Change ImageAS3 鼠标悬停更改图像
【发布时间】:2012-05-10 21:40:48
【问题描述】:

目前我正在尝试使用 mouseover 事件更改加载到 sprite 中的图像,并使用 mouseout 将其更改回来。但它不能正常工作,我错过了什么吗?

public class Tab extends Sprite
{
    var imageLoader:Loader = new Loader();
    var TabSprite:Sprite = new Sprite();
    var SkinImages:Array = [Skin.TAB_ACTIVE,Skin.TAB_DISABLED,Skin.TAB_HOVER,Skin.TAB_VIEW];

    public function Tab()
    {   
        for each (var Image:String in SkinImages){
            imageLoader.load(new URLRequest(Image));
        }

        TabSprite.buttonMode = true;
        addChild(TabSprite);

        TabSprite.addChild(imageLoader);
        TabSprite.addEventListener(MouseEvent.MOUSE_OVER, onTabHover);
    }


    private function onTabHover(e:MouseEvent){
        trace("HOVER");
        TabSprite.removeEventListener(MouseEvent.MOUSE_OVER, onTabHover);
        imageLoader.load(new URLRequest(Skin.TAB_HOVER));
        imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
            TabSprite.addEventListener(MouseEvent.MOUSE_OUT, onTabOut);
        });

    }

    private function onTabOut(e:MouseEvent){
        trace("OUT");
        TabSprite.removeEventListener(MouseEvent.MOUSE_OUT, onTabOut);
        imageLoader.load(new URLRequest(Skin.TAB_VIEW));
        imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
            TabSprite.addEventListener(MouseEvent.MOUSE_OVER, onTabHover);
        });

    }
}

【问题讨论】:

  • 我认为你真的应该预先加载两个图像并切换每个图像的可见性。此外,您似乎没有将加载的图像添加到精灵中。
  • 关于切换可见性(而不是切换子级)的注意事项,如果两个对象具有相同(显示)的父级,并且可见性不同,则父级尺寸将受到不可见子级的影响。只要两个孩子的大小相同,这不是问题,但如果他们不这样做,这可能会导致许多父精灵定位的“wtf”时刻。这就是为什么在我的回答中我使用 addChild 和 removeChild 而不是切换“可见”参数。它不会创建隐藏的依赖项。

标签: actionscript-3 flash actionscript mouseover


【解决方案1】:

你不应该这样嵌套监听器。只需在构造函数中添加两个:

TabSprite.addEventListener(MouseEvent.ROLL_OVER, onTabHover);
TabSprite.addEventListener(MouseEvent.ROLL_OUT, onTabOut);

注意将 MOUSE_OVER 更改为 ROLL_OVER 在大多数情况下会更好。您也不应该在每次鼠标事件时都加载图像。预加载它们,然后使用。在侦听器中使用匿名函数也是不好的做法,因为您无法删除该侦听器:

imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
        TabSprite.addEventListener(MouseEvent.MOUSE_OUT, onTabOut);
    });

事实上你并没有移除它——这很糟糕。

    for each (var Image:String in SkinImages){
        imageLoader.load(new URLRequest(Image));
    }

我怀疑它是否有效,我认为您不能使用一个加载器一次加载多个图像。

试试这个:

public class Tab extends Sprite
{
var imageOverLoader:Loader = new Loader();
var imageOutLoader:Loader = new Loader();
var TabSprite:Sprite = new Sprite();
var SkinImages:Array = Skin.TAB_ACTIVE,Skin.TAB_DISABLED,Skin.TAB_HOVER,Skin.TAB_VIEW];

public function Tab()
{   

    TabSprite.buttonMode = true;
    this.addChild(TabSprite); // you also need to add as a Child "Tab" object in the Main Class

    imageOutLoader.load(new URLRequest(Skin.TAB_VIEW));
    imageOverLoader.load(new URLRequest(Skin.TAB_HOVER));
    TabSprite.addChild(imageOutLoader);

    TabSprite.addEventListener(MouseEvent.ROLL_OVER, onTabHover);
    TabSprite.addEventListener(MouseEvent.ROLL_OUT, onTabOut);
}


private function onTabHover(e:MouseEvent){
    TabSprite.removeChild(imageOutLoader);
    TabSprite.addChild(imageOverLoader);

    trace("HOVER");

}

private function onTabOut(e:MouseEvent){
    TabSprite.removeChild(imageOverLoader);
    TabSprite.addChild(imageOutLoader);

    trace("OUT");

}
}

试试这个。

【讨论】:

  • 我不同意。当您只在知道自己结束时才倾听时,您会减少很多意外行为,反之亦然。
  • 我再次不同意你的观点。每当您更新代码并更改任何侦听器时,如果您将侦听器声明在代码中的分组位置(例如构造函数),则只需在一处更改侦听器。如果您忘记在一个地方更新您的代码,您会收到很多错误(= 意外行为)。将你的听众分组仍然是最好的,你不应该经常删除他们。
  • 我认为 Łukasz Zaroda 指的是一个特定事件侦听器的侦听器方法包含创建另一个事件侦听器的事实,而不是拥有一个函数名称然后在其中创建它。这是不好的做法,因为它可能会影响垃圾收集。
  • 我会说,与听众混在一起可能很好,但前提是你要拥有大量的听众,所以如果你能以代码透明度为代价将它们减少一半,这很棒。但我认为在大多数情况下,尤其是对于初学者来说,它会让代码变得太不干净。您最终可以在开发结束时优化该问题的代码,但在开发阶段这将是一种痛苦......我承认,我应该在答案中澄清这一点。影响垃圾收集也很有趣,但我对那个话题一无所知。
  • 非常感谢您的帮助,非常感谢。
猜你喜欢
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多