显示具有 Graphics 标签的文章。 显示所有文章
显示具有 Graphics 标签的文章。 显示所有文章

2008年7月5日 星期六

AS3 - BitmapText 程序分享   [+/-]

Ticore's Blog

由于 Flash Player 一直以来都无法对系统字体的文字作旋转与不规则形状遮罩
可是到了 Flash Player 9 AS3,可以将文字绘制成位图
也可以自行继承内建类别 Sprite, TextField 等
于是想到做一个 TextField Wrapper,提供系统文字的点阵化功能
藉以达到文字可旋转、套用不规则遮罩

其实这个 BitmapText 程序去年就已经写了
主要是出于研究目的
专案一次也没有用到过
没想到最近新出的 Flash Player 10 beta 文字引擎
已经可以使用系统字体作旋转了
倘若再不把这程序拿出来使用一下,恐怕就这样永不见天日了~~><>

主要是包含两个类别 TextWrapper, BitmapText
TextWrapper 只是 TextField 的外覆类别
真正在做点阵绘图的是 BitmapText
由于 AS3 TextField 成员属性与方法相当多
我已经很尽量的复写大部分的方法了

TextWrapper Class:

/*
TextWrapper AS3 v0.0.2
 
Date: 2007.04.25
作者: Ticore Shih
Blog:http://ticore.blogspot.com
EMail: swl@ms53.url.com.tw
 
v0.0.1
继承 Sprite 包覆一个 TextField
 
v0.0.2
增加 TextField 一般性方法
*/

package com.ticore.text {
 
 import flash.geom.*;
 import flash.display.*;
 import flash.text.*;
 import flash.events.*;
 
 public class TextWrapper extends Sprite {
  //
  // Protected Property
  //
  protected var _txt_:TextField;
  //
  // Constructor
  //
  public function TextWrapper() {
   init();
  }
  protected function init():void {
   _txt_ = new TextField();
   this.addChild(_txt_);
  }
  //
  // Override DisplayObject Property and Method
  //
  public override function set width(w:Number):void {
   _txt_.width = w;
  }
  public override function get width():Number {
   return _txt_.width;
  }
  
  public override function set height(h:Number):void {
   _txt_.height = h;
  }
  public override function get height():Number {
   return _txt_.height;
  }
  //
  // Proxy Common TextField Property
  //
  public function set antiAliasType(value:String):void {
   _txt_.antiAliasType = value;
  }
  public function get antiAliasType():String {
   return _txt_.antiAliasType;
  }
  
  public function set autoSize(value:String):void {
   _txt_.autoSize = value;
  }
  public function get autoSize():String {
   return _txt_.autoSize;
  }
  
  public function set gridFitType(value:String):void {
   _txt_.gridFitType = value;
  }
  public function get gridFitType():String {
   return _txt_.gridFitType;
  }
  
  public function set htmlText(value:String):void {
   _txt_.htmlText = value;
  }
  public function get htmlText():String {
   return _txt_.htmlText;
  }
  
  public function set restrict(value:String):void {
   _txt_.restrict = value;
  }
  public function get restrict():String {
   return _txt_.restrict;
  }
  
  public function set text(txt:String):void {
   _txt_.text = txt;
  }
  public function get text():String {
   return _txt_.text;
  }
  
  public function set type(type:String):void {
   _txt_.type = type;
  }
  public function get type():String {
   return _txt_.type;
  }
  
  
  public function set backgroundColor(value:uint):void {
   _txt_.backgroundColor = value;
  }
  public function get backgroundColor():uint {
   return _txt_.backgroundColor;
  }
  
  public function set borderColor(value:uint):void {
   _txt_.borderColor = value;
  }
  public function get borderColor():uint {
   return _txt_.borderColor;
  }
  
  public function set textColor(value:uint):void {
   _txt_.textColor = value;
  }
  public function get textColor():uint {
   return _txt_.textColor;
  }
  
  
  public function get bottomScrollV():int {
   return _txt_.bottomScrollV;
  }
  
  public function get caretIndex():int {
   return _txt_.caretIndex;
  }
  
  public function get length():int {
   return _txt_.length;
  }
  
  public function get maxChars():int {
   return _txt_.maxChars;
  }
  
  public function get maxScrollH():int {
   return _txt_.maxScrollH;
  }
  
  public function get maxScrollV():int {
   return _txt_.maxScrollV;
  }
  
  public function get numLines():int {
   return _txt_.numLines;
  }
  
  public function get selectionBeginIndex():int {
   return _txt_.selectionBeginIndex;
  }
  
  public function get selectionEndIndex():int {
   return _txt_.selectionEndIndex;
  }
  
  
  public function set sharpness(value:Number):void {
   _txt_.sharpness = value;
  }
  public function get sharpness():Number {
   return _txt_.sharpness;
  }
  
  public function set thickness(value:Number):void {
   _txt_.thickness = value;
  }
  public function get thickness():Number {
   return _txt_.thickness;
  }
  
  public function get textHeight():Number {
   return _txt_.textHeight;
  }
  public function get textWidth():Number {
   return _txt_.textWidth;
  }
  
  
  public function set alwaysShowSelection(value:Boolean):void {
   _txt_.alwaysShowSelection = value;
  }
  public function get alwaysShowSelection():Boolean {
   return _txt_.alwaysShowSelection;
  }
  
  public function set border(value:Boolean):void {
   _txt_.border = value;
  }
  public function get border():Boolean {
   return _txt_.border;
  }
  
  public function set condenseWhite(value:Boolean):void {
   _txt_.condenseWhite = value;
  }
  public function get condenseWhite():Boolean {
   return _txt_.condenseWhite;
  }
  
  public function set displayAsPassword(value:Boolean):void {
   _txt_.displayAsPassword = value;
  }
  public function get displayAsPassword():Boolean {
   return _txt_.displayAsPassword;
  }
  
  public function set embedFonts(value:Boolean):void {
   _txt_.embedFonts = value;
  }
  public function get embedFonts():Boolean {
   return _txt_.embedFonts;
  }
  
  public function set mouseWheelEnabled(value:Boolean):void {
   _txt_.mouseWheelEnabled = value;
  }
  public function get mouseWheelEnabled():Boolean {
   return _txt_.mouseWheelEnabled;
  }
  
  public function set multiline(value:Boolean):void {
   _txt_.multiline = value;
  }
  public function get multiline():Boolean {
   return _txt_.multiline;
  }
  
  public function set selectable(value:Boolean):void {
   _txt_.selectable = value;
  }
  public function get selectable():Boolean {
   return _txt_.selectable;
  }
  
  public function set useRichTextClipboard(value:Boolean):void {
   _txt_.useRichTextClipboard = value;
  }
  public function get useRichTextClipboard():Boolean {
   return _txt_.useRichTextClipboard;
  }
  
  public function set wordWrap(value:Boolean):void {
   _txt_.wordWrap = value;
  }
  public function get wordWrap():Boolean {
   return _txt_.wordWrap;
  }
  //
  // Proxy Common TextField Method
  //
  public function appendText(text:String):void {
   _txt_.appendText(text);
  }
  
  public function getCharBoundaries(charIndex:int):Rectangle {
   return _txt_.getCharBoundaries(charIndex);
  }
  
  public function getCharIndexAtPoint(x:Number, y:Number):int {
   return _txt_.getCharIndexAtPoint(x,y);
  }
  
  public function getFirstCharInParagraph(charIndex:int):int {
   return _txt_.getFirstCharInParagraph(charIndex);
  }
  
  public function getImageReference(id:String):DisplayObject {
   return _txt_.getImageReference(id);
  }
  
  public function getLineIndexAtPoint(x:Number, y:Number):int {
   return _txt_.getLineIndexAtPoint(x,y);
  }
  
  public function getLineIndexOfChar(charIndex:int):int {
   return _txt_.getLineIndexOfChar(charIndex);
  }
  
  public function getLineLength(lineIndex:int):int {
   return _txt_.getLineLength(lineIndex);
  }
  
  public function getLineMetrics(lineIndex:int):TextLineMetrics {
   return _txt_.getLineMetrics(lineIndex);
  }
  
  public function getLineOffset(lineIndex:int):int {
   return _txt_.getLineOffset(lineIndex);
  }
  
  public function getLineText(lineIndex:int):String {
   return _txt_.getLineText(lineIndex);
  }
  
  public function getParagraphLength(charIndex:int):int {
   return _txt_.getParagraphLength(charIndex);
  }
  
  public function replaceSelectedText(value:String):void {
   _txt_.replaceSelectedText(value);
  }
  
  public function replaceText(beginIndex:int, endIndex:int, newText:String):void {
   _txt_.replaceText(beginIndex,endIndex,newText);
  }
  
  public function setTextFormat(format:TextFormat, beginIndex:int = -1, endIndex:int = -1):void {
   _txt_.setTextFormat(format,beginIndex,endIndex);
  }
  public function getTextFormat(beginIndex:int = -1, endIndex:int = -1):TextFormat {
   return _txt_.getTextFormat(beginIndex,endIndex);
  }
  
  public function set defaultTextFormat(format:TextFormat):void {
   _txt_.defaultTextFormat = format;
  }
  public function get defaultTextFormat():TextFormat {
   return _txt_.defaultTextFormat;
  }
  
 }
}

BitmapText Class:

/*
BitmapText AS3 v0.0.4
 
Date: 2007.04.25
作者: Ticore Shih
Blog:http://ticore.blogspot.com
EMail: swl@ms53.url.com.tw
 
v0.0.1
利用 BitmapData draw TextFIeld
达到可以呈现旋转文字的效果
 
v0.0.2
增加 TextField 一般性方法与属性控制
增加 validate 属性,减少不必要 draw 次数
 
TextField.autoSize 功能会有一些问题
TextField 大小会一直跳动,重复 draw 会发生多重图象
 
v0.0.3
增加 TextField 一般性方法与属性控制
 
v0.0.4
重构将 TextWrapper 功能独立为单一 Class
*/

package com.ticore.text {
 
 import flash.geom.*;
 import flash.display.*;
 import flash.text.*;
 import flash.events.*;
 import flash.filters.*;
 
 public class BitmapText extends TextWrapper {
  
  // Private Property
  private var _validate_:Boolean = true;
  private var magniFactor:Number = 3;
  private var blurFilter:BlurFilter;
  private var _useBitmapText_:Boolean = true;
  
  private var bmpData:BitmapData;
  private var bmp:Bitmap;
  
  public function BitmapText() {
   init();
  }
  protected override function init():void {
   super.init();
   _txt_.addEventListener(Event.CHANGE, onChange);
   bmp = new Bitmap();
   bmp.smoothing = true;
   bmp.scaleX = bmp.scaleY = 1 / magniFactor;
   this.addChild(bmp);
   _txt_.visible = false;
   this.addChild(_txt_);
   blurFilter = new BlurFilter(1 + magniFactor / 6, 1 + magniFactor / 6, BitmapFilterQuality.MEDIUM);
   validate = false;
   addEventListener(Event.ENTER_FRAME, onEnterFame);
  }
  //
  // Private Method
  //
  private function updateBmpData():void {
   if (bmpData) {
    bmpData.dispose();
   }
   bmpData = new BitmapData((width + 1) * magniFactor, (height + 1) * magniFactor, true, 0x00000000);
   bmp.bitmapData = bmpData;
   bmp.smoothing = true;
   validate = false;
  }
  
  private function onChange(eventObj:Event):void {
   validate = false;
  }
  
  private function onEnterFame(eventObj:Event):void {
   if (!validate) {
    draw();
   }
  }
  
  private function draw():void {
   if (bmpData == null) {
    updateBmpData();
   }

   if (bmpData.width < (width + 1) * magniFactor || bmpData.height < (height + 1) * magniFactor) {
    updateBmpData();
   }
   var rect:Rectangle = new Rectangle(_txt_.x, _txt_.y, _txt_.width, _txt_.height);
   bmpData.fillRect(bmpData.rect, 0x00000000);
   var xOffset:Number = -_txt_.x;

   var dev:Number = magniFactor / 3;
   bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + 0, 0));
   bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + dev, 0));
   bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + 0, dev));
   bmpData.applyFilter(bmpData, bmpData.rect, new Point(0, 0), blurFilter);
   bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + dev / 2, dev / 2));

   bmp.x = _txt_.x;
   bmp.y = _txt_.y;
   validate = true;
  }
  
  //
  // Public Method
  //
  public function set validate(value:Boolean):void {
   _validate_ = value;
  }
  public function get validate():Boolean {
   return _validate_;
  }
  
  public function set useBitmapText(value:Boolean):void {
   _useBitmapText_ = value;
   _txt_.visible = !value;
   bmp.visible = value;
  }
  public function get useBitmapText():Boolean {
   return _useBitmapText_;
  }
  //
  // Override Method
  //
  public override function set width(w:Number):void {
   super.width = w;
   validate = false;
  }
  public override function set height(h:Number):void {
   super.height = h;
   validate = false;
  }
  public override function appendText(text:String):void {
   super.appendText(text);
   validate = false;
  }
  public override function replaceSelectedText(value:String):void {
   super.replaceSelectedText(value);
   validate = false;
  }
  public override function replaceText(beginIndex:int, endIndex:int, newText:String):void {
   super.replaceText(beginIndex,endIndex,newText);
   validate = false;
  }
  public override function setTextFormat(format:TextFormat, beginIndex:int = -1, endIndex:int = -1):void {
   super.setTextFormat(format,beginIndex,endIndex);
   validate = false;
  }
  public override function set defaultTextFormat(format:TextFormat):void {
   super.defaultTextFormat = format;
   validate = false;
  }
  
  public override function set antiAliasType(value:String):void {
   super.antiAliasType = value;
   validate = false;
  }
  public override function set autoSize(value:String):void {
   super.autoSize = value;
   validate = false;
  }
  public override function set gridFitType(value:String):void {
   super.gridFitType = value;
   validate = false;
  }
  public override function set htmlText(value:String):void {
   super.htmlText = value;
   validate = false;
  }
  public override function set restrict(value:String):void {
   super.restrict = value;
   validate = false;
  }
  public override function set text(value:String):void {
   super.text = value;
   validate = false;
  }
  
  public override function set backgroundColor(value:uint):void {
   super.backgroundColor = value;
   validate = false;
  }
  public override function set borderColor(value:uint):void {
   super.borderColor = value;
   validate = false;
  }
  public override function set textColor(value:uint):void {
   super.textColor = value;
   validate = false;
  }
  
  public override function set sharpness(value:Number):void {
   super.sharpness = value;
   validate = false;
  }
  public override function set thickness(value:Number):void {
   super.thickness = value;
   validate = false;
  }
  
  public override function set alwaysShowSelection(value:Boolean):void {
   super.alwaysShowSelection = value;
   validate = false;
  }
  public override function set border(value:Boolean):void {
   super.border = value;
   validate = false;
  }
  public override function set condenseWhite(value:Boolean):void {
   super.condenseWhite = value;
   validate = false;
  }
  public override function set displayAsPassword(value:Boolean):void {
   super.displayAsPassword = value;
   validate = false;
  }
  public override function set embedFonts(value:Boolean):void {
   super.embedFonts = value;
   validate = false;
  }
  public override function set multiline(value:Boolean):void {
   super.multiline = value;
   validate = false;
  }
  public override function set selectable(value:Boolean):void {
   super.selectable = value;
   validate = false;
  }
  public override function set wordWrap(value:Boolean):void {
   super.wordWrap = value;
   validate = false;
  }
  
 }
}

测试程序如下:

import com.ticore.text.*;

var bmpTxt:BitmapText = new BitmapText();
this.addChild(bmpTxt);
bmpTxt.border = true;
bmpTxt.multiline = true;
bmpTxt.rotation = 0;
bmpTxt.wordWrap = true;
bmpTxt.rotation = 15;
bmpTxt.width = 320;
bmpTxt.height = 250;
bmpTxt.x = 170;
bmpTxt.y = 30;

var format:TextFormat = bmpTxt.getTextFormat();
format.font = "新细明体";
format.align = "center";

for (var i:Number = 6; i <= 22; format.size=i; bmpTxt.defaultTextFormat=format; bmpTxt.appendText("Font Size format.size 新细明体\n");>

原始文件下载

实际运行效果撷图:

看起来应该还不错吧!
即使在旋转状态下也没有很严重的锯齿
我特别在绘制位图步骤提升了分辨率
并且作了偏移绘制,套用滤镜
当然这些动作是会消耗效能的
所以只有在必要时才会进行重绘的动作

Read more...

2008年6月14日 星期六

AS 技巧 - Layer BlendMode 的用处   [+/-]

Ticore's Blog

Flash Player 8 新增的混合模式功能中的图层模式 (Layer)
一般使用起来或许觉得没有什么特别的用处
说明文档上写得更是令人雾茫茫
简单的说,只是让 DisplayObject 子对象预先混和颜色而已

基本上,除了 Normal 之外的混合模式,都会强迫预先混和子对象颜色
但是其它混合模式都是有特殊效果的
假如不需要那些效果,但是又要强迫预先混合颜色时
就要用 Layer 混合模式了

对于像是 Flex 这样由大量的 DisplayObject 组合而成的组件
遇到需要淡入、淡出效果时
即使是在最外层设置 Alpha 透明度
每个子对象仍会先被单独套用 Alpha 效果再叠合成一张图
这样就会有某些位置颜色特别突兀不透明

此时 Layer 混合模式就非常好用了
它可以让整个表单先叠合成一张图再进行 Alpha 效果
可以确保组件颜色看起来不会特别突兀

以下是用 Flex 作的简单测试
可以容易观察到多层嵌套组件在不同 Alpha, BlendMode 的效果

<?xml version="1.0"?>
<mx:Application layout="vertical" fontSize="12" backgroundColor="#FFFFFF"
   xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Style>
  HBox.whiteBox {
   paddingTop: 15px;
   paddingBottom: 15px;
   paddingLeft: 15px;
   paddingRight: 15px;
   backgroundColor: #000000;
  }
 </mx:Style>
 <mx:HBox styleName="whiteBox" alpha="{alphaSlider.value}"
    blendMode="{blendModeCb.value ? blendModeCb.value : 'normal'}">
  <mx:HBox styleName="whiteBox">
   <mx:HBox styleName="whiteBox">
    <mx:HBox styleName="whiteBox" />
   </mx:HBox>
  </mx:HBox>
 </mx:HBox>
 
 <mx:HRule width="100%" />
 <mx:HBox verticalAlign="middle">
  <mx:Label text="BlendMode: " />
  <mx:ComboBox id="blendModeCb">
   <mx:dataProvider>
    ["normal", "layer", "darken", "invert", "hardlight"]
   </mx:dataProvider>
  </mx:ComboBox>
 </mx:HBox>
 <mx:HBox verticalAlign="middle">
  <mx:Label text="Alpha: " />
  <mx:HSlider id="alphaSlider" value="0.5"
    tickValues="[0, 0.5, 1]" labels="[0, 0.5, 1]"
    minimum="0" maximum="1" liveDragging="true" />
 </mx:HBox>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

线上测示示范:

相关连结:
Flex Label, TextField 半透明小技巧
Flash 8 半透明输入、动态文字字段

Read more...

2008年5月18日 星期日

Flash Player 10 beta - JPEGLoaderContext 介绍   [+/-]

Ticore's Blog

最近 Flash Player 10 beta 出了
各大网站、Blog 已经有太多相关文章了
在此不再赘述

除了那些官方列出来的新功能之外
还有一些是没有被发现的
像是 flash.system::JPEGLoaderContext 类别

先来利用 describeType 观察一下 JPEGLoaderContext

import flash.system.*;
import flash.utils.*;
trace(describeType(JPEGLoaderContext));

可以得到以下输出结果:

<type name="flash.system::JPEGLoaderContext"
  base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.system::JPEGLoaderContext">
    <extendsClass type="flash.system::LoaderContext"/>
    <extendsClass type="Object"/>
    <constructor>
      <parameter index="1" type="Number" optional="true"/>
      <parameter index="2" type="Boolean" optional="true"/>
      <parameter index="3" type="flash.system::ApplicationDomain" optional="true"/>
      <parameter index="4" type="flash.system::SecurityDomain" optional="true"/>
    </constructor>
    <variable name="deblockingFilter" type="Number"/>
    <variable name="applicationDomain" type="flash.system::ApplicationDomain"/>
    <variable name="securityDomain" type="flash.system::SecurityDomain"/>
    <variable name="checkPolicyFile" type="Boolean"/>
  </factory>
</type>

从名称上看起来,用途应该是与 LoaderContext 类似的
然后是用来处理外部 JPEG 图档
只是多了一个 deblockingFilter 变量
看起来也很像是去马赛克用的

以下便是实际使用示范:(需要自行准备一个外部图档 img.jpg)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  initialize="init();" layout="horizontal" backgroundColor="#FFFFFF">
 <mx:Script>
  <![CDATA[
   import flash.system.*;
   import flash.utils.*;
   
   [Bindable]
   public var jpgLdrCxt1:JPEGLoaderContext = new JPEGLoaderContext(0);
   public var jpgLdrCxt2:JPEGLoaderContext = new JPEGLoaderContext(1);
   
   public function init():void{
    
    trace(describeType(JPEGLoaderContext));
    
    img1.loaderContext = jpgLdrCxt1;
    img1.source = "img.jpg";
    img2.loaderContext = jpgLdrCxt2;
    img2.source = "img.jpg";
   }
  ]]>
 </mx:Script>
 <mx:Image id="img1" scaleX="1.5" scaleY="1.5" />
 <mx:Image id="img2" scaleX="1.5" scaleY="1.5" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

以下是实际用 Flash Player 10.0.1.218 运行的效果

可以明显看得出来其中的差异
deblockingFilter 值大约是在 0-1 之间
超过 1 以上就没有太大的差异了
假如再加上 Bitmap.smoothing 会得到更好的效果

相关连结:
Flash Player 10 beta - 新的影格事件
Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x
Flash Player 10 beta - MouseCursor 功能

Read more...

2008年4月20日 星期日

ActionScript width, height pitfall   [+/-]

Ticore's Blog

Flash 的图像对象尺寸指定上,有一个很容易犯错的陷阱
举例来说,以下的 AS3 程序会动态创建黑色矩形 MovieClip
但是实际运行,却没有办法看到任何东西

import flash.display.MovieClip;

var mc:MovieClip = new MovieClip();
this.addChild(mc);

mc.width = mc.width;

with (mc.graphics) {
 beginFill(0, 0.5);
 drawRect(0, 0, 100, 100);
 endFill();
}

mc.scaleX = 1;

只要在最后重新设置一次 scaleY 为 1 就会正常了

import flash.display.MovieClip;

var mc:MovieClip = new MovieClip();
this.addChild(mc);

mc.width = mc.width;

with (mc.graphics) {
 beginFill(0, 0.5);
 drawRect(0, 0, 100, 100);
 endFill();
}

mc.scaleX = 1;
mc.scaleY = 1;

主要原因可能是在 MovieClip 内没有任何图像时
指定其 width 为 0,会同时导致 scaleX, scaleY 变成 0~

Read more...

2007年10月28日 星期日

两种使用 Flash 开发 Flex Skin 方式比较   [+/-]

Ticore's Blog

一般在 Flex 中使用外部 Graphical Skin
都是用 Embed 标签来嵌入外部 SWF or PNG、JPG....
假如以 Flash 集成,可以用更方便的做法

那便是用 Flash 输出 SWC 类别库之后
直接在 Flex 内引用 Symbol Class
优点如下:

  • 不必额外撰写 Embed 标签
  • 可以保留 Flash Symbol 内的 ActionScript (使用 Embed 无法保留 Symbol AS)
  • 具有较好的程序码提示功能

保留 ActionScript,意味着可以同时混和 Graphical Skin、Programmatic Skin
直接作出 Hybrid Skin,有些情况会很方便

相关连结:
用 Flash 开发 Flex Skin 才是王道
在 Flash 作位图九宫格缩放技巧
Flex Embed 位图档小技巧
Flex Embed 外部资源技巧

Read more...

2007年10月20日 星期六

用 Flash 开发 Flex Skin 才是王道   [+/-]

Ticore's Blog

日前 Adobe Labs 推出了许多外挂 Adobe Labs - Flex Skin Design Extensions
可以让设计师容易使用 Flash、Photoshop、Illustrator、Fireworks 开发 Flex Skin
但是 Flex 原本就是 SWF Base 的东西
自然以 SWF 为来源,可以达到最好的效果
以下是四种软件输出 Flex Skin 功能比较:

时间轴
影格标签
Tween 动画
ActionScript
位图
位图
九宫格缩放
矢量图
矢量图
九宫格缩放
位图柔化
Flash
Illustrator
×
×
×
×
Photoshop
×
×
×
×
×
Fireworks
×
×
×
×
×

由上表看来,使用 Flash 作为 Flex Skin 最后输出工具才是最好选择
这并不代表,其它三种软件没有用
因为 Flash 本身画图工具不够,还是需要绘图软件辅助

相关连结:
两种使用 Flash 开发 Flex Skin 方式比较
在 Flash 作位图九宫格缩放技巧
Flex Embed 位图档小技巧

Read more...

2007年10月6日 星期六

在 Flash 作位图九宫格缩放技巧   [+/-]

Ticore's Blog

Flash 8、9 虽然有支持 Scale 9 缩放功能
但是仅限于矢量对象
MovieClip 的 Scale 9 设置对位图并没有效果
以下介绍一个技巧,可以让 Flash Scale 9 功能也能应用在位图上

先将位图包成 MovieClip,并勾选 Scale 9 设置

将位图打散成为矢量填色区块

沿着 Scale 9 Grid 划线,将位图填色区块切割开

最后,把九个填色区块个别包成组,删除切割用的线条
这样该 MovieClip 便可以用 Scale 9 模式缩放了

Flash 位图九宫格 (Scale 9) 缩放比较

相关连结:
Flex Embed 位图档小技巧
用 Flash 开发 Flex Skin 才是王道

Read more...

Flex Embed 位图档小技巧   [+/-]

Ticore's Blog

Flex 可以使用 Embed 标签,指定外部图档素材
但是透过这种方式汇入的图片默认是无抗锯齿效果的
虽然可以自行用 AS3 重新以 smooth 方式 draw
不过实在太麻烦

先看看直接 Embed 图档的情况,有很严重的锯齿

以下介绍利用 Flash 改善位图锯齿

将图档汇入 Flash,并且勾选 Allow smoothing 选项

将图片包成一个 MovieClip,并输出 SWF
在 Flex MXML 内指定 Embed 标签

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 width="120" height="112"
 backgroundImage="@Embed(source='assets.swf', symbol='fx')">
</mx:Application>

运行结果

相关连结:
用 Flash 开发 Flex Skin 才是王道
在 Flash 作位图九宫格缩放技巧
Flex Embed 外部资源技巧

Read more...

2007年7月17日 星期二

Degrafa - A Flex Graphics Framework   [+/-]

Ticore's Blog

MS SilverLight 提供相当完整的 XML 描述矢量图形的方式
Flex 在这方面显得非常缺乏
只能采用 AS3 程序画图,或是嵌入 Flash 预先画好的 Assets

Degrafa 便是补 Flex 这方面的不足
让 Flex Developer 也可以用 XML 描述图像
不过当前还没有 release

据称 Degrafa 可以用以下的 XML 画出 11 条垂直线:

<Strokes>
    <mx:Stroke id="OrangeStroke" color="#EE9819" />
</Strokes>
<Geometry:Line Stroke="{OrangeStroke}"
    x="10" y="10" x1="0" y1="100"/>
<Geometry:Line Stroke="{OrangeStroke}"
    x="10" y="10" x1="0" y1="100">
    <Geometry:repeater>
        <Repeaters:LineRepeater count="11" moveOffsetX="10"
            moveOffsetY="0" offsetX="10" offsetY="0"/>
    </Geometry:repeater>
</Geometry:Line>
Read more...

2006年11月9日 星期四

动态读取外部 PNG 作为 Alpha Mask   [+/-]

Ticore's Blog

看到邦邦的问题
http://mmug.com.tw/forum/viewtopic.php?p=39227

测试出来的结果如下:



SWF URL:
http://riafiles.googlepages.com/gradientMask.swf

PNG URL:
http://riafiles.googlepages.com/gradientMask.png

关键应该是在设置 mask.cacheAsBitmap 的时机

ActionScript:

var maskURL:String = maskURL == null ? "gradientMask.png" : maskURL;

import flash.geom.*;

var maskee:MovieClip = this.createEmptyMovieClip("maskee", 100);
var masker:MovieClip = this.createEmptyMovieClip("masker", 200);

with (maskee) {
    colors = [0xFF0000, 0x0000FF];
    fillType = "radial"
    alphas = [100, 100];
    ratios = [0, 0xFF];
    spreadMethod = "reflect";
    interpolationMethod = "linearRGB";
    focalPointRatio = 0.9;
    matrix = new Matrix();
    matrix.createGradientBox(100, 100, Math.PI, 0, 0);
    beginGradientFill(fillType, colors, alphas, ratios, matrix, 
        spreadMethod, interpolationMethod, focalPointRatio);
    moveTo(0, 0);
    lineTo(550, 0);
    lineTo(550, 200);
    lineTo(0, 200);
    lineTo(0, 0);
    endFill();
}


var mcLoader:MovieClipLoader = new MovieClipLoader();
var mcLisObj:Object = {};
mcLisObj.onLoadInit = function(evtObj):Void{
 masker.cacheAsBitmap = true;
 masker.onPress = function():Void{
  startDrag(this);
 };
 masker.onRelease = masker.onReleaseOutside = function():Void{
  stopDrag();
 };
 maskee.cacheAsBitmap = true;
 maskee.setMask(masker);
};
mcLoader.addListener(mcLisObj);
mcLoader.loadClip(maskURL, masker);
// Ticore's Blog - http://ticore.blogspot.com/
Read more...

2005年9月21日 星期三

Flash 8 AS2 位图双线性取样函式   [+/-]

Ticore's Blog

既然 Flash 8 可以直接操作点阵资料
那就可以用来实作一些图象处理的功能了
以下便是用 AS 作位图双线性重新取样函式

不过这只是个人研究用的
毕竟AS跑大量回圈还是比不上 Native 程序
所以并不具有实用的价值

真正欲做位图缩放,可以使用 Matrix + draw
至少比 AS Implement 的快上100倍

/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
import flash.display.*;
import flash.geom.*;

//=======================================================================

function resizeTo(width:Number, height:Number, img:BitmapData):BitmapData {
var temp:BitmapData = new BitmapData(width, height, true, 0xFF000000);

var p0:Point = new Point();
var p1:Point = new Point();
var p2:Point = new Point();
var p3:Point = new Point();
var p4:Point = new Point();

var c1:Number;
var c2:Number;
var c3:Number;
var c4:Number;

var a:Number;
var r:Number;
var g:Number;
var b:Number;

var dx:Number;
var dy:Number;
var cdx:Number;
var cdy:Number;

var dtl:Number;
var dtr:Number;
var dbl:Number;
var dbr:Number;

for(var i:Number = 0 ; i < width ; ++i){
for(var j:Number = 0 ; j < height ; ++j){
p0.x = i / width * (img.width -1);
p0.y = j / height * (img.height - 1);
p1.x = Math.floor(p0.x);
p1.y = Math.floor(p0.y);
p2.x = p1.x + 1;
p2.y = p1.y;
p3.x = p1.x + 1;
p3.y = p1.y + 1;
p4.x = p1.x;
p4.y = p1.y + 1;

c1 = img.getPixel32(p1.x, p1.y);
c2 = img.getPixel32(p2.x, p2.y);
c3 = img.getPixel32(p3.x, p3.y);
c4 = img.getPixel32(p4.x, p4.y);

dx = p0.x - p1.x;
dy = p0.y - p1.y;
cdx = 1 - dx;
cdy = 1 - dy;

dtl = dx * dy;
dtr = cdx * dy;
dbr = dx * cdy;
dbl = cdx * cdy;

a = ((c1 & 0xFF000000) * dbl
+ (c2 & 0xFF000000) * dbr
+ (c3 & 0xFF000000) * dtl
+ (c4 & 0xFF000000) * dtr) & 0xFF000000;

r = ((c1 & 0x00FF0000) * dbl
+ (c2 & 0x00FF0000) * dbr
+ (c3 & 0x00FF0000) * dtl
+ (c4 & 0x00FF0000) * dtr) & 0x00FF0000;

g = ((c1 & 0x0000FF00) * dbl
+ (c2 & 0x0000FF00) * dbr
+ (c3 & 0x0000FF00) * dtl
+ (c4 & 0x0000FF00) * dtr) & 0x0000FF00;

b = ((c1 & 0x000000FF) * dbl
+ (c2 & 0x000000FF) * dbr
+ (c3 & 0x000000FF) * dtl
+ (c4 & 0x000000FF) * dtr) & 0x000000FF;

temp.setPixel32(i , j , a | r | g | b);
}
}
return temp;
}

//=======================================================================
Read more...