문제

나는 플래시 라이브러리와 함께 스프라이트 기호로 구성되어의 다른 스프라이트와 디자인 시 적용되는 필터입니다.나는 포함 그 상징으로 플렉스 같은 응용 프로그램 그래서:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            [Bindable]
            [Embed(source="Resources.swf", symbol="SquareContainer")]
            private var squareContainer_class:Class;

            private function log(msg:String):void {
                    output.text = output.text + "\n" + msg;
            }
        ]]>
    </mx:Script>

    <mx:VBox horizontalAlign="center" width="100%" height="100%" >
        <mx:Image id="squareContainer" source="{squareContainer_class}"/>
        <mx:Button click="log(squareContainer.width + ', ' + squareContainer.height);"/>
        <mx:TextArea id="output" width="100%" height="100%" />
    </mx:VBox>

</mx:Application>

이 예제에서 SquareContainer 상징은 100px 폭 100px height;그러나 그것은 포함 아이 sprite 으로 빛과 흐림 여과기,그 원인 스프라이트를 표시하는 것보다 훨씬 큰 100x100.이후 나는 알 수 없습에 대한 특정 구성의 컨테이너를 사용할 수 없는 비트맵 이미지 generateFilterRect()에서 얻을 수있는 필터를 적용하여 중첩 sprites.

를 얻을 수 있는 방법은 크기의 스프라이트 플러스 필터가?

도움이 되었습니까?

해결책

오 달콤한 성공! (그리고 팁에 감사합니다) 친구가 중첩 스프라이트에 존재할 수있는 필터를 처리하기 위해 멋진 재귀 기능으로 문제를 해결하는 데 도움을주었습니다.

private function getDisplayObjectRectangle(container:DisplayObjectContainer, processFilters:Boolean):Rectangle {
    var final_rectangle:Rectangle = processDisplayObjectContainer(container, processFilters);

    // translate to local
    var local_point:Point = container.globalToLocal(new Point(final_rectangle.x, final_rectangle.y));
    final_rectangle = new Rectangle(local_point.x, local_point.y, final_rectangle.width, final_rectangle.height);       

    return final_rectangle;
}

private function processDisplayObjectContainer(container:DisplayObjectContainer, processFilters:Boolean):Rectangle {
    var result_rectangle:Rectangle = null;

    // Process if container exists
    if (container != null) {
        var index:int = 0;
        var displayObject:DisplayObject;

        // Process each child DisplayObject
        for(var childIndex:int = 0; childIndex < container.numChildren; childIndex++){
            displayObject = container.getChildAt(childIndex);

            //If we are recursing all children, we also get the rectangle of children within these children.
            if (displayObject is DisplayObjectContainer) {

                // Let's drill into the structure till we find the deepest DisplayObject
                var displayObject_rectangle:Rectangle = processDisplayObjectContainer(displayObject as DisplayObjectContainer, processFilters);

                // Now, stepping out, uniting the result creates a rectangle that surrounds siblings
                if (result_rectangle == null) { 
                    result_rectangle = displayObject_rectangle.clone(); 
                } else {
                    result_rectangle = result_rectangle.union(displayObject_rectangle);
                }                       
            }                       
        }

        // Get bounds of current container, at this point we're stepping out of the nested DisplayObjects
        var container_rectangle:Rectangle = container.getBounds(container.stage);

        if (result_rectangle == null) { 
            result_rectangle = container_rectangle.clone(); 
        } else {
            result_rectangle = result_rectangle.union(container_rectangle);
        }


        // Include all filters if requested and they exist
        if ((processFilters == true) && (container.filters.length > 0)) {
            var filterGenerater_rectangle:Rectangle = new Rectangle(0,0,result_rectangle.width, result_rectangle.height);
            var bmd:BitmapData = new BitmapData(result_rectangle.width, result_rectangle.height, true, 0x00000000);

            var filter_minimumX:Number = 0;
            var filter_minimumY:Number = 0;

            var filtersLength:int = container.filters.length;
            for (var filtersIndex:int = 0; filtersIndex < filtersLength; filtersIndex++) {                      
                var filter:BitmapFilter = container.filters[filtersIndex];

                var filter_rectangle:Rectangle = bmd.generateFilterRect(filterGenerater_rectangle, filter);

                filter_minimumX = filter_minimumX + filter_rectangle.x;
                filter_minimumY = filter_minimumY + filter_rectangle.y;

                filterGenerater_rectangle = filter_rectangle.clone();
                filterGenerater_rectangle.x = 0;
                filterGenerater_rectangle.y = 0;

                bmd = new BitmapData(filterGenerater_rectangle.width, filterGenerater_rectangle.height, true, 0x00000000);                      
            }

            // Reposition filter_rectangle back to global coordinates
            filter_rectangle.x = result_rectangle.x + filter_minimumX;
            filter_rectangle.y = result_rectangle.y + filter_minimumY;

            result_rectangle = filter_rectangle.clone();
        }               
    } else {
        throw new Error("No displayobject was passed as an argument");
    }

    return result_rectangle;
}

다른 팁

이 방법은 일반 100x100 제곱을 반환하기 때문에 GetBounds 또는 GetRect의 일반적인 방법을 사용하여 이것이 가능하지는 않습니다.

몇 가지 제안이 있습니다.

먼저 필터를 동적으로 적용 할 수 있습니다. 이렇게하면 필터의 숫자를 갖고 실제 크기가 무엇인지를 해결하기 위해 프로그래밍 방식으로 수학을 할 수 있습니다.

FLA의 Movieclip에 두 번째 레이어를 추가 할 수 있습니다. FLA는 원래 정사각형의 크기와 모든 필터가 있습니다. 그런 다음이 정사각형의 알파를 0으로 설정하십시오

셋째, 당신은 정사각형 플러스가 들어있는 FLA에 PNG를 가질 수 있습니다.

개인적으로 필터 나 원래 정사각형이 변경되면 최소한의 유지 보수가 필요하기 때문에 중간 옵션을 사용합니다.

글쎄, 좋은 소식과 나쁜 소식이 있습니다. 나쁜 소식은 실제로이 "올바른 방법"을 수행하는 효과적인 방법이 없다는 것입니다. 좋은 소식은이를 근사화하는 적절한 방법이 있다는 것입니다.

일반적인 규칙은 너비의 크기는 대략 (filter.blurx * 1.5) + sprite.width 여기서 "필터"가 sprite.filters 어레이의 필터 인 것입니다. 블리 리와 높이에 대해서도 마찬가지입니다. 다른 일반적인 규칙은 최소 x가 sprite.x- (filter.blurx * 1.5) / 2가된다는 것입니다.

이 숫자 중 어느 것도 "Adobe Official"이 아니지만,이를 기반으로 비트 맵타타를 만들 수 있도록 합리적인 오류 마진 내에서의 작업은 없습니다.

여기에 약간 다른 방법:다만 전체 개체로 BitmapData 고 그 결정의 범위를 투명하지 않은 지역의 bitmap.이 접근해야 성능이 향상 특히,복잡한 물체.

package lup.utils
{
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    public class BoundsHelper
    {
        private var _hBmd:BitmapData;
        private var _hBmdRect:Rectangle;
        private var _hMtr:Matrix;
        private var _hPoint:Point;

        private var _xMin:Number;
        private var _xMax:Number;
        private var _yMin:Number;
        private var _yMax:Number;

        /**
         * Specify maxFilteredObjWidth and maxFilteredObjHeight to match the maximal possible size
         * of a filtered object. Performance of the helper is inversely proportional to the product
         * of these values.
         *
         * @param maxFilteredObjWidth Maximal width of a filtered object.
         * @param maxFilteredObjHeight Maximal height of a filtered object.
         */
        public function BoundsHelper(maxFilteredObjWidth:Number = 500, maxFilteredObjHeight:Number = 500) {
            _hMtr = new Matrix();
            _hPoint = new Point();
            _hBmd = new BitmapData(maxFilteredObjWidth, maxFilteredObjHeight, true, 0);
            _hBmdRect = new Rectangle(0, 0, maxFilteredObjWidth, maxFilteredObjHeight);
        }

        /**
         * Determines boundary rectangle of an object relative to the given coordinate space.
         *
         * @param obj The object which bounds are being determined.
         *
         * @param space The coordinate space relative to which the bounds should be represented.
         *        If you pass null or the object itself, then bounds will be represented
         *        relative to the (untransformed) object.
         *
         * @param dst Destination rectangle to store the result in. If you pass null,
         *        new rectangle will be created and returned. Otherwise the passed
         *        rectangle will be updated and returned.
         */
        public function getRealBounds(obj:DisplayObject, space:DisplayObject = null, dst:Rectangle = null):Rectangle {
            var tx:Number = (_hBmdRect.width  - obj.width ) / 2,
                ty:Number = (_hBmdRect.height - obj.height) / 2;

            // get transformation matrix that translates the object to the center of the bitmap
            _hMtr.identity();
            _hMtr.translate(tx, ty);

            // clear the bitmap, so it will contain only pixels with zero alpha channel
            _hBmd.fillRect(_hBmdRect, 0);
            // draw the object; it will be drawn untransformed, except for translation
            // caused by _hMtr matrix
            _hBmd.draw(obj, _hMtr);

            // get the area which encloses all pixels with nonzero alpha channel (i.e. our object)
            var bnd:Rectangle = dst ? dst : new Rectangle(),
                selfBnd:Rectangle = _hBmd.getColorBoundsRect(0xFF000000, 0x00000000, false);

            // transform the area to eliminate the effect of _hMtr transformation; now we've obtained
            // the bounds of the object in it's own coord. system (self bounds)
            selfBnd.offset(-tx, -ty);

            if (space && space !== obj) { // the dst coord space is different from the object's one
                // so we need to obtain transformation matrix from the object's coord space to the dst one
                var mObjToSpace:Matrix;

                if (space === obj.parent) {
                    // optimization
                    mObjToSpace = obj.transform.matrix;
                } else if (space == obj.stage) {
                    // optimization
                    mObjToSpace = obj.transform.concatenatedMatrix;
                } else {
                    // general case
                    var mStageToSpace:Matrix = space.transform.concatenatedMatrix; // space -> stage
                        mStageToSpace.invert();                                    // stage -> space
                    mObjToSpace = obj.transform.concatenatedMatrix;                // obj -> stage
                    mObjToSpace.concat(mStageToSpace);                             // obj -> space
                }

                // now we transform all four vertices of the boundary rectangle to the target space
                // and determine the bounds of this transformed shape

                _xMin =  Number.MAX_VALUE;
                _xMax = -Number.MAX_VALUE;
                _yMin =  Number.MAX_VALUE;
                _yMax = -Number.MAX_VALUE;

                expandBounds(mObjToSpace.transformPoint(getPoint(selfBnd.x, selfBnd.y)));
                expandBounds(mObjToSpace.transformPoint(getPoint(selfBnd.right, selfBnd.y)));
                expandBounds(mObjToSpace.transformPoint(getPoint(selfBnd.x, selfBnd.bottom)));
                expandBounds(mObjToSpace.transformPoint(getPoint(selfBnd.right, selfBnd.bottom)));

                bnd.x = _xMin;
                bnd.y = _yMin;
                bnd.width = _xMax - _xMin;
                bnd.height = _yMax - _yMin;
            } else {
                // the dst coord space is the object's one, so we simply return the self bounds
                bnd.x = selfBnd.x;
                bnd.y = selfBnd.y;
                bnd.width = selfBnd.width;
                bnd.height = selfBnd.height;
            }

            return bnd;
        }

        private function getPoint(x:Number, y:Number):Point {
            _hPoint.x = x;
            _hPoint.y = y;
            return _hPoint;
        }

        private function expandBounds(p:Point):void {
            if (p.x < _xMin) {
                _xMin = p.x;
            }
            if (p.x > _xMax) {
                _xMax = p.x;
            }
            if (p.y < _yMin) {
                _yMin = p.y;
            }
            if (p.y > _yMax) {
                _yMax = p.y;
            }
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top