| INDEX |

Tweenerにはベジェ曲線上をトゥイーンさせるプロパティ「_bezier」があるのだけど、曲線の座標を指定するのが面倒だったりなかったりします。できればガイドのように自分で描いた曲線をトゥイーンさせたい。で、ペンツールなどで描いた曲線からTweenerの_bezier用のスクリプト出力する簡単なJSFLをつくってみた。

とりあえず、できあがりはこんな感じ。グレーの曲線がペンツールで描いた曲線です。

手順としては、まず下のスクリプトを適当なファイルに保存します。例えば「makeBezierTweenOption.jsfl」とかいうファイル名で。

//****************************************************************************
// Script for Tweener _bezier Option
//
// sample output : { x:460, y:100, _bezier:[{x:250, y:200},{x:355, y:150}] }
//****************************************************************************

var edgeArray = fl.getDocumentDOM().selection[0].edges;

var tmp  = [];
var tmp2 = [];
for ( i=0; i<edgeArray.length; i++ )
  tmp.push( edgeArray[i] );

var e0 = tmp.shift();
tmp2.push( e0 );
joinX0 = e0.getControl(0).x;
joinY0 = e0.getControl(0).y;
joinX2 = e0.getControl(2).x;
joinY2 = e0.getControl(2).y;

while( tmp2.length<edgeArray.length )
{
  is_not_join = true;
  var min_value = -1;
  var min_pos   = -1;
  var min_index = -1;
  for( i=0; i<tmp.length; i++ )
  {
    var ed = tmp[i];
    var p0 = ed.getControl(0);
    var p2 = ed.getControl(2);
    if( p0.x==joinX2 && p0.y==joinY2 )
    {
      is_not_join = false;
      tmp2.push( ed );
      joinX2 = p2.x;
      joinY2 = p2.y;
      tmp.splice( i, 1 );
      i = 0;
    }
    else if( p2.x==joinX0 && p2.y==joinY0 )
    {
      is_not_join = false;
      tmp2.unshift( ed );
      joinX0 = p0.x;
      joinY0 = p0.y;
      tmp.splice( i, 1 );
      i = 0;
    }
    else
    {
      var min1 = (p0.x-joinX2)*(p0.x-joinX2) + (p0.y-joinY2)*(p0.y-joinY2);
      var min2 = (p2.x-joinX0)*(p2.x-joinX0) + (p2.y-joinY0)*(p2.y-joinY0);
      if( min_value<0 || min1<min_value || min2<min_value )
      {
        if( min1<min2 )
        {
          min_value = min1;
          min_pos   = 0;
        }
        else
        {
          min_value = min2;
          min_pos   = 2;
        }
        min_index = i;
      }
    }
  }
  //最近傍に連結
  if( is_not_join )
  {
    if( min_index>= 0 )
    {
      var ed = tmp[min_index];
      var p0 = ed.getControl(0);
      var p2 = ed.getControl(2);
      if( min_pos==0 )
      {
        tmp2.push( ed );
        joinX2 = p2.x;
        joinY2 = p2.y;
      }
      else
      {
        tmp2.unshift( ed );
        joinX0 = p0.x;
        joinY0 = p0.y;
      }
      tmp.splice( min_index, 1 );
    }
    else
    {
      break;
    }
  }
}

var lastpos = "";
var option = "_bezier:[";
for( i=0; i<tmp2.length; i++ )
{
  var ed = tmp2[i];
  var p1 = ed.getControl(1);
  
  option += "{x:" + p1.x + ",y:" + p1.y + "}";
    if( i==tmp2.length-1 )
    {
    var p2 = ed.getControl(2);
    lastpos = "x:" + p2.x + ", y:" + p2.y;
  }
  else
  {
    option += ",";
  }
}
option += "]";
fl.trace( "{" + lastpos + ", " + option + "}" );

で、Flash上でトゥイーンさせたい曲線(上のSWFだとグレーのライン)を選択し、メニューの「コマンド→コマンドの実行」か何かで「makeBezierTweenOption.jsfl」を走らせます。うまくいけばこんな感じで出力されます。
※あんまりきちんとつくってないんでバグっても気にせずに。

{x:385, y:207, _bezier:[{x:58.05,y:61.4},{x:145.9,y:80.65},{x:246.7,y:167.05},{x:345.55,y:209.3}]}

これをTweener.addTweenのオプションで使うわけです。

Tweener.addTween( targetObj, {x:385, y:207, _bezier:[{x:58.05,y:61.4},{x:145.9,y:80.65},{x:246.7,y:167.05},{x:345.55,y:209.3}], time:2, transition:"linear"} );

実際には、Tweenerの_bezierは、ベジェ曲線の始点、制御点、終点の内、制御点の配列で指定し、各曲線の分割点は制御点間の中点を使っているので、描いた曲線と同じ軌跡をたどらないのです。そのことを念頭におけば大抵問題ないのかなぁと思ったりします。

“[jsfl]Tweenerの_bezier用パラメータ書き出し” への3件のフィードバック

  1. nutsu より:

    while文の中身が怪しすぎたので修正しました。

  2. nutsu より:

    JSFLの内容はちらっと問題ありなので、bezier用パラメータ書き出し(改め)を見てください。

  3. shun1ok より:

    こちら使わせて頂きました。便利です。ありがとうございます。

| INDEX |