筛选显示对象示例:Filter WorkbenchFlash Player 9 和更高版本,Adobe AIR 1.0 和更高版本 Filter Workbench 提供了一个用户界面,用于对图像和其他可视内容应用不同的滤镜以及查看结果代码,这些代码可用于在 ActionScript 中生成相同的效果。除了提供试验滤镜的工具外,此应用程序还展示了以下技巧:
若要获取此范例的应用程序文件,请参阅 www.adobe.com/go/learn_programmingAS3samples_flash_cn。可以在 Samples/FilterWorkbench 文件夹中找到 Filter Workbench 应用程序文件。该应用程序包含以下文件:
试验 ActionScript 滤镜Filter Workbench 应用程序旨在帮助您试验各种滤镜效果,并为该效果生成相关的 ActionScript 代码。使用该应用程序,您可以从包含可视内容(包括位图图像和 Flash 创建的动画)的三种不同文件中进行选择,并可采用单独或与其他滤镜相结合的方式,将八种不同的 ActionScript 滤镜应用于选定的图像。此应用程序包含以下滤镜:
用户选定图像并将滤镜应用于图像后,应用程序将显示一个带有用于设置选定滤镜特定属性的控件的面板。例如,下列图像显示的是已选择“斜角”滤镜的应用程序: 如果用户调整滤镜属性,则预览将实时更新。用户还可以应用多个滤镜,方法是:自定义一个滤镜,单击“应用”按钮;自定义另一个滤镜,单击“应用”按钮,以此类推。 应用程序的滤镜面板具有一些功能和限制:
创建滤镜实例Filter Workbench 应用程序包含一个类集,各可用滤镜均有一个对应的类,各面板用这些类来创建滤镜。用户选定滤镜后,与滤镜面板相关联的 ActionScript 代码就将创建相应滤镜工厂类的实例。(这些类称为工厂类,因为其用途在于创建其他对象的实例,这与实际工厂创建各产品极为相似) 只要用户更改面板上的属性值,面板的代码就会调用工厂类中的相应方法。各工厂类包含面板用于创建相应滤镜实例的特定方法。例如,如果用户选择“模糊”滤镜,则应用程序将创建 BlurFactory 实例。BlurFactory 类包含一个 modifyFilter() 方法,该方法接受三个参数:blurX、blurY 和 quality,这三个参数一起用于创建所需的 BlurFilter 实例: private var _filter:BlurFilter; public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void { _filter = new BlurFilter(blurX, blurY, quality); dispatchEvent(new Event(Event.CHANGE)); } 另一方面,如果用户选择“卷积”滤镜,因为该滤镜允许更大的灵活性,所以需要控制的属性就会更多。在 ConvolutionFactory 类中,如果用户在滤镜面板上选择不同的值,则将调用以下代码: private var _filter:ConvolutionFilter; public function modifyFilter(matrixX:Number = 0, matrixY:Number = 0, matrix:Array = null, divisor:Number = 1.0, bias:Number = 0.0, preserveAlpha:Boolean = true, clamp:Boolean = true, color:uint = 0, alpha:Number = 0.0):void { _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); dispatchEvent(new Event(Event.CHANGE)); } 请注意,在各例中,如果滤镜值发生变化,则工厂对象将调度 Event.CHANGE 事件,从而向侦听器通知滤镜的值已经改变。将滤镜实际应用于过滤内容的 FilterWorkbenchController 类将侦听该事件,以确定何时需检索滤镜的新副本并将其重新应用于过滤的内容。 FilterWorkbenchController 类无需知道各滤镜工厂类的特定详细信息,它只需知道滤镜已更改,并能够访问滤镜副本即可。为支持此目的,应用程序包含了一个 IFilterFactory 接口,该接口定义滤镜工厂类需提供的行为,以便应用程序的 FilterWorkbenchController 实例能够完成自己的工作。IFilterFactory 定义在 FilterWorkbenchController 类中使用的 getFilter() 方法: function getFilter():BitmapFilter; 请注意,getFilter() 接口方法定义指定该方法返回一个 BitmapFilter 实例,而非特定类型的滤镜。BitmapFilter 类不定义特定类型的滤镜,而是用来构建所有滤镜类的基类。各滤镜工厂类定义 getFilter() 方法的特定实现,此时将返回对所创建滤镜对象的引用。例如,以下就是 ConvolutionFactory 类源代码的缩写版本: public class ConvolutionFactory extends EventDispatcher implements IFilterFactory { // ------- Private vars ------- private var _filter:ConvolutionFilter; ... // ------- IFilterFactory implementation ------- public function getFilter():BitmapFilter { return _filter; } ... } ConvolutionFactory 类在实现 getFilter() 方法时将返回一个 ConvolutionFilter 实例,尽管调用 getFilter() 的任何对象无需知道此返回结果。根据 ConvolutionFactory 所遵循的 getFilter() 方法的定义,此方法必须返回任意 BitmapFilter 实例,这些实例可能是任意 ActionScript 滤镜类的实例。 将滤镜应用于显示对象如前所述,Filter Workbench 应用程序使用 FilterWorkbenchController 类的实例(下文称为“控制器实例”),该实例执行将滤镜应用于所选可视对象的实际任务。控制器实例必须首先知道滤镜需应用于哪些图像或可视内容,然后才能应用滤镜。用户选定图像后,应用程序将调用 FilterWorkbenchController 类中的 setFilterTarget() 方法,传入在 ImageType 类中定义的一个常量: public function setFilterTarget(targetType:ImageType):void { ... _loader = new Loader(); ... _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); ... } 控制器实例使用该信息来加载指定的文件,并将所加载的文件存储在一个名为 _currentTarget 的实例变量中: private var _currentTarget:DisplayObject; private function targetLoadComplete(event:Event):void { ... _currentTarget = _loader.content; ... } 用户选择滤镜后,应用程序将调用控制器实例的 setFilter() 方法,为控制器提供对相关滤镜工厂对象的引用,此引用存储在名为 _filterFactory 的实例变量中。 private var _filterFactory:IFilterFactory; public function setFilter(factory:IFilterFactory):void { ... _filterFactory = factory; _filterFactory.addEventListener(Event.CHANGE, filterChange); } 请注意,正如上文所说明的那样,控制器实例并不知道为其提供的滤镜工厂实例的具体数据类型,它只知道对象实现 IFilterFactory 实例,这意味着它具有 getFilter() 方法,并可在滤镜更改时调度 change (Event.CHANGE) 事件。 如果用户改变滤镜面板中的滤镜属性,则控制器实例将通过滤镜工厂的 change 事件发现滤镜已发生更改,该事件调用控制器实例的 filterChange() 方法。而该方法又将调用 applyTemporaryFilter() 方法: private function filterChange(event:Event):void { applyTemporaryFilter(); } private function applyTemporaryFilter():void { var currentFilter:BitmapFilter = _filterFactory.getFilter(); // Add the current filter to the set temporarily _currentFilters.push(currentFilter); // Refresh the filter set of the filter target _currentTarget.filters = _currentFilters; // Remove the current filter from the set // (This doesn't remove it from the filter target, since // the target uses a copy of the filters array internally.) _currentFilters.pop(); } 将滤镜应用于显示对象的工作在 applyTemporaryFilter() 方法中进行。首先,控制器将通过调用滤镜工厂的 getFilter() 方法来检索对滤镜对象的引用。 var currentFilter:BitmapFilter = _filterFactory.getFilter(); 控制器实例有一个名为 _currentFilters 的数组实例变量,所有曾应用于显示对象的滤镜均存储在该变量中。下一步就是将新近更新的滤镜添加到该数组: _currentFilters.push(currentFilter); 然后,代码将滤镜数组分配给显示对象的 filters 属性,这会将滤镜实际应用于图像: _currentTarget.filters = _currentFilters; 最后,由于此最近添加的滤镜仍旧是“工作”滤镜,不应将其永久应用于显示对象,因此将其从 _currentFilters 数组中删除: _currentFilters.pop(); 将此滤镜从数组中删除并不会影响已过滤的显示对象,因为在将滤镜数组分配给 filters 属性时,显示对象将生成滤镜数组的副本,而且显示对象使用的是内部数组而非原始数组。因此,对滤镜数组所做的任何更改均不会影响显示对象,直至数组被再次分配给显示对象的 filters 属性。 |
|