将 beginBitmapFill 与现有的影片剪辑/形状一起使用? (动画 CC)

Posted

技术标签:

【中文标题】将 beginBitmapFill 与现有的影片剪辑/形状一起使用? (动画 CC)【英文标题】:Use beginBitmapFill with existing movieclip/shape? (Animate CC) 【发布时间】:2019-07-02 05:12:08 【问题描述】:

所有使用 beginBitmapFill 的教程似乎都以动态绘制对象为中心。是否可以简单地将位图填充应用于影片剪辑内的现有形状?我知道我可以通过在“颜色”面板中选择形状并选择位图来手动执行此操作。但是可以使用代码来执行此操作吗?这是我正在尝试的,它没有给出错误,但它也不起作用:

grl.tops.shapes.graphics.beginBitmapFill(new cubepattern(), null, true, false);

【问题讨论】:

大概,可能,但这不是一个简单的方法。您可以读取并(可能)计算出 Graphics 对象上已经存在的笔触形状,然后使用透明线条应用填充来复制它。一项艰巨的任务。 help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/… 最好使用蒙版在现有形状上绘制填充。否则是的,填充在readGraphicsData() 返回的列表中表示,您可能决定从两个源编译,一个是您想要填充的形状,另一个是您使用所需位图填充的形状,您从第一个获取路径元素从第二个来源获取并填充元素,然后构造一个新形状并将构造的列表提供给它的graphics.drawGraphicsData 您所尝试的只是将位图填充对象添加到该形状的图形数据的 end,所以如果您决定在该图形上绘制一些东西,然后调用 endFill()它会充满你的位图。否则是的,它只是未使用。 【参考方案1】:

正如其他人评论的那样,您可以分别使用 readGraphicsData 和 drawGraphicsData 。它甚至没有过于复杂。只需遍历所需形状的 IGraphicsData,找到 GraphicsBitmapFill 类的实例后立即停止,使用另一个 BitmapFill 创建一个新实例,最后将更改应用于原始形状。

嗯,一张照片值一千个字。 这是一个例子。这可能看起来有点长,但只有很多代码来准备形状并加载用作位图填充的图像。

关注 process() 函数。

package

    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.Graphics;
    import flash.display.Loader
    import flash.display.LoaderInfo;
    import flash.display.IGraphicsData;
    import flash.display.GraphicsBitmapFill;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.utils.getQualifiedClassName;

    public class Main extends Sprite
    
        private var bitmapData1:BitmapData;
        private var bitmapData2:BitmapData;
        private var masterSprite:Sprite = new Sprite();
        private var texturesLoaded:int = 0;
        private var loader:Loader = new Loader();

        public function Main():void
        
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        

        private function init(e:Event = null):void
        
            removeEventListener(Event.ADDED_TO_STAGE, init);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
            loader.load(new URLRequest("textureA.jpg"));
            addChild(masterSprite);
            masterSprite.x = masterSprite.y = 200;
        

        private function onComplete(event:Event):void
        
            switch (texturesLoaded)
            
                case 0: 
                    bitmapData1 = Bitmap(LoaderInfo(event.target).content).bitmapData;
                    loader.load(new URLRequest("textureB.jpg"));
                    break;
                case 1: 
                    bitmapData2 = Bitmap(LoaderInfo(event.target).content).bitmapData;
                    loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
                    drawStar();
                    process();
            
            texturesLoaded++;
        

        private function process():void
        
            var tempShape:Shape = Shape(masterSprite.getChildAt(0));

            var graphicsData:Vector.<IGraphicsData> = tempShape.graphics.readGraphicsData();
            for (var a:int = 0; a < graphicsData.length; a++)
            
                if (getQualifiedClassName(graphicsData[a]) == "flash.display::GraphicsBitmapFill")
                
                    var bitmapFill:GraphicsBitmapFill = new GraphicsBitmapFill(bitmapData2);
                    graphicsData[a] = bitmapFill; break;
                
            
            tempShape.graphics.drawGraphicsData(graphicsData);
        

        private function drawStar():void
        
            var angles:Array = new Array(0, 36, 72, 108, 144, 180, 216, 252, 288, 324, 360);
            var innerRadius:int = 40;
            var outerRadius:int = 80;
            var shape:Shape = new Shape();
            shape.graphics.beginBitmapFill(bitmapData1);
            shape.graphics.moveTo(0 + Math.cos(angles[a] * (Math.PI / 180)) * outerRadius, 0 + Math.sin(angles[a] * (Math.PI / 180)) * outerRadius);
            for (var a:int = 0; a < angles.length; a++)
            
                angles[a] -= 90;
                if (a % 2 == 0)
                
                    shape.graphics.lineTo(0 + Math.cos(angles[a] * (Math.PI / 180)) * outerRadius, 0 + Math.sin(angles[a] * (Math.PI / 180)) * outerRadius);
                
                else
                
                    shape.graphics.lineTo(0 + Math.cos(angles[a] * (Math.PI / 180)) * innerRadius, 0 + Math.sin(angles[a] * (Math.PI / 180)) * innerRadius);
                
            
            shape.graphics.endFill();
            masterSprite.addChild(shape);
        
    

【讨论】:

哇,谢谢!我正在尝试对此进行测试,但我对外部代码知之甚少。我已将其保存到 .as 文件中,然后在同一文件夹中创建了一个 .fla,并在“类”字段中添加了 as 的名称并调用 Main();那正确吗?现在我收到一个错误,文件的位置不是它在“主要”中所说的,我不知道.. 如果我不需要通过代码做这么多,只想复制movieclip“tops”的形状并用位图“cubepattern”填充它怎么办?我主要使用 process() 函数中的东西,对吧? 看起来您的 DisplayObject 不是形状。不幸的是,我只能猜测它到底是什么。您可以尝试 var tempShape:Sprite = Sprite(grl.tops.shapes); 或进行跟踪(grl.tops.shapes);并查看调试面板输出的类型。 实际上,代码正在循环遍历形状的 IGraphicsData,如果找到 BitmapFill 并替换它,则停止。也许它仍然没有通过正确的形状循环?在 if() 条件中放入 trace 语句,看看它是否在 for 循环中找到了 BitmapFill 甚至是 trace(graphicsData[a])。 是的,这需要从tempShape 中剥离现有的图形数据,因为drawGraphicsData() 不会替换形状上存在的整个图形数据集,而是添加到它的尾部,有效地重叠任何东西以前在那里。所以,在绘制新的图形数据集之前调用graphics.clear()就可以了。

以上是关于将 beginBitmapFill 与现有的影片剪辑/形状一起使用? (动画 CC)的主要内容,如果未能解决你的问题,请参考以下文章

尝试将 LowDB 与现有的 db.json 集成

如何将 asyncio 与现有的阻塞库一起使用?

将 vuejs 与现有的 html 一起使用

将附加扩展与现有的词法分析器相关联

将 grunt 与现有的 wordpress 实例一起使用

将 Grails 与现有的 Web 应用程序集成