AS3.0 Image Effects 复制图形

野味出家人

野味出家人

2016-01-29 12:09

AS3.0 Image Effects 复制图形,复制图形概念上理解起来很简单,但是他是drawing API工具包新增功能里最受欢迎的改变之一。 任何绘制在shape和Sprite里面的图形都与该shape或sprite融合在一起,没有任何途径从一个图形对象中复制图形到另外一个中, ...

(作者注:从这一节开始,慢慢变得有趣了,实例也复杂了不少书中所有代码都经本人编译通过的(FD+flex4.0 SDK),可以直接运行。 )

引用:

等的就是这个!(知道我咋这么激动吗?)。每一个FLASH新版本的推出都会出台多项对于绘图API的改进,但都比不上这次的最新版本,通过这一章,我们将探讨drawing API的新开放的功能

复制图形概念上理解起来很简单,但是他是drawing API工具包新增功能里最受欢迎的改变之一。 任何绘制在shape和Sprite里面的图形都与该shape或sprite融合在一起,没有任何途径从一个图形对象中复制图形到另外一个中,当然你可以使用BitmapData类来复制图形,但是它复制的是位图而不是矢量图,或者你可以保存所有的绘图过程用来重新创建图像,显然这不是个十分灵活的解决方案。

现在,你只需要一个简单的函数就能搞定:

copyGraphics():void

使用copyGraphics(),一个图形实例的任何内容可以随时复制到另外一个。实在太爽了,我们将通过下面的例子探讨它可能的用途,创建一个类似于老旧的呼吸运动记录器的东西,如同http://www.myoats.com上的一样,图1-13展示了www.myoats.com上的效果。

下面的类你可以在CopyingGraphics.as文件中找到,编译并测试这个类,你会看到一个黑色的舞台,当你点击鼠标并且移动来绘制线条的时候,会整个旋转你绘制的图形,线条会被围绕舞台中心复制多次并且跟随你所画的更新。使用上下箭头,你可以调整复制的次数,结果如图1-14所示:

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/fjc/)

与先前的例子比较,这是一个漂亮的大工程,所以仔细看看代码,玩玩最终生成的程序,之后我会详细讲解有关内容。

代码:

package{        import flash.display.Shape;        import flash.display.Sprite;        import flash.events.Event;        import flash.events.KeyboardEvent;        import flash.events.MouseEvent;        import flash.filters.GlowFilter;        import flash.ui.Keyboard;               /**         * ...         * @author bardpub         */        [SWF(width=550,height=400,backgroundColor=0)]        public class CopyingGraphics extends Sprite        {    private static const INIT_SEGMENTS:int = 10;                private static const MAX_SEGMENTS:int = 20;                private static const MIN_SEGMENTS:int = 3;                private static const THICKNESS:int = 1;                private static const COLOR:uint = 0x66CCCC;                private static const ROTATION_RATE:int = 1;    private var _shapeHolder:Sprite;                private var _shapes:Vector.;    public function CopyingGraphics()                {                        init();                }    private function init():void {                    _shapeHolder = new Sprite();                        _shapeHolder.x = stage.stageWidth / 2;                        _shapeHolder.y = stage.stageHeight / 2;                        addChild(_shapeHolder);                        _shapes = new Vector.();                        for (var i:int = 0; i < INIT_SEGMENTS; i++ ) {     addSegment();                        }                        positionSegments();                        stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);                        stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);                        stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown);                        filters = [new GlowFilter(COLOR)];                }    private function draw():void {                        var shape:Shape = _shapes[0];                        shape.graphics.lineTo(shape.mouseX, shape.mouseY);                        var segments:int = _shapeHolder.numChildren;                        for (var i:int = 1; i < segments; i++ ) {     _shapes[i].graphics.copyFrom(shape.graphics);                        }                }    private function addSegment():void {                        var shape:Shape = new Shape();                        if (_shapes.length  0) {     shape.graphics.copyFrom(_shapes[0].graphics);                        } else {     shape.graphics.lineStyle(THICKNESS, COLOR);                        }                        _shapes.push(shape);                        _shapeHolder.addChild(shape);                }    private function removeSegment():void {                        var shape:Shape = _shapes.pop();                        _shapeHolder.removeChild(shape);                }    private function positionSegments():void {                        var segments:int = _shapeHolder.numChildren;                        var angle:Number = 360 / segments;                        for (var i:int = 1; i < segments; i++ ) {     _shapes[i].rotation = angle * i;                        }                }    private function onStageMouseDown(event:MouseEvent):void {                        var shape:Shape = _shapes[0];                        shape.graphics.moveTo(shape.mouseX, shape.mouseY);                        addEventListener(Event.ENTER_FRAME, onEnterFrame);                }    private function onStageMouseUp(event:MouseEvent):void {                        removeEventListener(Event.ENTER_FRAME, onEnterFrame);                }    private function onEnterFrame(event:Event):void {                        _shapeHolder.rotation += ROTATION_RATE;                        draw();                }    private function onStageKeyDown(event:KeyboardEvent):void {                        switch (event.keyCode) {     case Keyboard.UP:             if (_shapeHolder.numChildren < MAX_SEGMENTS) {                     addSegment();                     positionSegments();             }             break;     case Keyboard.DOWN:             if (_shapeHolder.numChildren  MIN_SEGMENTS) {                     removeSegment();                     positionSegments();             }             break;                        }                }        }}

12AS3.0 Image Effects 复制图形(下)

在声明了包与类并且导入了相关的类之后,我定义了一些在程序中会用到的常量,(注:这段程序会在一个shape内绘制内容,然后会复制几个shape并让他旋转一定角度,作者把这些shape称为段(segment),把我弄得晕晕的,总让我想起汇编的segment ) INIT_SEGMENTS是开始时围绕所绘制的线条旋转的段的个数,MAX_SEGEMNTS和MIN_SEGMENTS 就是最大值与最小值了, THICKNESS与COLOR用来定义线条的外观,最后,ROTATION_RATE用来控制当你绘制的时候,shape旋转得多快。

随后的一些属性用来保持程序中创建的shape和Sprite的引用, _shapeHolder是一个大容器,所有的shape添加在他里面,他会在你鼠标绘制的时候旋转, _shapes向量数组存贮所有创建的shape实例。

引用:

ctionScript3.0中的Vector类型是Flash Player10新增的内容,是一个与Array相似的数据结构,可以使用任何你知道的有关数组的方法操作,但是有一套更为严格的规则,最明显的是 Vector在创建的时候需要指定一个参数类型,并且它只接受指定参数类型的数据,如下面的一句代码:

var sprites:Vector.<Sprite = new Vector.<Sprite();

你只能把Sprite类的实例放入数组,不像Array一样你可以放任何类型的数据,这样做最大的好处就是任何被添加到Vector里的数据你都明确知道它的类型,并不需要从Object类型转换,从Vector里取出来的数据并不需要做类型检查。

var sprite:Sprite = sprites.pop()

如果你试图在一个Array类型上这么错,编译器会抛出一个错误,Vector让代码更加干净,执行速度更快。

在类构造器内,我只是调用了init()方法。通常,当我需要超过两到三行代码来初始化程序的时候,我会把它们放在一个名为init的方法内,然后在构造器中调用。

init方法内我做的第一件事是创建_shapeHolder,把他定位在舞台的中间并且添加到显示列表。

代码:

_shapeHolder = new Sprite();_shapeHolder.x = stage.stageWidth / 2;_shapeHolder.y = stage.stageHeight / 2;addChild(_shapeHolder);

然后我初始化_shapes向量数组,用一个循环调用addSegment()方法创建所有的段。addSegment()方法是用来添加一个段到 _shapeHolder容器的。

循环结束后调用positionSegment()方法来围绕中心旋转所有的段。

代码:

_shapes = new Vector.<Shape();for (var i:int = 0; i < INIT_SEGMENTS; i++ ) {    addSegment();}positionSegments();

现在我们来看看addSegment()方法。

代码:

var shape:Shape = new Shape();if (_shapes.length  0) {    shape.graphics.copyFrom(_shapes[0].graphics);} else {    shape.graphics.lineStyle(THICKNESS, COLOR);}_shapes.push(shape);_shapeHolder.addChild(shape);

创建一个新的Shape实例之后,我检查一下他是不是第一个被创建的,如果不是第一个我要用来绘图的shape,我调用神奇的copyFrom()方法,这会把我在第一个shape中绘制的所有的内容复制到现在的shape,如果是第一个shape,我就调用 lineStyle()方法定义绘制的线条样式,最后,我把新创建的shape添加到_shapes数组同时添加进_shapesHolder容器。

所有的段都添加好了之后,调用positionSegments()方法来围绕_shapesHolder容器的注册点也就是舞台的中心点旋转他们,用360除以段的数量就可以很容易的算出每个段之间相距的角度。

代码:

var segments:int = _shapeHolder.numChildren;var angle:Number = 360 / segments;for (var i:int = 1; i < segments; i++ ) {    _shapes[i].rotation = angle * i;}

init方法最后的几行为舞台添加3个事件侦听器,然后给舞台应用发光滤镜用来添加一些视觉效果。(有关滤镜的更多内容在下一章)。

在onStageMouseDown()函数中,我在第一个shape中调用moveTo()方法,这样虚拟画笔会移动到鼠标当前的位置,然后我创建一个侦听器用来侦听EVENT_FRAME事件。

代码:

var shape:Shape = _shapes[0];shape.graphics.moveTo(shape.mouseX, shape.mouseY);addEventListener(Event.ENTER_FRAME, onEnterFrame);

onStageMouseUp()函数中我只是简单的移除对ENTER_FRAME事件的侦听,onEnterFrame函数会在ENTER_FRAME 发生时调用。在onEnterFrame里面,我旋转_shapeHolder容器并调用draw()方法。

代码:

_shapeHolder.rotation += ROTATION_RATE;draw();

draw()方法,我在第一个shape中调用lineTo方法,这样会绘制一条到鼠标当前位置的直线。

代码:

var shape:Shape = _shapes[0];shape.graphics.lineTo(shape.mouseX, shape.mouseY);

记住当鼠标按下之后这会发生在每一帧上,即便鼠标不移动,但是因为_shapeHolder容器自身的旋转,所以当前鼠标坐在的位置跟之前 shape.moveTo定义的位置还是不一样。接下来,我遍历所有的段,调用copyFrom方法把第一个shape中的内容复制到他们每一个里面,就这么简单!

代码:

var segments:int = _shapeHolder.numChildren;for (var i:int = 1; i < segments; i++ ) {    _shapes[i].graphics.copyFrom(shape.graphics);}

init方法里面最后一个侦听器用来侦听键盘按下事件。当键盘按下时,onStageKeyDown方法被调用,在它里面我检查上下箭头是否被按下,如果按下Up键,我首先确保当前段的数量小于最大段数限制,如果还没达到限制,我调用addSegment()方法添加一个新段,然后调用 positionSegment()方法定位所有的段。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/fjc/)

代码:

case Keyboard.UP:    if (_shapeHolder.numChildren < MAX_SEGMENTS) {        addSegment();        positionSegments();    }

如果DOWN键被按下,我检查当前段数是否小于最小段数限制,如果没有,我调用removeSegment()方法删除一个段并调用 positionSegment()方法从新定位所有的段。

removeSegment()方法简单的删除_shape数组里面的最后一个值,并把它从_shapeHolder容器中删除。

代码:

var shape:Shape = _shapes.pop();_shapeHolder.removeChild(shape);

现在继续玩玩你的大作吧,看看你画出什么漂亮的东西出来,记得按上下键来调整段的数量,看看出来的效果有什么不同。图1-15中我展示了一些我的“艺术品”。

  12
展开更多 50%)
分享

猜你喜欢

AS3.0 Image Effects 复制图形

flash教程
AS3.0 Image Effects 复制图形

Flash教程:AS3.0实例之打字效果

flash教程
Flash教程:AS3.0实例之打字效果

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

AutoCAD 2008 精确绘制图形

autocad教程
AutoCAD 2008  精确绘制图形

Flash AS3.0菜鸟学飞教程:函数的引用

flash教程
Flash AS3.0菜鸟学飞教程:函数的引用

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Flash AS3.0菜鸟学飞教程:创建MovieClip类

flash教程
Flash AS3.0菜鸟学飞教程:创建MovieClip类

Flash AS3.0菜鸟学飞教程:代码的位置

flash教程
Flash AS3.0菜鸟学飞教程:代码的位置

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

《欢乐西游》快速升级解析

《欢乐西游》快速升级解析

HTML组件之:日历主页面

HTML组件之:日历主页面
下拉加载更多内容 ↓