代码之家  ›  专栏  ›  技术社区  ›  bzlm

flash/actionscript:将显示对象“绘制到”另一个对象上

  •  -1
  • bzlm  · 技术社区  · 15 年前

    如何在ActionScript中正确地将一个向量对象绘制到另一个向量对象的特定位置,考虑到定位、透明度等?

    我的想法(如建议 here )使用 beginBitmapFill ()和 drawRect ()绘制位图副本(使用 BitmapData.draw (第页)一个movieclip到。 graphics 其他movieclip的属性,但这比我想象的要困难,主要是因为以下原因:

    1. 不保留透明度 :如果源movieclip是透明的,则目标图形将变为白色。我试过用 BlendMode 但是没有帮助。看起来白色像素实际上被复制到位图数据中。我一定错过了什么,但我不知道是什么。 问题似乎在于 BitmapData 构造函数错误:透明度不默认为 但是 . 所以如果你创建一个 new BitmapData(x, y, true) 透明度是保留的,否则不会。

    2. 定位 .如果源movieclip居中(中心位于(0,0),则在将其复制到位图数据时必须应用矩阵来移动它,否则位图将只包含源movieclip的右下角。弄清楚要移动多少是很棘手的,我认为这涉及到以某种方式获得边界。(如果源对象在画布中完全居中,则可以将其偏移一半的宽度和高度。)

    3. 起始位图填充 瓷砖 . 如果你不开始 画矩形 ()在(0,0)处,位图填充也不会从位图中的(0,0)开始。这意味着您必须根据要开始绘制的位置再次移动源位图。

    (还有其他一些东西,比如必须使用LineStyle(0,0,0),这样drawRect()就不会绘制边框等。)

    所有这些棘手的问题让我相信我走错了路。有更简单的方法吗?有没有图书馆可以帮助我?有人成功地做到了吗?也许我的画布不应该是精灵,而应该是位图?但是我不知道怎么用 lineTo ()等。

    情况是这样的 :我有一个sprite,我用它的.graphics绘制,使用lineto()等。现在我想在绘制时使用movieclip作为画笔(或将另一个movieclip的副本放在绘图表面上),使另一个movieclip成为第一个movieclip图形的一部分。我不能 addChild ()因为矢量图形不会与绘制的图形交互。


    编辑 : Theo 提供了一个运行良好的解决方案 除了 因为它不适用于 旋转和缩放 应用于绘制到图形表面上的DisplayObject。这是 Theo's solution :

    private function drawOntoGraphics(source : IBitmapDrawable, target : Graphics, position : Point = null) : void
    {
        position = position == null ? new Point() : position;
        var bounds : Rectangle = DisplayObject(source).getBounds(DisplayObject(source));
        var bitmapData : BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00000000);
        bitmapData.draw(source, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y), null, null, null, true);
        target.beginBitmapFill(bitmapData, new Matrix(1, 0, 0, 1, bounds.x + position.x, bounds.y + position.y));
        target.drawRect(bounds.x + position.x, bounds.y + position.y, bounds.width, bounds.height);
    }
    

    为了支持旋转和缩放,我假设必须修改以下内容:

    1. 这个 Matrix 用于 draw() 应该从源复制缩放和旋转 DisplayObject ?
    2. 这个 矩阵 用于 beginBitmapFill() 也应该复制这个缩放和旋转吗?或者可能会产生“双重”缩放和旋转?
    3. 这个 drawRect() 应修改坐标以匹配缩放和旋转的尺寸。 显示对象 ?这意味着什么 getBounds() 不准确吗?

    编辑 :这里是一个支持缩放和旋转的工作实现,由所有反馈生成:

    static function DrawOntoGraphics(source:MovieClip, target:Graphics, 
            position:Point = null):void {
        var sourceClass:Class = getDefinitionByName(getQualifiedClassName(source)) 
            as Class;   
        var sourceCopy:MovieClip = new sourceClass();
        sourceCopy.rotation = source.rotation;
        sourceCopy.scaleX = source.scaleX;
        sourceCopy.scaleY = source.scaleY;
        sourceCopy.graphics.clear();
        var placeholder:MovieClip = new MovieClip();
        placeholder.addChild(sourceCopy);
        if (!position) 
            position = new Point();
        var bounds:Rectangle = placeholder.getBounds(placeholder);
        var bitmapData:BitmapData = new BitmapData(bounds.width, bounds.height, 
            true, 0x00000000);
        var drawMatrix:Matrix = new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y);
        bitmapData.draw(placeholder, drawMatrix);           
        placeholder.removeChild(sourceCopy);
        var fillMatrix:Matrix = new Matrix(1, 0, 0, 1, bounds.x + position.x, 
            bounds.y + position.y);
        target.beginBitmapFill(bitmapData, fillMatrix);
        target.lineStyle(0, 0x00000000, 0);
        target.drawRect(bounds.x + position.x, bounds.y + position.y, 
            bounds.width, bounds.height);
        target.endFill();
    }
    

    有点关联,但不是那么热门的问题: How to put an image (say, PNG) on a graphics in Flex 3?

    3 回复  |  直到 10 年前
        1
  •  1
  •   Theo.T    15 年前

    使用display objects getbounds函数可以可靠地在绘制时转换坐标:

    private function drawOntoGraphics(source : IBitmapDrawable, target : Graphics, position : Point = null) : void
    {
            position = position == null ? new Point() : position;
    
            var bounds : Rectangle = DisplayObject(source).getBounds(DisplayObject(source));
            var bitmapData : BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00000000);
    
            bitmapData.draw(source, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y), null, null, null, true);
            target.beginBitmapFill(bitmapData, new Matrix(1, 0, 0, 1, bounds.x + position.x, bounds.y + position.y));
            target.drawRect(bounds.x + position.x, bounds.y + position.y, bounds.width, bounds.height);
    }
    

    除了你的评论…下面同样的方法使用 位图数据 而不是图形对象作为画布:

    private function drawOntoBitmapData(source : IBitmapDrawable, target : BitmapData, position : Point = null) : void
    {
        position = position == null ? new Point() : position;
        var bounds : Rectangle = DisplayObject(source).getBounds(DisplayObject(source));
        var bitmapData : BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00000000);
        bitmapData.draw(source, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y), null, null, null, true);
        target.draw(bitmapData, new Matrix(1, 0, 0, 1, bounds.x + position.x, bounds.y + position.y));
    }
    
        2
  •  2
  •   grapefrukt    15 年前

    我认为,你有几种方法来解决这个问题:

    • 使用“画布”形状的图形属性
      优点:又好又简单
      缺点:非常有限,特别是当你需要移除东西时,因为你需要重新绘制整个画布。

    • 使用位图和.draw()方法
      优点:又好又简单,你可以更容易地做重复的事情。
      缺点:基本上与前面的方法有相同的问题,删除任何内容都需要重新绘制。而且,由于它是位图,所以它不能扩展。

    • 使用sprite并将基元添加为子级
      优点:非常灵活。
      缺点:这允许您单独移动、缩放和删除对象。但是,它将比前两个选项稍微复杂一些。

    使用最后一种方法(如果你想用它做一些小事情的话,我建议你这样做)你的问题可以通过使用添加到你的“绘图”中的位图来解决,这些位图支持透明性(就像你已经发现的那样),并且比使用位图填充要简单一些(这有点难以纠正)。

    我有一个例子 using a bitmap to clone and draw other DisplayObjects 在我的博客上。这不完全是您想要的,但代码可能有一些用途,至少是draw方法的矩阵部分。

        3
  •  1
  •   srahosting    15 年前

    bzlm-你可以将起始x位置设置为常量,并将drawrect和matrix translate结合起来。

    var xPos:Number = 750;
    var matrix:Matrix = new Matrix();
    matrix.translate(xPos,0);
    mySprite.graphics.beginBitmapFill(myBitmap,matrix);
    mySprite.graphics.drawRect(xPos,yPos,imgWidth,imgHeight);