Actionscript 3和动态遮罩

3

我有一个容器MovieClip,它作为内容区域需要被遮罩。当我在这个容器内使用Shape创建遮罩时,似乎无法与我在此处创建的其他容器内容进行交互,例如按钮等。

以下是我的代码(省略了所有导入等):

class MyContainer extends MovieClip
{
   protected var masker : Shape = null;
   protected var panel : MyPanel = null;

   public function MyContainer()
   {
      this.masker = new Shape();
      this.masker.graphics.clear();
      this.masker.graphics.beginFill( 0x00ff00 );
      this.masker.graphics.drawRect(0, 0, 1, 1);  // 1x1 pixel.
      this.masker.graphics.endFill();
      addChild( this.masker );

      this.panel = new MyPanel();  // has buttons and stuff.
      addChild( this.panel );

      this.mask = this.masker;
   }

   // called by it's parent when the stage is resized.
   public function resize( width : Number, height : Number ) : void
   {
      // set the mask to half the size of the stage.
      this.masker.width  = width  / 2;
      this.masker.height = height / 2;

      // set the panel to half the size of the stage.
      this.panel.resize( width / 2, height / 2);
   }
}

当我将遮罩(形状)添加到显示层级中时,我无法再与MyPanel中定义的任何按钮进行交互。然而,如果不将遮罩添加到显示层级中,则可以与MyPanel中的内容进行交互,但遮罩的大小/位置不正确。我猜想当遮罩未添加到显示层级中时,它位于影片的左上角(虽然我无法证明)。
如何让我的遮罩大小/位置正确,并让用户与MyPanel中的按钮进行交互?
2个回答

5
this.masker.mouseEnabled = false; //set on this.masker

那应该可以。现在它会在事件到达容器中的任何其他地方之前拦截它们。我不是100%确定,但我相信遮罩会位于容器顶部。另一个选项是在显示列表底部向MyContainer添加另一个遮罩子项,并将面板添加为其同级。但你仍然需要在被遮罩的sprite/mc上将mouseEnabled和mouseChildren设置为false。

package
{
    import flash.display.Shape;
    import flash.display.Sprite;

    public class MyContainer extends Sprite
    {
       protected var masker : Shape = null;
       protected var panel:MyPanel;

       public function MyContainer()
       {

          this.masker = new Shape();
          this.masker.graphics.clear();
          this.masker.graphics.beginFill( 0x00ff00 );
          this.masker.graphics.drawRect(0, 0, 1, 1);  // 1x1 pixel.
          this.masker.graphics.endFill();
          addChild( this.masker );

          this.panel = new MyPanel();
          this.addChild(panel);
          this.mask = this.masker;
       }

       // called by it's parent when the stage is resized.
       public function resize( width : Number, height : Number ) : void
       {
          // set the mask to half the size of the stage.
          this.masker.width  = width  / 2;
          this.masker.height = height / 2;

          // set the panel to half the size of the stage.
       }
    }
}

-

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;

    public class MyPanel extends Sprite
    {
        public function MyPanel()
        {
            this.graphics.beginFill(0xFF0000)
            this.graphics.drawRect(0,0,10,10);
            this.addEventListener(MouseEvent.MOUSE_OVER, this.handleMouseOver)
            this.addEventListener(MouseEvent.MOUSE_OUT, this.handleMouseOut)
        }

        public function handleMouseOver(event:Event):void
        {
            this.graphics.clear();
            this.graphics.beginFill(0x00FF00)
            this.graphics.drawRect(0,0,10,10);
        }

        public function handleMouseOut(event:Event):void
        {
            this.graphics.clear();
            this.graphics.beginFill(0xFF0000)
            this.graphics.drawRect(0,0,10,10);
        }
    }
}

但是masker是一个Shape,因此没有mouseEnabled属性。这就是我使用Shape而不是Sprite的原因。 - Luke
以上代码可以按预期与MyPanel进行交互。 - Joel Hooks
好的。我还没有解决,但我发现应用于容器的 Glow 滤镜在某种程度上影响了遮罩。从容器中删除 Glow 滤镜使其按照上述描述正常工作。然而,我无法复制上面的示例中的问题。如果我有更多发现,我会在这里评论。 - Luke
从文档中可以得知:"当将显示对象的cacheAsBitmap属性设置为true并将cacheAsBitmapMatrix属性设置为Matrix对象时,掩码和被掩码的显示对象必须是同一个缓存位图的一部分。"请注意,当应用任何过滤器时,cacheAsBitmap会自动变为true,因此在这种情况下也适用。 - Triynko
因此,如果显示对象已缓存,则遮罩必须是显示对象的子级。如果显示列表中显示对象的祖先已缓存,则遮罩必须是该祖先或其后代之一的子级。如果被遮罩对象的多个祖先都已缓存,则遮罩必须是在显示列表中最靠近被遮罩对象的缓存容器的后代。 - Triynko
显示剩余4条评论

1

我注意到的一件事是,如果遮罩是遮罩对象的子代,那么所有与鼠标相关的事件或交互的遮罩位置都会偏移,尽管在视觉上看起来一切正常。

例如,我有一个包含按钮的剪辑,并由其子代之一进行遮罩。结果只有一半的按钮可以被点击,如果我将剪辑向左移动一点,那么只有四分之一的按钮仍然可以被点击。

基本上,鼠标事件遮罩似乎相对于遮罩对象的父级定位,而视觉遮罩则不是这样。

您需要将遮罩移到父级剪辑中。以下是我的操作方法:

class MaskedObject extends MovieClip{
  public var maskClip:MovieClip;
  public var maskOrigin:Point

  public function MaskedObject (){
     maskOrigin = new Point(maskClip.x,maskClip.y);
     parent.addChild(maskClip);
     maskClip.x = maskOrigin.x + this.x;
     maskClip.y = maskOrigin.y + this.y;
     mask = maskClip;
  }

  override function set x(val:Number):void{
    super.x = val;
    maskClip.x = maskOrigin.x + this.x;
  }


  override function set y(val:Number):void{
    super.y = val;
    maskClip.y = maskOrigin.y + this.y;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接