开发者

how to trace "depth" or stacking order of a display object?

How can you trace the "depth" or stacking order of a display object with AS3?

I'm trying to figure out开发者_如何学Go if my sprite is behind another sprite...


container.getChildIndex(displayObject);

but that will only tell you how deep it is, not necessarily if anything is in front of it.


Function comparing two DisplayObject instances to determine which one is at a higher "depth" on the display list:

private function higher(a:DisplayObject, b:DisplayObject):DisplayObject
{           
    // Parent chains
    var ac:Array = [a];
    var bc:Array = [b];

    // Pointers to individual nodes
    var an:DisplayObject = a.parent;
    var bn:DisplayObject = b.parent;

    while (an != null) {
        ac.push(an);

        an = an.parent;
    }

    while (bn != null) {
        bc.push(bn);

        bn = bn.parent;
    }

    var acl:int = ac.length;
    var bcl:int = bc.length;

    var n:int = Math.min(acl, bcl);
    var i:int = 0;

    for (; i < n; i++) {
        an = ac[acl - i - 1];
        bn = bc[bcl - i - 1];

        // First uncommon ancestor
        if (an != bn)
            break;
    }

    var ca:DisplayObjectContainer = an.parent;
    if (!ca)
        return null;

    if (ca.getChildIndex(an) > ca.getChildIndex(bn))
        return a;
    else
        return b;
}

Note: If one of the objects is not on the display list, the function returns null. You can change it to return the other object instead.

You can almost certainly optimize this, but this is a first cut.


Just a refactored version of Manish answer using vectors and which won't return weird result if you ever call higher(a,a.parent).

parents() may be used for other purpose too :

public function higher(a:DisplayObject, b:DisplayObject):DisplayObject
{
    var aParents:Vector.<DisplayObject> = parents(a);
    var bParents:Vector.<DisplayObject> = parents(b);
    var commonDepth:int = Math.min(aParents.length, bParents.length);
    for (var depth:int = 0; depth < commonDepth; depth++)
        if (aParents[depth] != bParents[depth])
            break;
    if (depth == 0 || depth == commonDepth)
        return null;
    var commonAncestor:DisplayObjectContainer = aParents[depth].parent;
    if (commonAncestor.getChildIndex(aParents[depth]) > commonAncestor.getChildIndex(bParents[depth]))
        return a;
    else
        return b;
}

private function parents(d:DisplayObject):Vector.<DisplayObject>
{
    var result:Vector.<DisplayObject> = new Vector.<DisplayObject>;
    while (d != null)
    {
        result.unshift(d);
        d = d.parent;
    }
    return result;
}


private function getDepth(clip:DisplayObject):uint
{
    var depth:uint = 0;
    var currentClip:DisplayObject = clip;
    while (currentClip.parent && currentClip.parent != this)
    {
        depth++;
        currentClip = currentClip.parent;
    }
    return depth;
}


container.getChildIndex(child) should do it, it returns the index of the child


This is a revised version of what jauboux did from a version Manish did.
Namely, adding a null return value from highestOf() when depths match.

/**
 * @param  ifDepthsMatchReturnObjectA
 * @return  Whichever DisplayObject is higher on the display list.
 *           Optionally returns `null` if they're at the same depth.
 */
public function highestOf(a:DisplayObject, b:DisplayObject, ifDepthsMatchReturnObjectA:Boolean = false):DisplayObject
{
    var aParents:Vector.<DisplayObject> = ancestorsOf(a);
    var bParents:Vector.<DisplayObject> = ancestorsOf(b);
    var commonDepth:int = Math.min(aParents.length, bParents.length);
    for (var depth:int = 0; depth < commonDepth; depth++)
        if (aParents[depth] != bParents[depth])
            break;
    if (depth == 0 || depth == commonDepth)
        return null;
    var commonAncestor:DisplayObjectContainer = aParents[depth].parent;
    var aDepthOnCommonAncestor:int = commonAncestor.getChildIndex(aParents[depth]);
    var bDepthOnCommonAncestor:int = commonAncestor.getChildIndex(bParents[depth]);
    if (aDepthOnCommonAncestor > bDepthOnCommonAncestor)
        return a;
    else if (aDepthOnCommonAncestor < bDepthOnCommonAncestor)
        return b;
    else
        return ifDepthsMatchReturnObjectA ? a : null;
}

/**
 * @return  Whether a is higher than b.
 */
public function isHigher(a:DisplayObject, b:DisplayObject):Boolean
{
    return highestOf(a, b) === a;
}

/**
 * @return  All ancestors of given display.
 */
private function ancestorsOf(display:DisplayObject):Vector.<DisplayObject>
{
    var result:Vector.<DisplayObject> = new Vector.<DisplayObject>;
    while (display != null)
    {
        result.unshift(display);
        display = display.parent;
    }
    return result;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜