AS3 水波纹

  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这个容器中的所有的对象。

原文地址:https://www.cnblogs.com/lingLuoChengMi/p/8286916.html