国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Flutter進階之實現動畫效果(七)

2019-10-21 21:40:50
字體:
來源:轉載
供稿:網友

我們假設一種情況,如果應用程序使用條形圖顯示給定年份的產品類別的銷售額,用戶可以選擇另一年,然后該應用程序將動畫到該年的條形圖。如果產品類別在兩年內是相同的,或者恰好是相同的,除了在其中一個圖表中右側顯示的其他類別,我們可以使用我們現有的代碼。但如果公司在2016年有A,B,C和X類產品,但是在2017年中斷了B并推出了D?

Flutter,動畫效果

動畫效果可以做得非常好看,但仍然會讓用戶感到困惑。為什么?因為它不保留語義。它將表示產品類別B的圖形元素轉換為代表類別C的一個圖形元素,而將C的圖形元素轉換到其他地方。正因為2016 B恰好是在2017 C后來出現的同一位置,并不意味著前者應該變成后者。相反,2016年B應該消失,2016年C應該向左移動到2017年,而2017年D應該出現在右邊。我們可以使用傳統的合并排序列表實現這種混合。

我們可以分別給每一個條形以不同的顏色,然后使用顏色來區分銷售的產品,一種顏色代表一個產品,當一種顏色消失時,說明該產品已經下架,反之,則說明新產品已經上架。

通過語義對應的組件進行復合值之間的線性插值(lerp),當組件形成排序列表時,合并算法可以將這些組件放在側面上,使用不可見組件來處理單面合并。我們所需要的是使Bar實例以線性順序相互比較。然后我們可以將它們合并。

// ...class BarChart { // ... factory BarChart.random(Size size, Random random) { const barWidthFraction = 0.75; final ranks = selectRanks(random, ColorPalette.primary.length); final barCount = ranks.length; final barDistance = size.width / (1+barCount); final barWidth = barDistance * barWidthFraction; final startX = barDistance - barWidth/2; final bars = new List.generate(  barCount,  (i)=> new Bar(  ranks[i],  startX + i * barDistance,  barWidth,  random.nextDouble() * size.height,  ColorPalette.primary[ranks[i]],  ), ); return new BarChart(bars); } static List<int> selectRanks(Random random, int cap) { final ranks = <int>[]; var rank = 0; while(true) {  // 模擬產品的上架下架  if(random.nextDouble() < 0.2) rank++;  if(cap <= rank) break;  ranks.add(rank);  rank++; } return ranks; } static BarChart lerp(BarChart begin, BarChart end, double t) { final bars = <Bar>[]; final bMax = begin.bars.length; final eMax = end.bars.length; var b = 0; var e = 0; while (b + e < bMax + eMax) {  /*  這里的條件判斷中包含兩種情況  b < bMax && e == eMax:  當新圖表條形數減少時  b < bMax && begin.bars[b] < end.bars[e]:  當新圖表不包含舊圖表的顏色條形時  滿足一種情況,處理舊圖表中多余的條形,即向左側方清除舊條形  */  if(b < bMax && (e == eMax || begin.bars[b] < end.bars[e])) {  bars.add(Bar.lerp(begin.bars[b], begin.bars[b].collapsed, t));  b++;  /*  這里的條件判斷中包含兩種情況  e < eMax && b == bMax:  當新圖表條形數增加時  e < eMax && end.bars[e] < begin.bars[b]:  當新圖表包含舊圖表沒有的顏色條形時  滿足一種情況,處理舊圖表中沒有的條形,即向右側方繪制新條形  */  } else if(e < eMax && (b == bMax || end.bars[e] < begin.bars[b])) {  bars.add(Bar.lerp(end.bars[e].collapsed, end.bars[e], t));  e++;  // 當新圖表與舊圖表有同一個顏色條形時,原地變形  } else {  bars.add(Bar.lerp(begin.bars[b], end.bars[e], t));  b++;  e++;  } } return new BarChart(bars); }}class BarChartTween extends Tween<BarChart> { BarChartTween(BarChart begin, BarChart end) : super(begin: begin, end: end); @override BarChart lerp(double t) => BarChart.lerp(begin, end, t);}class Bar { Bar(this.rank, this.x, this.width, this.height, this.color); final int rank; final double x; final double width; final double height; final Color color; Bar get collapsed => new Bar(rank, x, 0.0, 0.0, color); /* bool operator <( Duration other ) 如果此Duration的值小于other值,則返回true bool operator <(Duration other) => this._duration < other._duration; */ bool operator <(Bar other) => rank < other.rank; static Bar lerp(Bar begin, Bar end, double t) { assert(begin.rank == end.rank); return new Bar(  begin.rank,  lerpDouble(begin.x, end.x, t),  lerpDouble(begin.width, end.width, t),  lerpDouble(begin.height, end.height, t),  Color.lerp(begin.color, end.color, t) ); }}class BarTween extends Tween<Bar> { BarTween(Bar begin, Bar end) : super(begin: begin, end: end) { assert(begin.rank == end.rank); } @override Bar lerp(double t) => Bar.lerp(begin, end, t);}// ...

具體來說,我們將以整數rank屬性的形式為每個條形分配一個排序鍵。然后可以方便地使用rank來從調色板中分配每個條形的顏色,從而使我們能夠跟蹤動畫演示中各個條形圖的移動。

隨機條形圖現在將基于隨機選擇的行列。

Flutter,動畫效果

但這不是最有效的解決方案,我們正在BarChart.lerp中重復執行合并算法,對于t的每個值都執行一次。為了解決這個問題,我們將實現前面一篇文章中提到的想法,以便在BarChartTween中存儲可重用的信息。

// ...class BarChartTween extends Tween<BarChart> { final _tweens = <BarTween>[]; BarChartTween(BarChart begin, BarChart end) : super(begin: begin, end: end) { final bMax = begin.bars.length; final eMax = end.bars.length; var b = 0; var e = 0; while (b + e < bMax + eMax) { if(b < bMax && (e == eMax || begin.bars[b] < end.bars[e])) { _tweens.add(new BarTween(begin.bars[b], begin.bars[b].collapsed)); b++; } else if(e < eMax && (b == bMax || end.bars[e] < begin.bars[b])) { _tweens.add(new BarTween(end.bars[e].collapsed, end.bars[e])); e++; } else { _tweens.add(new BarTween(begin.bars[b], end.bars[e])); b++; e++; } } } @override BarChart lerp(double t) => new BarChart( new List.generate( _tweens.length, (i) => _tweens[i].lerp(t)) );}// ...

然后我們就可以刪除靜態的BarChart.lerp方法了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄浦区| 普格县| 玉环县| 闻喜县| 铜鼓县| 明水县| 商丘市| 米易县| 防城港市| 濉溪县| 陆良县| 星子县| 定远县| 扬中市| 鲁甸县| 个旧市| 邯郸市| 西和县| 宁乡县| 恩施市| 绍兴县| 昌都县| 内乡县| 屯昌县| 乌鲁木齐市| 正镶白旗| 广州市| 龙山县| 新郑市| 彝良县| 邳州市| 宿迁市| 织金县| 高安市| 沙田区| 城口县| 湟源县| 房产| 婺源县| 随州市| 崇州市|