PDA

View Full Version : how to erase in Graphics drawing


freeman
11-02-2008, 06:34 PM
Hi I'm confused with this problem, I've done a lot of searching and couldn't find a solution. Please help me...

Basically what I want to do is to erase what I've drawn with the graphics object in Shape, without having to call clear(). For example, I have drawn a circle in the Shape, and now I want to erase the center part of the circle so that it becomes a ring.

I want to use this Shape as mask. I don't know how I can do the erasing correctly so the mask functions as I expected -- revealing the masked image only in the ring area, not the center part, and not the outside part.

Any help would be great..

wvxvw
11-02-2008, 08:47 PM
function ring(gfx:Graphics, raduis0:Number, raduis1:Number, color:uint):void
{
var c1:Number = raduis0 * (Math.SQRT2 - 1);
var c2:Number = raduis0 * Math.SQRT2 / 2;
var d:Number = raduis0 * 2;

var c3:Number = raduis1 * (Math.SQRT2 - 1);
var c4:Number = raduis1 * Math.SQRT2 / 2;
var d1:Number = raduis1 * 2;
var d2:Number = raduis0 - raduis1;

gfx.beginFill(color);
gfx.moveTo(d, raduis0);
gfx.curveTo(d, raduis0 + c1, raduis0 + c2, raduis0 + c2);
gfx.curveTo(raduis0 + c1, d, raduis0, d);
gfx.curveTo(raduis0 - c1, d, raduis0 - c2, raduis0 + c2);
gfx.curveTo(0, raduis0 + c1, 0, raduis0);
gfx.curveTo(0, raduis0 - c1, raduis0 - c2, raduis0 - c2);
gfx.curveTo(raduis0 - c1, 0, raduis0, 0);
gfx.curveTo(raduis0 + c1, 0, raduis0 + c2, raduis0 - c2);
gfx.curveTo(d, raduis0 - c1, d, raduis0);

gfx.moveTo(d2 + d1, d2 + raduis1);
gfx.curveTo(d2 + d1, d2 + raduis1 + c3, d2 + raduis1 + c4, d2 + raduis1 + c4);
gfx.curveTo(d2 + raduis1 + c3, d2 + d1, d2 + raduis1, d2 + d1);
gfx.curveTo(d2 + raduis1 - c3, d2 + d1, d2 + raduis1 - c4, d2 + raduis1 + c4);
gfx.curveTo(d2, d2 + raduis1 + c3, d2, d2 + raduis1);
gfx.curveTo(d2, d2 + raduis1 - c3, d2 + raduis1 - c4, d2 + raduis1 - c4);
gfx.curveTo(d2 + raduis1 - c3, d2, d2 + raduis1, d2);
gfx.curveTo(d2 + raduis1 + c3, d2, d2 + raduis1 + c4, d2 + raduis1 - c4);
gfx.curveTo(d2 + d1, d2 + raduis1 - c3, d2 + d1, d2 + raduis1);
gfx.endFill();
}

var shape:Shape = new Shape();
ring(shape.graphics, 100, 50, 0xFF);
addChild(shape);
Needs optimizing a bit... :p

mattkenefick
11-02-2008, 09:30 PM
Needs optimizing a bit... :p

Probably might be a better idea to use Graphics.drawCircle( x, y, radius );

wvxvw
11-02-2008, 09:55 PM
nope... you need to moveTo() twice before you call endFill, you cannot do it with drawCircle() :)

mattkenefick
11-02-2008, 09:58 PM
nope... you need to moveTo() twice before you call endFill, you cannot do it with drawCircle() :)

var sprite:Sprite = new Sprite();
var gfx:Graphics = sprite.graphics;

gfx.lineStyle( 10, 0x0, 1 );
gfx.drawCircle( 50,50, 30 );
gfx.endFill();

addChild( sprite );


Looks like a ring to me? ;)

wvxvw
11-02-2008, 10:07 PM
yes, just make the hole a square now ;)

freeman
11-02-2008, 10:08 PM
Thanks guys :)

these are nice work-arounds, but not the answer I'm looking for -- actually what I want is more complicated than a ring, and I really need to be able to both draw and erase...

is it possible at all, with AS3 at its current state?

freeman
11-02-2008, 10:10 PM
I mean I'm looking for a way to erase what I've drawn

mattkenefick
11-02-2008, 10:10 PM
yes, just make the hole a square now ;)

var sprite:Sprite = new Sprite();
var gfx:Graphics = sprite.graphics;

gfx.lineStyle( 5, 0x0, 1 );
gfx.drawRect( 0,0, 30,30 );
gfx.endFill();

addChild( sprite );

wvxvw
11-02-2008, 10:13 PM
If what you want is more complex, I'd think about using SVG parser that's already in the Flex mx framework... But, you cannot erase parts of graphics, you're not given access to it via AS.

@mattkenefick
yes, kind of hole of a doughnut without a doughnut... anyhow, seems like OP's asking about something different anyway :)

freeman
11-02-2008, 10:17 PM
I'm not familiar with svg -- do you suggest me to prepare my graphics as an SVG file?

wvxvw
11-02-2008, 10:19 PM
If they are so complicated, that you cannot manage them using the given API, I can hardly think of a different solution... But, keep in mind, even though there is SVG parser it doesn't fully support the format... though it was a long time requested feature, and, seems like it may be improved some time later...

mattkenefick
11-02-2008, 10:22 PM
This will cut a hole out of a shape.. Put a gradient or something on your background so you can tell it's working.

// create your shape
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0,1);
sprite.graphics.drawRect(0,0,200,200);
sprite.graphics.endFill();

// apply it to bitmap data
var bData:BitmapData = new BitmapData(200,200,true,0x000000);
var bmp:Bitmap = new Bitmap(bData);
bData.draw(sprite);

// add to stage
addChild( bmp );

// cut a hole out
bData.fillRect( new Rectangle(30,30,20,20), 0);

freeman
11-02-2008, 10:25 PM
so basically AS3 API provides all kinds of ways of drawing, but only one function clear() to erase? it's kinda hard to believe...

mattkenefick
11-02-2008, 10:26 PM
If you want like.. an ERASER tool.. use this.. it will follow your mouse and delete the color

// create your shape
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0,1);
sprite.graphics.drawRect(0,0,200,200);
sprite.graphics.endFill();

// apply it to bitmap data
var bData:BitmapData = new BitmapData(200,200,true,0x000000);
var bmp:Bitmap = new Bitmap(bData);
bData.draw(sprite);

// add to stage
addChild( bmp );

// cut a hole out
stage.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent){
bData.fillRect( new Rectangle(e.stageX,e.stageY,5,5), 0);
})


FTW!

freeman
11-02-2008, 10:27 PM
trying it...

freeman
11-02-2008, 10:35 PM
Incredible... it works...

so you make a region into black color in a BitmapData, and it causes the bitmap to be transparent in that area?

freeman
11-02-2008, 10:37 PM
I mean how does AVM know whether it should render that region into black or into transparent?

mattkenefick
11-02-2008, 10:40 PM
trying it...

The black is just because I set the BitmapData to be black. You set it to a gradient, a red color, or you could even make it a picture of yourself. Anything that bitmapdata can hold (which means drawings from a shape or what else)

wvxvw
11-02-2008, 10:45 PM
Colors are uints where 2 first bytes are responsible for alpha channel... Again, just keep in mind that it is bitmap, meaning, when you scale it, it will loose quality, and you cannot refer shapes you used to create that bitmap.

freeman
11-02-2008, 10:50 PM
I finally got it. The difference lies in the color format.

There's still a problem -- as i mentioned i'll use this thing as a mask. Although when directly added to the display list this bitmap appears with a transparent hole inside, however when it's used as a mask, that hole didn't mask the image...

wvxvw
11-02-2008, 10:55 PM
You should set cacheAsBitmap of those 2 shapes you use for mask and masked to true.

freeman
11-02-2008, 11:01 PM
I couldn't get it work by setting the two cacheAsBitmap's to true...

and I don't understand, what difference does that make? and the mask itself is a bitmap -- how does setting its cacheAsBitmap make any sense?

wvxvw
11-03-2008, 06:10 AM
This is because if you do set cacheAsBitmap to true, than setting mask works like blendMode = "erase", and it will make flash to apply _bitmap_ mask.

freeman
11-05-2008, 08:48 PM
Thank you very much!