第一件事是第一件事,我是GSAP的新手,請耐心等待。我試着盡我所能描述我正在努力的。GSAP:一次管理多個補間和時間線
爲了創建一個SVG文件的動畫,我開始潛入GSAP。我爲SVG文件中的不同元素創建了幾個補間。 一切工作正常,並按預期動畫。
由於我在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個元素左右的動畫。這就是爲什麼爲每個元素添加補間變得非常混亂的原因。另外我希望整個主要時間表都是重複的。這裏的問題是,我希望我的所有補間動畫都在「動畫中」上,而不是「在外動畫上」,同時我也不想在「動畫」上錯開。
所有這些小小的癥結讓我想到了一個替代解決方案來管理我的補間和時間表的創建。
是排在我腦海中最方便的解決方案是,以存儲對象中我的動畫元素和時間表的所有信息:
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',
}
}
};
比我寫的這個「createTweens」方法返回GSAP吐溫
/* 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;
}
如果我執行下面的代碼,它會播放我的「主進」時間線。
const tweens = createTweens(animation);
const timelines = createTimelines(animation, tweens);
timelines['main-in'].play();
到目前爲止,這實際上是工作。但是,如果我嘗試將「主入」時間線添加到新時間線,則不再有效。
const anotherTimeline = new TimelineLite();
anotherTimeline.add(timelines['main-in']);
anotherTimeline.play();
爲了調試這一點,我想
TweenMax.getTweensOf(anotherTimeline);
但所有這返回的是一個空數組。然後我登錄同爲我的「主在」時間線:
console.log(TweenMax.getTweensOf(timelines['main-in']));
也返回一個空Array,這是非常令人困惑的我,因爲即使這個時間表似乎是空的,它扮演着我「,在動畫「上:
timelines['main-in'].play()
我真的堅持在這裏,真的希望從更高級的用戶提供一些幫助,或者乾脆的人誰擁有了這個想法。我希望你們能跟隨我......萬一不是,看看提供的codepen ..
UPDATE:提前Click for Codepen DEMO
謝謝!
非常感謝您的詳細解答。你可能正確的事實是我可能在這裏過度設計一些; D。我已經達成了將所有事情分割多一點的條款,並且只有函數返回補間或時間軸。 我也在Greensock論壇發佈了這篇文章,但還沒有得到任何答覆,這就是爲什麼我在這裏發佈它; D。 –
順便說一下,即使這個問題可能與svg更相關,但在製作當前動畫時遇到了另一個問題,我在另一個主題中發佈了這些動畫。 http://stackoverflow.com/questions/40482500/svg-issue-with-multiple-masks-in-different-svg檢查出來,如果你喜歡,也許你有這個:)的答案。 –
是的,不幸的是,在各種瀏覽器中,隱藏在SVG中(尤其是動畫)掩蓋了(與GSAP完全無關)。在上面添加一個過濾器,你要求麻煩:)我希望我有一個簡單的解決方案。 – Jack