おいしいAS3 -41ページ目

TextFieldに文字スタイルを指定しながらテキストを追加する

Pageクラスに静的メソッドで追加したもの

addText(myTextField,"なんとかかんとか",myTextFormat,"なんとかかんとか",myTextFormat......)
ってかんじで最初にテキストフィールドを指定してその後
追加する文字の内容とテキストフォーマットを交互に入れていく


function addText(fld:TextField,...arg){
for(var i=0;i<arg.length-1;i+=2){
var orgLen=fld.text.length
fld.appendText(arg[i])
var newLen=fld.text.length
if(newLen>orgLen)fld.setTextFormat(arg[i+1],orgLen,newLen)
}
}



きっと活躍してくれるだろう


配列をそのままargumentsクラスに
変換して引数にできたら便利なのにって思うんだけど
なんでさせてくれないのかな・・・



追記:2/27
追加する文字が0文字だとエラーが出たんで
ちょっと修正しました

Pageクラス、そろそろ無理だな

もうすぐ300行

だけどまだ一番しっぽの
スライドメニュー生成のやつ以外は
最低限用意しとくべきメソッドだと
個人的には思う所です

コンストラクタの第二引数の
設定項目にindexを追加
indexに設定されたフィールドはインデックスとして
クリックすると対応するカテゴリの行の配列を
onSelectFuncに渡して実行するインデックスが
indexes配列プロパティに入れられます

onCompFuncでindexesを
どっかに並べて配置して
カテゴリーインデックスとかにするわけです

setIndexStyle()でそのインデックスの
通常、接触、訪問中、訪問済みの文字スタイルを
設定できるようにしてあります

trimIcon()で一括全部アイコンのサイズ調整するようにしました


Sprite拡張クラスでアイコンをマスクするのも追加しようと思ってます

静的メソッドでも文字スタイルを指定しながら
テキストフィールドにテキストを追加していく
メソッドが入用であろうと考えてます

このあたりまではこのクラスの役割として
最低限用意しておくべきと思う所

言ってる事変わった?
気にしたら負けです

多分また500行ぐらいになるのでしょう
いつものことです

しかしそろそろブログに
コード全部のせるのは限界でしょうかね


/*
CSVクラス等が読み込んだ
テーブルデータを元に
指定されたフィールドの画像やタイトル等を受けて
ロールオーバー時、ロールアウト時、クリック時
それぞれが対応するオブジェクトを引数として
指定の関数を実行するアイコンを生成します


■パブリックプロパティ
dataSource テーブルデータをロードしてコンプリートイベントを発生させるクラスのインスタンス
data 読み込んだテーブルデータの指定のフィールドを画像や動画で置き換えたオブジェクトの配列、iconフィールドのみ追加の形

icons マウスイベントを受けて対応する行を引数に関数を実行するアイコンの配列
indexes クリックで対応する行の配列を引数に関数を実行するインデックスの配列

onCompFunc dataプロパティがそろったときにdataプロパティを引数に実行される関数、主にアイコンをレイアウトする為に使う
onOverFunc アイコンのロールオーバー時に各オブジェクトを引数に実行される関数、主に内容の説明を表示する為に使う
onOutFunc アイコンのロールアウト時に各オブジェクトを引数に実行される関数、主に内容の説明の表示終了の為に使う
onClickFunc アイコンのクリック時に各オブジェクトを引数に実行される関数、主に内容をレイアウトして表示する為に使う

■パブリックメソッド
Page(テーブルデータ、データ構成)
・データ構成
 icon アイコンとなる画像のURLが入ったフィールド
 index インデックスとなるフィールド
 images データロード後画像をロードする画像のURLのフィールドの配列

trimIcon(幅、高さ) アイコンのイメージのサイズを指定値に収まるように拡大縮小、クロップします
setIndexStyle(スタイルオブジェクト) インデックスの通常、接触、訪問中、訪問済みのフォーマットをセッティングします
・スタイルオブジェクト
 font 4つの状態に共通のフォント
 colors 4つの状態に応じた4つの色、ただし3つ以下でも接触と訪問済みは通常で、訪問中は接触で補完されます
 sizes 4つの状態に応じた4つの文字サイズ、ただし3つ以下でもcolorsと同じ補完をします
 def 通常の文字スタイルとなるTextFormat、これを設定するとfont、colorsやsizesは無視します
 over 接触時の文字スタイルとなるTextFormat、これを設定するとfont、colorsやsizesは無視します
 act 訪問中の文字スタイルとなるTextFormat、これを設定するとfont、colorsやsizesは無視します
 past 訪問済みの文字スタイルとなるTextFormat、これを設定するとfont、colorsやsizesは無視します

search({フィールド名:値,.....})

*/

package simplizer.page{

import flash.display.*
import flash.text.*
import flash.events.*
import flash.geom.*
import flash.net.URLRequest

public class Page extends EventDispatcher{

public var dataSource:EventDispatcher
public var data:Array=new Array()
public var onCompFunc:Function=function(data:Array){}
public var onSelectFunc:Function=function(data:Array){}
public var onOverFunc:Function=function(tgt:Object){}
public var onOutFunc:Function=function(tgt:Object){}
public var onClickFunc:Function=function(tgt:Object){}

public var icons:Array=new Array()
public var indexes:Array=new Array()

private var images:Array=new Array()

public function Page(src:EventDispatcher,fldObj:Object){
dataSource=src
fldObj.icon=fldObj.icon||""
fldObj.index=fldObj.index||""
fldObj.images=fldObj.images||[]
fldObj.dummyIcon=fldObj.dummyIcon||"noimage.jpg"
fldObj.dummyImage=fldObj.dummyImage||"noimage.jpg"
src.addEventListener(Event.COMPLETE,init)
function init(e){
//アイコン生成、画像読み込み開始、テーブルデータをdataに代入
for each(var row in (src as Object).data){
var newRow=new Object()
for(var col in row){
if(col==fldObj.icon){
newRow.icon=new MovieClip()
icons.push(newRow.icon)
if(fldObj.images.some(function(tgt){return (tgt==col)})){
newRow.icon.image=newRow.icon.addChild(new Loader())
images.push(newRow.icon.image)
with(newRow.icon.image){
load(new URLRequest(row[col]||fldObj.dummyIcon))
}
}else{
newRow.icon.text=newRow.icon.addChild(new TextField())
with(newRow.icon.text){
text=row[col]
background=true
selectable=false
}
}
with(newRow.icon){
addEventListener(MouseEvent.ROLL_OVER,makeListener("Over",newRow))
addEventListener(MouseEvent.ROLL_OUT,makeListener("Out",newRow))
addEventListener(MouseEvent.CLICK,makeListener("Click",newRow))
}
}
if(fldObj.images.some(function(tgt){return (tgt==col)})){
newRow[col]=new Loader()
newRow[col].load(new URLRequest(row[col]||fldObj.dummyImage))
images.push(newRow[col])
}else{
newRow[col]=row[col]
}
}
data.push(newRow)
}
//インデックスを生成
for each(var ind in getValuesOf(fldObj.index)){
var newIndex:MovieClip=new MovieClip()
var keyObj:Object=new Object
keyObj[fldObj.index]=ind
with(newIndex){
buttonMode=true
addEventListener(MouseEvent.CLICK,makeListener("Select",search(keyObj)))
}
newIndex.textField=newIndex.addChild(new TextField())
with(newIndex.textField){
text=ind||"no title"
width=textWidth
height=textHeight
selectable=false
}
indexes.push(newIndex)
}
//画像読み込み完了待機
addEventListener(Event.COMPLETE,makeListener("Comp"))
var cnt=images.length
if(cnt==0)this.dispatchEvent(new Event(Event.COMPLETE))
for each(var img in images){
img.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e){
e.target.removeEventListener(e.type,arguments.callee);
cnt--;
if(cnt==0)dispatchEvent(new Event(Event.COMPLETE));})
}
}
function makeListener(type:String,tgt:Object=null):Function{
switch(type){
case "Select":
return function(e){onSelectFunc(tgt)}
break;
case "Over":
return function(e){onOverFunc(tgt)}
break;
case "Out":
return function(e){onOutFunc(tgt)}
break;
case "Click":
return function(e){onClickFunc(tgt)}
break;
case "Comp":
return function(e){onCompFunc(data)}
break;
default:
return null
}
}
}
//スタイル
public function trimIcons(W:Number,H:Number){
for each(var icon in icons){
var maskSpr:Sprite=new Sprite()
with(maskSpr.graphics){
beginFill(0)
drawRect(0,0,W,H)
endFill()
}
with(icon.image){
scaleX=scaleY=Math.max(W/width,H/height)
}
icon.addChild(maskSpr)
icon.mask=maskSpr
}
}
public function setIndexStyle(strObj:Object){
strObj.font=strObj.font||"ヒラギノ明朝 Pro W6"
strObj.sizes=strObj.sizes||[11,12,12,11]
strObj.colors=strObj.colors||[0x888888,0x448888,0x00AAAA,0xAAAAAA]
strObj.def=strObj.def||new TextFormat(strObj.font,strObj.sizes[0],strObj.colors[0])
strObj.over=strObj.over||new TextFormat(strObj.font,strObj.sizes[1]||strObj.sizes[0],strObj.colors[1]||strObj.colors[0])
strObj.act=strObj.act||new TextFormat(strObj.font,strObj.sizes[2]||strObj.sizes[1]||strObj.sizes[0],strObj.colors[2]||strObj.colors[1]||strObj.colors[0])
strObj.past=strObj.past||new TextFormat(strObj.font,strObj.sizes[3]||strObj.sizes[0],strObj.colors[3]||strObj.colors[0])
for each(var ind in indexes){
ind.isVisiting=false
ind.isVisited=false
with(ind.textField){
defaultTextFormat=strObj.def
setTextFormat(defaultTextFormat)
width=textWidth+10
height=textHeight+10
}
ind.addEventListener(MouseEvent.MOUSE_OVER,onEvent)
ind.addEventListener(MouseEvent.MOUSE_OUT,onEvent)
ind.addEventListener(MouseEvent.CLICK,onEvent)
}
function onEvent(e){
with(e.currentTarget){
switch(e.type){
case MouseEvent.MOUSE_OVER:
if(!isVisiting)textField.setTextFormat(strObj.over)
break;
case MouseEvent.MOUSE_OUT:
if(!isVisiting){
if(isVisited){
textField.setTextFormat(strObj.past)
}else{
textField.setTextFormat(strObj.def)
}
}
break;
case MouseEvent.CLICK:
for each(var ind in indexes){
if(ind.isVisiting){
ind.isVisiting=false
ind.textField.setTextFormat(strObj.past)
}
}
isVisiting=true
isVisited=true
textField.setTextFormat(strObj.act)
break;
}
textField.width=textField.textWidth+10
textField.height=textField.textHeight+10
}
}
}
//補助
public function search(keyObj,andFrg:Boolean=true):Array{
var rtn=new Array()
var filterFnc=function(tgt){
var frg:Boolean=false
for(var nm in keyObj){
frg=tgt[nm]==keyObj[nm]
if(frg){
break;
}else if(andFrg){
break;
}
}
if(frg)frg=rtn.indexOf(tgt)==-1
return frg
}
rtn=data.filter(filterFnc)
return rtn
}
public function getValuesOf(fName:String):Array{
var rtn:Array=new Array()
for each(var row in data){
if(rtn.indexOf(row[fName])==-1&&(fName in row))rtn.push(row[fName])
}
return rtn
}
//静的メソッド
public static function slideMenu(rowList:Array,paramObj:Object):Sprite{
var rtn=new Sprite()
paramObj.margine=paramObj.margine||120
paramObj.width=paramObj.width||550
for(var i in rowList){
rtn.addChild(rowList[i].icon)
}
rtn.addEventListener(Event.ADDED_TO_STAGE,function(e){rtn.addEventListener(Event.ENTER_FRAME,frameTick)})
rtn.addEventListener(Event.REMOVED_FROM_STAGE,function(e){rtn.removeEventListener(Event.ENTER_FRAME,frameTick)})
var totalLen=rowList.length*paramObj.margine
var dst=0
function frameTick(e){
dst=dst+(rtn.mouseX*(totalLen-paramObj.width)/paramObj.width-dst)/8
for(i in rowList){
var minX=i*5
var maxX=paramObj.width-rowList[i].icon.width+(i-rowList.length+1)*5
rowList[i].icon.x=Math.min(Math.max(-dst+i*paramObj.margine,minX),maxX)
if(rowList[i].icon.x>paramObj.width/2){
rtn.setChildIndex(rowList[i].icon,0)
}else{
rtn.setChildIndex(rowList[i].icon,rtn.numChildren-1)
}
}
}
return rtn
}
}
}

e.targetとe.currentTargetの違い

EventクラスのtargetとcurrentTargetっていう
イベントを発信したやつを取得するプロパティ

今まで『何が違うの?』ってカンジだったんですが
今頃なにが違うのかわかりました


var MC=new MovieClip()
var MCchild=MC.addChild(new Sprite())
with(MC.graphics){
beginFill(0x88FFFF)
drawRect(0,0,150,150)
endFill()
}
with(MCchild.graphics){
beginFill(0x55CCCC)
drawRect(50,50,50,50)
endFill()
}
MC.name="親"
MCchild.name="子供"
addChild(MC)

MC.addEventListener(MouseEvent.CLICK,listener)

function listener(e:Event):void{
trace("■結果")
trace("currentTarget = "+e.currentTarget.name)
trace("target     = "+e.target.name)
}



そうだったのか・・・

危うく『どうなってんのコレ!?子を取得しちゃうよ?バグ!?』とかいって
赤恥かくとこでした

『あれ?そういえばなんかターゲット取得って二つあったよな?』と
その場で思いとどまってよかったです