AS3的水波纹,我看网上的素材虽然有,但是很少有合适的,找了很久才找到一个能凑合用的。虽然效果还凑合,但是缺陷也有,内存占用太大了。今天在此发一下水波纹的类,有需要的朋友也好找一点。
这是 Rippler 类
package { import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.BlendMode; import flash.display.DisplayObject; import flash.events.Event; import flash.filters.ConvolutionFilter; import flash.filters.DisplacementMapFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; /** * * The Rippler class creates an effect of rippling water on a source DisplayObject. * * @example The following code takes a DisplayObject on the stage and adds a ripple to it, assuming source is a DisplayObject already on the stage. * * <listing version="3.0"> * import be.nascom.flash.graphics.Rippler; * * // create a Rippler instance to impact source, with a strength of 60 and a scale of 6. * // The source can be any DisplayObject on the stage, such as a Bitmap or MovieClip object. * var rippler : Rippler = new Rippler(source, 60, 6); * * // create a ripple with size 20 and alpha 1 with origin on position (200, 50) * rippler.drawRipple(100, 50, 20, 1); * </listing> * * @author David Lenaerts * @mail david.lenaerts@nascom.be * */ public class Rippler { // The DisplayObject which the ripples will affect.(波纹将会影响到的DisplayObject。) private var _source : DisplayObject; // Two buffers on which the ripple displacement image will be created, and swapped.(两个缓冲区,将产生波纹位移图像,并交换。) // Depending on the scale parameter, this will be smaller than the source(根据比例参数,这个比源要小) private var _buffer1 : BitmapData; private var _buffer2 : BitmapData; // The final bitmapdata containing the upscaled ripple image, to match the source DisplayObject(最后一个包含放大的波纹图像的位图数据,以匹配源显示对象) private var _defData : BitmapData; // Rectangle and Point objects created once and reused for performance(为性能而创建的矩形和点对象) private var _fullRect : Rectangle; // A buffer-sized Rectangle used to apply filters to the buffer(一个缓冲区大小的矩形用于将过滤器应用到缓冲区中) private var _drawRect : Rectangle; // A Rectangle used when drawing a ripple(绘制波纹时使用的矩形) private var _origin : Point = new Point(); // A Point object to (0, 0) used for the DisplacementMapFilter as well as for filters on the buffer(一个点对象(0,0)用于位移映射过滤器和缓冲区上的过滤器) // The DisplacementMapFilter applied to the source DisplayObject(应用于源DisplayObject的位移映射过滤器) private var _filter : DisplacementMapFilter; // A filter causing the ripples to grow(一种导致波纹生长的过滤器) private var _expandFilter : ConvolutionFilter; // Creates a colour offset to 0x7f7f7f so there is no image offset due to the DisplacementMapFilter(创建一个颜色偏移到0x7f7f7f,因此没有图像偏移,因为位移映射) private var _colourTransform : ColorTransform; // Used to scale up the buffer to the final source DisplayObject's scale(用于将缓冲区扩展到最终的源DisplayObject的规模) private var _matrix : Matrix; // We only need 1/scale, so we keep it here(我们只需要1/1,所以我们把它放在这里) private var _scaleInv : Number; /** * Creates a Rippler instance.(创建一个涟漪实例。) * * @param source The DisplayObject which the ripples will affect.(源代码将会影响到它的显示对象。) * @param strength The strength of the ripple displacements.(增强了波纹位移的强度。) * @param scale The size of the ripples. In reality, the scale defines the size of the ripple displacement map (map.width = source.width/scale). Higher values are therefor also potentially faster. * (大小是波纹的大小。实际上,这个比例定义了波纹位移贴图的大小(地图。宽度= source.width /规模)。更高的值也可能更快。) */ public function Rippler(source : DisplayObject, strength : Number, scale : Number = 2) { var correctedScaleX : Number; var correctedScaleY : Number; _source = source; _scaleInv = 1/scale; // create the (downscaled) buffers and final (upscaled) image data, sizes depend on scale(创建(缩小的)缓冲区和最终(放大的)图像数据,大小取决于规模) _buffer1 = new BitmapData(source.width*_scaleInv, source.height*_scaleInv, false, 0x000000); _buffer2 = new BitmapData(_buffer1.width, _buffer1.height, false, 0x000000); _defData = new BitmapData(source.width, source.height); // Recalculate scale between the buffers and the final upscaled image to prevent roundoff errors.(重新计算缓冲区和最后的向上缩放图像之间的比例,以防止循环错误。) correctedScaleX = _defData.width/_buffer1.width; correctedScaleY = _defData.height/_buffer1.height; // Create reusable objects(创建可重用的对象) _fullRect = new Rectangle(0, 0, _buffer1.width, _buffer1.height); _drawRect = new Rectangle(); // Create the DisplacementMapFilter and assign it to the source(创建位移-mapfilter并将其分配给源文件) _filter = new DisplacementMapFilter(_buffer1, _origin, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE, strength, strength, "wrap"); _source.filters = [_filter]; // Create a frame-based loop to update the ripples(创建一个基于框架的循环来更新波纹) _source.addEventListener(Event.ENTER_FRAME, handleEnterFrame); // Create the filter that causes the ripples to grow.(创建过滤器,使波纹产生) // Depending on the colour of its neighbours, the pixel will be turned white(取决于邻居的颜色,像素会变成白色) _expandFilter = new ConvolutionFilter(3, 3, [0.5, 1, 0.5, 1, 0, 1, 0.5, 1, 0.5], 3); // Create the colour transformation based on (创建基于颜色转换的颜色转换) _colourTransform = new ColorTransform(1, 1, 1, 1, 127, 127, 127); // Create the Matrix object(创建矩阵对象) _matrix = new Matrix(correctedScaleX, 0, 0, correctedScaleY); } /** * Initiates a ripple at a position of the source DisplayObject.(在源DisplayObject的位置上发起一个波纹。) * * @param x The horizontal coordinate of the ripple origin.(x是波纹原点的水平坐标。) * @param y The vertical coordinate of the ripple origin.(y是波纹原点的垂直坐标。) * @param size The size of the ripple diameter on first impact.(大小与第一次撞击时的波纹直径大小有关。) * @param alpha The alpha value of the ripple on first impact.(alpha值在第一次影响时的alpha值。) */ public function drawRipple(x : int, y : int, size : int, alpha : Number) : void { var half : int = size >> 1; // We need half the size of the ripple(我们需要波纹的一半大小。) var intensity : int = (alpha*0xff & 0xff)*alpha; // The colour which will be drawn in the currently active buffer(将在当前活动的缓冲区中绘制的颜色) // calculate and draw the rectangle, having (x, y) in its centre(计算并绘制矩形,在其中心有(x,y)) _drawRect.x = (-half+x)*_scaleInv; _drawRect.y = (-half+y)*_scaleInv; _drawRect.width = _drawRect.height = size*_scaleInv; _buffer1.fillRect(_drawRect, intensity); } /** * Returns the actual ripple image.(Returns the actual ripple image.) */ public function getRippleImage() : BitmapData { return _defData; } /** * Removes all memory occupied by this instance. This method must be called before discarding an instance.(删除该实例所占用的所有内存。在丢弃实例之前必须调用此方法。) */ public function destroy() : void { _source.removeEventListener(Event.ENTER_FRAME, handleEnterFrame); _buffer1.dispose(); _buffer2.dispose(); _defData.dispose(); } // the actual loop where the ripples are animated(波纹是动画的实际循环) private function handleEnterFrame(event : Event) : void { // a temporary clone of buffer 2(缓冲区2的临时克隆) var temp : BitmapData = _buffer2.clone(); // buffer2 will contain an expanded version of buffer1(buffer2将包含一个扩展版的buffer1) _buffer2.applyFilter(_buffer1, _fullRect, _origin, _expandFilter); // by substracting buffer2's old image, buffer2 will now be a ring(通过对buffer2的旧图像进行处理,buffer2将成为一个环) _buffer2.draw(temp, null, null, BlendMode.SUBTRACT, null, false); // scale up and draw to the final displacement map, and apply it to the filter(放大并绘制最终位移图,并将其应用到过滤器中) _defData.draw(_buffer2, _matrix, _colourTransform, null, null, true); _filter.mapBitmap = _defData; _source.filters = [_filter]; temp.dispose(); // switch buffers 1 and 2(switch buffers 1 and 2) switchBuffers(); } // switch buffer 1 and 2, so that (切换缓冲1和2,这样) private function switchBuffers() : void { var temp : BitmapData; temp = _buffer1; _buffer1 = _buffer2; _buffer2 = temp; } } }
用法如下
var mc:Sprite=new Sprite(); var r:Rippler;
addChild(mc); //目标 水纹起伏强度 水纹宽度 r=new Rippler(mc,40,10); //x,y,范围,强度 r.drawRipple(mouseX,mouseY,50,1);
其中mc是一个容器,r影响的是mc这个容器中的所有的对象。