swfmillでケータイFlashの配色を動的に一括変更してみよう

By ookura - 09/12/21 - このエントリをはてなブックマークに追加このエントリをYahoo!ブックマークに追加このエントリをdel.icio.usに追加このエントリをFC2ブックマークに追加

携帯Flashを作成していくと、Flash内の配色を動的にカスタマイズする必要が出てくるケースもあるかと思います。
今回はFlash内の文字・背景・ベクター画像の配色をswfmillで動的に変更する方法についてご紹介します。
 
 

画面イメージ

 
 

実現方法

swfmillで変換されたXML内の色要素の文字列を置換することで実現できます。
 
swfファイルを作成する際にあらかじめ設定別に各テキスト・ベクター画像の配色を分けて作成しておきます。
テキストの色も同じ方法で置換できてしまいますのでテキストと別の色設定にしたい場合はテキストも別の色を指定しておきます。
※テキストは静止テキスト・ダイナミックテキスト・テキスト入力のいずれでも色変更可能です。
 
グラデーションもグラデーション内の特定のカラーがデータとして存在しますので、それぞれ変換すれば色を変更することができます。
 
同じグラフィックでもビットマップ画像の場合はXMLにした際にカラーが取得できませんのでこちらは別の方法で置換する必要があります。
 
XMLの内部では配色はRed,Green,Blueの各色要素別に10進数で表現されています。
例:赤色の設定を青色に変更する場合

<color>
  <Color red="255" green="0" blue="0"/>
</color>


これをXML内で検索して特定の文字に変換しておき、再度変換したい配色を指定した文字列に変換してswfに戻すことで配色を変更することができます。
特定の文字列に置換

<color>
  <Color {$color01}/>
</color>


青色の設定に置換

<color>
  <Color red="0" green="0" blue="255"/>
</color>

配色ごとに個別に順番に変換してしまうと既に変換した配色を別の色置換処理で再度変更してしまう可能性がありますので、
一度全て特定の文字に置換してから変換先の色設定に置換するように注意してください。
 
swfmillで変換出力されるXML内の配色の書式については下記をご参照下さい。
→参照:「swfmillで出力されるXMLを解析してみよう」
 
※XMLをオブジェクトや配列に変換して扱った方が厳密な置換処理が可能ではあるのですが、本サンプルではシンプルに考えるために文字列として扱っています。
 
 

仕様

・ステージ上には静止テキストが3つ、グラデーションを設定したシェイプが一つ、線が一つ配置されています。
 
・スキンを変更すると各スキンに設定された配色に変更して出力されます。
 
 

SWFファイルの制作手順

・パブリッシュバージョンはFlashLite1.1とします。
 
・ステージサイズは240px×240pxとします。
 
・静止テキストを作成し、「_等幅」12pxで配置します。
 
・矩形ツールで四角いシェイプを配置し、40×480pxで左寄せ、Y座標-120の位置に配置します。
四角いシェイプは左から右にかけて線形グラデーションを指定します。右側の色は背景と同じにします。
 
・幅2pxの線ツールで線を2つ配置します。2つの線は同じ色にしておきます。
 
・パブリッシュして完成です。
 
 

PHPファイルソース

sample5057.php

<?php
/* 
 * ケータイFlashの配色を変更して出力するサンプル
 */

// 置換スキンを指定
$skin = intval($_GET['skin']);
    
// SWFファイルの内容を取得
$swfData = file_get_contents('sample5057.swf');

// 変換する配色設定
$replaceColor = array(
    // オリジナル
    'original' => array(
        'back'        => '#FFFFFF',
        'left'        => '#0099CC',
        'line'        => '#6666CC',
        'titleText'   => '#336600',
        'contentText' => '#666600',
        'footerText'  => '#333333',
    ),
    // スキン1
    'skin1' => array(
        'back'        => '#FFFFFF',
        'left'        => '#FD970F',
        'line'        => '#FFCC00',
        'titleText'   => '#F70000',
        'contentText' => '#EE4F02',
        'footerText'  => '#660000',
    ),
    // スキン2
    'skin2' => array(
        'back'        => '#E3F1C7',
        'left'        => '#339933',
        'line'        => '#CCCC00',
        'titleText'   => '#996633',
        'contentText' => '#006600',
        'footerText'  => '#666600',
    ),
    // スキン3
    'skin3' => array(
        'back'        => '#333333',
        'left'        => '#33CCCC',
        'line'        => '#00CCCC',
        'titleText'   => '#CCFFCC',
        'contentText' => '#FFFFFF',
        'footerText'  => '#CCCCCC',
    ),
);

// 該当するスキンの有無を確認
if (!isset($replaceColor["skin{$skin}"])) {
    exit;
}

// SWFからXMLに変換
$xmlString = swfConvert($swfData, 'swf2xml', 'cp932');

// 元ファイルの色設定を設定名に置換
foreach($replaceColor['original'] as $key => $value){
    // RGBに分解して10進数に変換
    $colorRed   = hexdec(substr($value,1,2));
    $colorGreen = hexdec(substr($value,3,2));
    $colorBlue  = hexdec(substr($value,5,2));
    $colorString = 'red="' . $colorRed . '" green="' . $colorGreen . '" blue="' . $colorBlue . '"';
    $xmlString  = str_replace($colorString, '{$' . $key . '}', $xmlString);
}

// 設定名を各スキンの色設定に置換
foreach($replaceColor["skin{$skin}"] as $key => $value){
    // RGBに分解して10進数に変換
    $colorRed    = hexdec(substr($value,1,2));
    $colorGreen  = hexdec(substr($value,3,2));
    $colorBlue   = hexdec(substr($value,5,2));
    $colorString = 'red="' . $colorRed . '" green="' . $colorGreen . '" blue="' . $colorBlue . '"';
    $xmlString   = str_replace('{$' . $key . '}', $colorString, $xmlString);
}

// XMLからSWFに変換
$swfOutput = swfConvert($xmlString, 'xml2swf', 'cp932');

// SWFのヘッダを出力
header('Content-type: application/x-shockwave-flash');

// SWFのデータを出力
echo $swfOutput;

// SWFとXMLを相互変換する関数
function swfConvert($input, $command = 'swf2xml', $swfmillEncode = 'UTF-8') {
    
    // 変換コマンドをチェック
    if (!in_array($command, array('swf2xml', 'xml2swf'))) {
        return false;
    }
    // エンコード指定をチェック
    if (!in_array($swfmillEncode, array('cp932', 'UTF-8'))) {
        return false;
    }
    
    // 入出力の指定
    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("file", "error-output.txt", "a")
    );
    
    // swfmillコマンドを実行してリソースとファイルポインタを取得
    $process = proc_open('/usr/local/bin/swfmill -e ' . $swfmillEncode . ' ' . $command . ' stdin stdout', $descriptorspec, $pipes);
    
    if (is_resource($process)) {
        
        // 標準入力にXMLデータを書き込み
        fwrite($pipes[0], $input);
        fclose($pipes[0]);
        
        // 標準出力からSWFファイルのバイナリデータを読み込み
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        
        // パイプを全て閉じてからプロセスを閉じる
        proc_close($process);
    }
    return $output;
}

※今回からはswfmill変換処理を関数にまとめてみました。
※UTF-8で記述しています。
※同階層に書き込み可能権限で「error-output.txt」を配置しています。
 
 

備考

・FlashLite2.0以降の場合はActionScriptを併用することでFlash内でさらに文字列や文字列の一部の配色を変更することができます。
→参照:「ケータイFlashの文字色を動的に変更してみよう」
→参照:「ケータイFlashのテキストにHTMLのようなリンクをつけるには」
 
・ビットマップ画像を差し替える場合はバイナリデータを置換することで可能です。
→参照:「swfmillでケータイFlashを動的生成してみよう(画像置換編)」
 
 

実行例

実行例はこちらからご確認下さい。

URLをメールで送る
http://ookura.tanikaze.com/Sample/post5057/
 
 

サンプルファイル

sample5057.zip
上記サンプルのFlashファイル一式です。
 
 

関連ページ

ケータイFlash関連の記事一覧