2016-11-07 47 views
0

最初に最初に、私はGSAPを初めて使っています。私は私が苦労していることを説明するために最善を尽くそうとしています。GSAP:一度に複数のトゥイーンとタイムラインを管理する

SVGファイルをアニメーション化するために、私はGSAPにダイビングを開始しました。 SVGファイル内のさまざまな要素に対していくつかのTweensを作成しました。 すべて正常に動作し、期待通りにアニメーション化されています。

私はSVG内でアニメーション化する要素がたくさんあるので、私はTimelineLiteを追加して、全体をより詳細に制御し始めました。

まず、私はすべての要素を宣言した私がアニメーション化したい:この時点で

は、私のスクリプトファイルには、このような何かを見て私は私のトゥイーンを保存するために、オブジェクトを作成したより

this.phone = document.querySelector('#gsap-phone-svg'); 
this.body = document.querySelectorAll('.gsap-phone-body'); 
this.body.shadow = this.phone.querySelectorAll('.gsap-phone-body-shadow'); 
this.body.mask = this.phone.querySelectorAll('.gsap-phone-body-mask'); 
this.layer = this.phone.querySelectorAll('.gsap-phone-layer'); 
this.screen = this.phone.querySelectorAll('.gsap-phone-screen'); 
this.screen.clipPath = this.phone.querySelectorAll('.gsap-phone-screen-clipPath'); 
. 
. 
. 
// many more following here 

:終わり

const tweens = {}; 

// creating tweens 

tweens.body = TweenMax.to(this.body, this.animDur/2,{ 
y: this.maxExpand/6*-1, 
ease: this.ease 
}); 

. 
. 
. 

// many more following here 

私はその後そうのように)私は新しいTimelineLite(に渡さ一時配列にすべての私のトゥイーンを追加しました:

const tl = new TimelineLite(); 
tl.add(tweensArray, 0, "start", 0.05); 

これまでのところロジックと思われますが、今ここには要点があります。あなたは、私が20以上の要素を持っているかどうかに気づいたかもしれません。なぜなら、それ自身のすべての要素にトゥイーンを追加するのは非常に混乱するからです。また、私はメインタイムライン全体を繰り返したいと思う。ここでの問題は、「インアニメーション」のすべてのトゥイーンが「アウトアニメーション」よりも異なるイージングを必要としていることと、「アウトアニメーション」をずらすことができないことです。

これらの小さな欠点は、私がトゥイーンとタイムラインの作成を管理するための代替ソリューションを考えさせました。

私の心に来た最も便利なソリューションは、オブジェクト内の私のアニメーション要素とスケジュールに関するすべての情報を保存することでした。私はGSAPトゥイーンを返すために、この「createTweens」方法を書いたより

const animation = { 
    settings : { 
     duration: 1.5, 
     expansion: 1, 
     easeIn: Elastic.easeOut.config(1, 0.5), 
     easeOut: Power2.easeInOut 
    }, 
    timelines : { 
     main : { 
     delay : 0, 
     paused : true, 
     align : 'start', 
     stagger : 0.05, 
     }, 
     test : { 
     delay: 0, 
     paused : true, 
     align : 'start', 
     stagger : 0.5 
     } 
    }, 
    items : { 
     phone : { 
     id : '#gsap-phone-svg', 
     start : { }, 
     end : { }, 
     timeline : 'test', 
     }, 
     body : { 
     class : '.gsap-phone-body', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y : -21, 
     }, 
     timeline : 'test', 
     }, 
     layer : { 
     class : '.gsap-phone-layer', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y : -62.5, 
     }, 
     timeline : 'main', 
     }, 
     radar : { 
     class : '.gsap-phone-radar', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y : -25, 
     }, 
     timeline : 'main', 
     }, 
     radarBase : { 
     class : '.gsap-phone-radar-base', 
     start: { 
      y : 0, 
     }, 
     end : { 
      y: -16, 
     }, 
     timeline : 'test', 
     }, 
     ringOne : { 
     class : '.gsap-phone-radar-ring-1', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y: -25, 
     }, 
     timeline : 'test', 
     }, 
     ringTwo : { 
     class : '.gsap-phone-radar-ring-2', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y: -41, 
     }, 
     timeline : 'main', 
     }, 
     ringThree : { 
     class : '.gsap-phone-radar-ring-3', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y: -62.5, 
     }, 
     timeline : 'main', 
     }, 
     cancel : { 
     class : '.gsap-phone-cancel', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y: -50, 
     }, 
     timeline : 'main', 
     }, 
     submit : { 
     class : '.gsap-phone-submit', 
     start : { 
      y : 0, 
     }, 
     end : { 
      y: -100, 
     }, 
     timeline : 'main', 
     } 
    } 
}; 

/* create tweens */ 
function createTweens(anim){ 
    const el = anim.items; 
    const settings = anim.settings; 
    const duration = settings.duration; 
    const easeIn = settings.easeIn; 
    const easeOut = settings.easeOut; 
    const tweensIn = []; 
    const tweensOut = []; 
    let tempTween = null; 

    for (const key in el){ 
     const curEl = el[key]; 
     const selector = curEl.class || el[key].id; 
     const startPoint = curEl.start || ''; 
     const endPoint = curEl.end || ''; 
     const timeline = curEl.timeline || ''; 
     const nodes = document.querySelectorAll(selector); 

     nodes.forEach(object => { 
     tweensIn.push(getTween(object, endPoint, duration, easeIn, `${timeline}-in`)); 
     tweensOut.push(getTween(object, startPoint, duration, easeOut, `${timeline}-out`)); 
     }); 
    } 

    function getTween(tw, twValues, twDur, twEase, tl){ 
     const vars = twValues; 
     vars.paused = false; 
     vars.ease = twEase; 
     tempTween = TweenMax.to(tw, twDur/2, vars); 
     tempTween.data = { 
     timelineName : tl 
     }; 
     return tempTween; 
    } 

    return tweensIn.concat(tweensOut); 
} 

とタイムラインを返すために別の関数:

/* create timelines */ 
function createTimelines(anim, tweens){ 
    const el = anim.timelines; 
    const timelines = {}; 
    // timelines.mainIn = new TimelineLite(); 
    // timelines.mainOut = new TimelineLite(); 
    const tweensForTimelines = {}; 

    for(const key in el){ 
     const delay = el[key].delay; 
     const paused = el[key].paused; 
     const align = el[key].align; 
     const stagger = el[key].stagger; 
     const vars = {}; 
     vars.paused = paused; 

     timelines[`${key}-in`] = new TimelineLite(vars); 
     timelines[`${key}-in`].delay = delay; 
     timelines[`${key}-in`].align = align; 
     timelines[`${key}-in`].stagger = stagger; 

     timelines[`${key}-out`] = new TimelineLite(vars); 
     timelines[`${key}-out`].delay = delay; 
     timelines[`${key}-out`].align = align; 
     timelines[`${key}-out`].stagger = stagger; 

     tweensForTimelines[`${key}-in`] = []; 
     tweensForTimelines[`${key}-out`] = []; 
    } 

    if(Object.keys(tweensForTimelines).length !== 0){ 
     for(let i = 0; i < tweens.length; i++){ 
     const curTween = tweens[i]; 
     const tlTarget = curTween.data.timelineName; 
     tweensForTimelines[tlTarget].push(curTween); 
     } 
    } 


    for(const key in timelines){ 
     try{ 
     timelines[key].add(tweensForTimelines[key], timelines[key].delay, timelines[key].align, timelines[key].stagger); 
     console.log(TweenMax.getTweensOf(timelines[key])); 
     timelines[key].data = tweensForTimelines[key]; 
     } catch(e){ 

     } 
    } 

    return timelines; 
} 

の場合私は以下のコードを実行します。それは私の "main-in"タイムラインを再生します。

const tweens = createTweens(animation); 
const timelines = createTimelines(animation, tweens); 
timelines['main-in'].play(); 

これまでのところ、これは実際には機能しています。しかし、私が "main-in"タイムラインを新しいタイムラインに追加しようとすると、それはもはや動作しません。

const anotherTimeline = new TimelineLite(); 
anotherTimeline.add(timelines['main-in']); 
anotherTimeline.play(); 

これをデバッグするために、私は

TweenMax.getTweensOf(anotherTimeline); 

を試みたが、このすべてが返されますが、空の配列です。それから私は私の「メインの」タイムラインのために同じことをログに記録:このタイムラインが空であるように思われるにもかかわらず、それは私「でアニメーションを果たしているので、

console.log(TweenMax.getTweensOf(timelines['main-in'])); 

も、私にとって非常に混乱して、空の配列を返します"on:

timelines['main-in'].play() 

私は本当にここにこだわっていて、より高度なユーザーからの助けを借りて本当に感謝しています。事前にClick for Codepen DEMO

ありがとう:私は..提供codepenを見て、君たちがいない場合には...私に従うことができました

UPDATEを願っています!

答えて

1

私はあなたのすべてのコードを解析して完全な交換を行う時間がありませんでしたが、それは過度に設計されたものとして私を攻撃しましたが、私の脳はちょうど異なった働きをし、 (悪くないか悪いか)。

最も直感的でわかりやすいのは、アニメーションをチャンクに分割して、タイムラインライト/マックスやトゥイーンライト/マックスをマスタータイムラインにネストする関数を入れたものですもしあなたがそうならば)。

ちょっと好き:あなたが養うことができますので、

function phoneIntro() { 
    var tl = new TimelineLite(); 
    tl.to(...) 
     .to(...); 
    return tl; 
} 

function flipPhone() { 
    var tl = new TimelineLite(); 
    tl.to(...); 
    return tl; 
} 

var master = new TimelineMax({repeat:-1}); 
master.add(phoneIntro(), 0) 
     .add(flipPhone(), "-=1"); //overlap by 1 second 
     ... 

そしてもちろん、あなたがこのモジュール化アプローチにアニメーションの同じ種類をやっている要素の多くを持っている場合は、同様に非常に便利ですどのような変数であれ、あなたのために仕事をしてアニメーションを吐き出す機能が必要です。

function buildStep(element, duration, x, y) { 
    return TweenMax.to(element, duration, {x:x, y:y, rotation:30}); 
} 

モジュール化された関数を作成して必要なものを作成すると、どのように柔軟性があるのか​​が明確になってくることを願っています。このアプローチは、コード内の場所を簡単に見つけることができるため、アニメーションを編集する時間を大幅に短縮できます(タイミングなどの実験も可能)。 「私はイントロを2秒長くしたいです...」phoneIntro()関数を見つけてそこのものを微調整してください。完了しました。マスターTimelineMaxで相対的なタイミングで物事を張っているので、最初にモジュール化されたチャンクに加えられた変更は自動的に後続のもののタイミングを後退させ、うまく流れます。 20種類の遅延があります。

また、TweenLite.getTweensOf(anotherTimeline)が空の配列を返す理由は、そのメソッドがのトゥイーンを検出するためです。同様に、文字通り、タイムライン自体をトゥイーン化している場合(おそらくその進行状況)、そのトゥイーンが返されます。 tweenを取得すると仮定したように聞こえます内部タイムラインインスタンスのです(そうではありません)。それがあなたの後ろにあれば、anotherTimeline.getChildren()と同じくらい簡単です。

少なくとも少しは助けてくれることを願っています。 GSAPの専門家の素晴らしいコミュニティがあるフォーラムhttp://greensock.com/forumsに質問を投稿してください。あなたが質問を投稿していなくても、素晴らしい場所です。

ハッピートゥイーン!

+0

この詳細な回答はありがとうございます。あなたはおそらく私がここで少し過剰に作ったかもしれないという事実には正しかったのです。私は既にすべてを分割するという言葉になっており、トゥイーンやタイムラインを返す機能を持っています。 私もGreensock Forumsにこれを掲載しましたが、まだ回答がありませんでした。 –

+0

ところで、この問題はもっと関連しているかもしれませんが、別のトピックで投稿した現在のアニメーションを制作する際に私が遭遇した別の問題があります。 http://stackoverflow.com/questions/40482500/svg-issue-with-multiple-masks-in-different-svgもしあなたが好きならチェックしてください。多分あなたはこれについての答えを持っています。 –

+0

ええ、SVG(特にアニメーション)のマスキングは、残念ながら(この時点ではGSAPとはまったく関係のない)さまざまなブラウザの中で混乱しています。一番上にフィルターを追加して、問題を尋ねています:)私はあなたに簡単な解決策があることを望みます。 – Jack