【问题标题】:How to determine whether a given object is a mask如何确定给定对象是否为掩码
【发布时间】:2013-04-09 07:20:31
【问题描述】:

显然,按照 Adob​​e 的说法,被蒙版的对象和蒙版对象都包含“蒙版”属性。这会导致循环引用,从而阻止确定哪个是实际掩码,哪个是掩码。

例如...

var clip:MovieClip = new MovieClip();
clip.name = "clip";
addChild(clip);

var boundary:Shape = new Shape();
boundary.name = "boundary";
clip.addChild(boundary);

clip.mask = boundary;

trace(clip.mask.name); // outputs "boundary"
trace(clip.mask.mask.name); // outputs "clip"

我已经遍历了clipboundary 的属性,似乎没有任何独特之处可以将它们区分开来。我的第一个想法是强制删除boundary 中多余的“掩码”引用,但是,这也会将clip 中的mask 属性设置为空,从而移除掩码。

我的第二个想法是检查掩码的父关系。如果父对象与对象的掩码相同,则所讨论的对象本身就是掩码。

var a:Array = [clip, boundary];

for each (var item in a) {
    if (item.mask == item.parent) {
        trace(item.name + " is a mask");
    }
}

// outputs "boundary is a mask"

似乎可以工作,并且在检查了掩码上的API reference 之后,很明显,在缓存时,掩码将需要成为被掩码的子项,但是......它也是有效的有一个与被遮罩的深度相同的遮罩(当遮罩需要不与被遮罩的内容一起移动时,我会不时这样做)。

例如...

MainTimeline ¬
    0: clip ¬
        0: boundary

...也可以布局为...

MainTimeline ¬
    0: clip ¬
    1: boundary

所以,难题来了。有关如何解决此问题的任何想法?

【问题讨论】:

    标签: actionscript-3 mask


    【解决方案1】:

    很好的问题,以前没有遇到过。我不知道周期性参考。

    如果您的掩码是专门的掩码,我建议您将其纳入您的命名约定。例如称它为 clipMask 而不是边界。

    如 cmets 中所述,在 mask 在同一个显示列表上的情况下,您可以使用 getChildIndex() 来比较它们在父显示列表中的位置。

    通常在这种情况下,我会将遮罩叠加在另一个显示对象上。这显然没有强制执行,我不相信它对蒙版的视觉结果有任何影响。但是对于大型组来说,维护比命名约定更容易。

    显然还是不理想。

    【讨论】:

    • 这是一种解决方法,但不是理想的解决方案。这是针对具有许多程序员的大型项目的代码库。每个人的面具名称都不一样,所以它只会在某些时候起作用。 ://
    • 这里很可能没有理想的解决方案。
    • 在这种情况下更接近一步可能是使用parent.getChildIndex(clip)parent.getChildIndex(boundary) 并假设较高的索引是掩码。如果每个人都可以在显示列表中始终将口罩放在更高的位置上,那就行了。
    • 在研究掩码时发现:actionscript.org/forums/archive/index.php3/t-184762.html - 如果您的任何掩码是在 IDE 中创建的,这对您来说真的很重要。
    • 我查看了您分享的链接。我看到的两个解决方案都与将可见性确定为相交因素有关,但是,它们都没有提供哪个对象产生蒙版的实际答案。至少通过将交叉点光栅化为图像并测试白色的普遍性,您似乎可以通过将一个对象移动到另一个对象的另一侧并再次运行测试来结束测试。这将告诉您哪个对象与这些可见性维度匹配,但如果频繁使用可能会证明计算成本很高......
    【解决方案2】:

    到目前为止,我发现的“最佳”技巧是在对象上运行hitTestPoint(在确保它们在目标下方有东西可以击中之后)。面具似乎永远不会返回true 进行全像素命中测试。这似乎适用于我测试过的大多数基本情况:

    public function isMask(displayObject:DisplayObject):Boolean {
    
        // Make sure the display object is a Class which has Graphics available,
        // and is part of a mask / maskee pair.
        if ((displayObject is Shape || displayObject is Sprite) && displayObject.mask) {
    
            // Add a circle at the target object's origin.
            displayObject['graphics'].beginFill(0);
            displayObject['graphics'].drawCircle(0, 0, 10);
    
            var origin:Point = displayObject.localToGlobal(new Point());
            var maskLocal:Point = displayObject.mask.globalToLocal(origin);
    
            // Add a circle at the same relative position on the "mask".
            displayObject.mask['graphics'].beginFill(0);
            displayObject.mask['graphics'].drawCircle(maskLocal.x, maskLocal.y, 10);
    
            // No matter which is the actual mask, one circle will reveal the other,
            // so hit testing the origin point should return true.
            // However, it seems to return false if the object is actually a mask.
            var hit:Boolean = displayObject.hitTestPoint(origin.x, origin.y, true);
    
            displayObject['graphics'].clear();
            displayObject.mask['graphics'].clear();
    
            // Return true if the hit test failed.
            return !hit;
        } else {
            return false;
        }
    }
    

    显然你想要缓存 graphics 以防对象已经有一些,它可以做一些比转换为 Sprite 更优雅的东西,以便它可以处理 Shapes, 但它是一个开始。

    编辑: 访问['graphics'] 让它接受Shapes,但显然不是超级高效。我不确定最好的方法是什么,除了添加一个接口。

    【讨论】:

    • 您的解决方案很有趣,而且似乎确实有效,但是,我承认我不完全理解为什么它有效。奇怪的是,如果 hitTestPoint 在像素标志设置为 true 的蒙版对象上运行,它会失败,但前提是 beginFilldraw 操作在它之前。如果只是在指定的点进行测试,那么任何对象类型都是可行的。我可以理解 hitTestPoint 可以在可见对象上工作(不要与属性obj.visible 混淆,因为掩码和对象都保留一个真值),但是为什么它在非预draw 对象上失败让我感到困惑。
    • 如果我理解您的问题,graphics 调用只是为了确保有像素要命中,因此非掩码始终返回 !hit == false。如果您的对象恰好在 0,0 处不透明,您可以删除所有 graphics 调用,这将正确返回。虽然这是一个可怕的黑客,所以我只建议作为最后的手段!
    • 我添加了一些 cmets,因为我认为我没有很好地解释自己。希望他们能有所帮助!令人讨厌的是,这无法处理所有可能的掩码类(例如SimpleButton),但我不确定如果没有GraphicsaddChild,您如何确保它们在某处不透明。
    • 这是有道理的。感谢您的澄清。我得等到今晚回家再试试这个,但是;使用临时形状代理原始 DisplayObject、对其应用蒙版、运行 hitPointTest、还原蒙版并删除代理怎么样?理论上,这将为所有对象类型提供准确的掩码检查。
    • 嗯,可能有一些方法可以解决问题,但我现在无法完全理解它。您需要使蒙版对中的两个对象在同一位置不透明,以确保某些东西可见。
    猜你喜欢
    • 2022-01-02
    • 1970-01-01
    • 2020-08-31
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2012-02-13
    相关资源
    最近更新 更多