欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Flutter繪制出3D效果動(dòng)畫

 更新時(shí)間:2022年08月12日 08:20:53   作者:島上碼農(nóng)  
本文主要介紹了Flutter繪圖的Path的應(yīng)用。Flutter的Path類提供了一個(gè)三維空間的變換方法,可以實(shí)現(xiàn)路徑在三維空間的平移、旋轉(zhuǎn)等操作,從而可以實(shí)現(xiàn)3D繪制的效果,感興趣的可以了解一下

前言

本篇我們繼續(xù)介紹 Flutter 繪圖的 Path 的應(yīng)用。Flutter 的 Path 類提供了一個(gè)三維空間的變換方法,可以實(shí)現(xiàn)路徑在三維空間的平移、旋轉(zhuǎn)等操作,從而可以實(shí)現(xiàn)3D 繪制的效果。通過本篇你將了解到:

  • Path的三維轉(zhuǎn)換方法 transform 的使用。
  • 繞三維空間某一點(diǎn)的旋轉(zhuǎn)實(shí)現(xiàn)。
  • 卡片3D 旋轉(zhuǎn)動(dòng)效。
  • 類似日歷的三維翻頁效果。

Path 的 transform 方法

Path 類的 transform 方法 將給定的Path 通過一個(gè)Float64List的對象進(jìn)行三維變換,然后返回變換后的 Path對象,方法定義如下。

Path transform(Float64List matrix4) {
  assert(_matrix4IsValid(matrix4));
  final Path path = Path._();
  _transform(path, matrix4);
  return path;
}

其中 Float64List 一般都是通過 Matrix4 對象的 storage得到,例如我們在 x 方向平移5.0,可以按如下方式得到對應(yīng)的 Float64List 對象。

var transform = (Matrix4.identity()
  ..translate(5.0, 0.0, 0.0)).storage;

Matrix4提供了平移、旋轉(zhuǎn)、逆矩陣等多種方法,有興趣的可以看一下 Matrix4的源碼,實(shí)際上就是大學(xué)線性代數(shù)課(這門課還挺難的)的矩陣乘法內(nèi)容。

繞任意點(diǎn)旋轉(zhuǎn)

網(wǎng)上關(guān)于繞任意點(diǎn)的旋轉(zhuǎn)推導(dǎo)很多,這里就不再贅述,結(jié)論就是實(shí)際上三個(gè)矩陣,先按給定點(diǎn)的(x,y,z)平移,再按給定的角度旋轉(zhuǎn),再按給定點(diǎn)的反向(-x,-y,-z)平移。比如下面是圍繞 point 點(diǎn),在 X 軸方向旋轉(zhuǎn) angle 角度的變換代碼。

var transform = Matrix4.identity()
  ..translate(point.dx, point.dy, point.dz)
  ..rotateX(angle)
  ..translate(-point.dx, -point.dy, -point.dz);

卡片3D 旋轉(zhuǎn)實(shí)現(xiàn)

有了上面的基礎(chǔ),我們就可以實(shí)現(xiàn)卡片的3D旋轉(zhuǎn)效果了。

這個(gè)實(shí)際就是用 Path 繪制了一個(gè)實(shí)心的正方形,然后繞中心點(diǎn)同時(shí)在 X 軸和 Y 軸旋轉(zhuǎn),旋轉(zhuǎn)的角度由動(dòng)畫來控制。然后在動(dòng)畫值的中間的變更顏色,就看起來像是兩面了。具體實(shí)現(xiàn)的代碼如下。

var paint = Paint()
  ..style = PaintingStyle.fill
  ..color = Colors.blue[400]!
  ..strokeWidth = 4.0;

var center = Offset(size.width / 2, size.height / 2);
var path = Path();
final rectSize = 100.0;
path.addRect(Rect.fromCenter(
    center: Offset(center.dx, center.dy),
    width: rectSize,
    height: rectSize));
var transform = Matrix4.identity()
  ..translate(center.dx, center.dy, 0.0)
  ..rotateX(pi * animationValue)
  ..rotateY(pi * animationValue)
  ..translate(-center.dx, -center.dy, 0.0);

var transformedPath = path.transform(transform.storage);
if (animationValue < 0.5) {
  paint.color = Colors.blue[400]!;
} else {
  paint.color = Colors.red;
}
canvas.drawPath(transformedPath, paint);

我們還可以繞 Z 軸旋轉(zhuǎn)來看看效果。

日歷翻頁效果

老的日歷通常是掛在墻上,過了一天就把這一天的翻上去。

觀察上面的圖,下面的部分是矩形,上面翻上去的會(huì)有一個(gè)曲度,這個(gè)我們可以通過貝塞爾曲線來實(shí)現(xiàn)。然后,翻頁過程其實(shí)就是從下面繞中間位置旋轉(zhuǎn)島上面的過程,只是在旋轉(zhuǎn)過程中需要同時(shí)更改繪制的路徑,逐步從矩形過渡到帶有曲度的形狀。

下半部分繪制

下半部分繪制比較簡單,我們?yōu)榱梭w現(xiàn)日歷的厚度,可以繪制多個(gè)高度錯(cuò)開的矩形,并且顏色有點(diǎn)偏差,看起來就像有厚度了。

繪制代碼如下,這里有兩個(gè)關(guān)鍵點(diǎn),一個(gè)是每次繪制的矩形會(huì)往下偏和往右偏移一定的位置,另一個(gè)是更改繪制顏色的透明度,這樣就會(huì)有厚度的感覺了。

var bottomPath = Path();
for (var i = 0; i < 10; ++i) {
  bottomPath.addRect(Rect.fromCenter(
      center: Offset(
          size.width / 2 + i / 1.5, center.dy + rectSize / 2 + i * 1.5),
      width: rectSize,
      height: rectSize));
  paint.color = Colors.white70.withAlpha(240 + 10 * i);
  canvas.drawPath(bottomPath, paint);

上半部分的繪制

上半部分我們的側(cè)邊繪制一定的曲度,這樣看著像翻過后卷起來的感覺。因?yàn)橛胁糠志砥饋砹?,因此高度?huì)比下半部分低一些,曲度我們通過貝塞爾曲線控制,繪制的代碼如下,這里有兩個(gè)常量,一個(gè)是 topHeight 代表上半部分的高度,一個(gè)是 flippedSize,用于控制貝塞爾曲線的曲度。

final topHeight = 90.0;
final flippedSize = -10.0;

var topPath = Path();
topPath.moveTo(center.dx - rectSize / 2, center.dy);
topPath.lineTo(center.dx + rectSize / 2, center.dy);
topPath.quadraticBezierTo(
    center.dx + rectSize / 2 + flippedSize,
    center.dy - topHeight / 2,
    center.dx + rectSize / 2,
    center.dy - topHeight);
topPath.lineTo(center.dx - rectSize / 2, center.dy - topHeight);
topPath.quadraticBezierTo(center.dx - rectSize / 2 + flippedSize,
    center.dy - topHeight / 2, center.dx - rectSize / 2, center.dy);
canvas.drawPath(topPath, paint);

繪制的效果如下,看起來就有日歷的感覺了。

翻頁動(dòng)效繪制

翻頁動(dòng)效實(shí)際上就是再畫一個(gè) Path,這個(gè)對象在動(dòng)畫過程中逐步從矩形轉(zhuǎn)換為上半部分的圖形,同時(shí)通過旋轉(zhuǎn)動(dòng)效翻轉(zhuǎn)上去 —— 也就是其實(shí)我們繪制的是下半部分,只是通過旋轉(zhuǎn)翻上去實(shí)現(xiàn)翻頁的動(dòng)效。實(shí)現(xiàn)的代碼如下,主要的邏輯為:

下邊緣的Y 軸位置在 animationValue = 0.0的時(shí)候等于下半部分的下邊緣Y 軸的位置(rectSize),在 animationValue = 1.0的時(shí)候等于上半部分的上邊緣Y 軸相對中心點(diǎn)對稱位置的,即 center.dy + topHeight,因此得到高度變化的計(jì)算代碼如下面第2行代碼所示。這里增加了一些小的偏移,主要是為了和上下部分有點(diǎn)偏移量,這樣能夠?qū)⒎摵推渌糠謪^(qū)分開。

左右兩側(cè)的曲度一開始是0,直到翻到中間位置后才顯示,這個(gè)通過第3到第6行控制,當(dāng) animationValue < 0.5的時(shí)候,aniamtedFlippedSize 一直是0,即貝塞爾的控制點(diǎn)和起止點(diǎn)在同一條直線上,這樣就不會(huì)有曲度了,等到animationValue > 0.5后,曲度跟隨 animationValue 變化,最終和上半部分的曲度保持一致,這樣旋轉(zhuǎn)上去后能夠重合。

旋轉(zhuǎn)采用上面我們說的繞任意一點(diǎn)旋轉(zhuǎn)的方式實(shí)現(xiàn),這里我們是繞屏幕的中心,繞 X軸旋轉(zhuǎn),角度范圍是0-180度。

最后是我們更改了翻頁的顏色,這個(gè)主要是能夠通過顏色區(qū)分,如果是相同的顏色的話就分不太出來了。

var flippedPath = Path();
var endY = rectSize - 2 + (topHeight - 1 - rectSize) * animationValue;
var animatedFlippedSize = 0.0;
if (animationValue > 0.5) {
  animatedFlippedSize = flippedSize * animationValue;
}
var offsetX = (1 - animationValue) * 4.0;
flippedPath.moveTo(center.dx - rectSize / 2, center.dy);
flippedPath.lineTo(center.dx + rectSize / 2, center.dy);
flippedPath.quadraticBezierTo(
    center.dx + rectSize / 2 + animatedFlippedSize - offsetX,
    center.dy + endY / 2,
    center.dx + rectSize / 2 - offsetX,
    center.dy + endY);

flippedPath.lineTo(center.dx - rectSize / 2 - offsetX, center.dy + endY);
flippedPath.quadraticBezierTo(
    center.dx - rectSize / 2 + animatedFlippedSize,
    center.dy + endY / 2,
    center.dx - rectSize / 2,
    center.dy);
var transform = Matrix4.identity()
  ..translate(center.dx, center.dy, 0.0)
  ..rotateX(pi * animationValue)
  ..translate(-center.dx, -center.dy, 0.0);
var transformedPath = flippedPath.transform(transform.storage);
if (animationValue < 0.5) {
  paint.color = Colors.white;
} else {
  paint.color = Colors.green[300]!;
}
canvas.drawPath(transformedPath, paint);

最終的實(shí)現(xiàn)效果如下所示。

總結(jié)

本篇介紹了Flutter 繪圖中的 Path類的三維空間變換方法和應(yīng)用,可以看到,基于三維變換可以實(shí)現(xiàn)3D效果圖形的繪制和實(shí)現(xiàn)3D 動(dòng)效,這在有些特殊繪制的場景中或增添趣味性十分有用。

以上就是利用Flutter繪制出3D效果動(dòng)畫的詳細(xì)內(nèi)容,更多關(guān)于Flutter 3D動(dòng)畫的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android實(shí)現(xiàn)APP在線下載更新

    Android實(shí)現(xiàn)APP在線下載更新

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)APP在線下載更新的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Android之OOM異常解決案例講解

    Android之OOM異常解決案例講解

    這篇文章主要介紹了Android之OOM異常解決案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Android中ActionBar以及menu的代碼設(shè)置樣式

    Android中ActionBar以及menu的代碼設(shè)置樣式

    這篇文章主要介紹了Android中ActionBar以及menu的代碼設(shè)置樣式的相關(guān)資料,需要的朋友可以參考下
    2015-07-07
  • Flutter SystemChrome使用方法詳解

    Flutter SystemChrome使用方法詳解

    這篇文章主要為大家介紹了Flutter SystemChrome使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • android中使用Html渲染的方式實(shí)現(xiàn)必填項(xiàng)前面的*號示例

    android中使用Html渲染的方式實(shí)現(xiàn)必填項(xiàng)前面的*號示例

    本篇文章主要介紹了android中使用Html渲染的方式實(shí)現(xiàn)必填項(xiàng)前面的*號示例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-09-09
  • 詳解android webView獨(dú)立進(jìn)程通訊方式

    詳解android webView獨(dú)立進(jìn)程通訊方式

    本篇文章主要介紹了android webView獨(dú)立進(jìn)程通訊方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • android自定義View圓圈拖動(dòng)

    android自定義View圓圈拖動(dòng)

    這篇文章主要為大家詳細(xì)介紹了android自定義View圓圈拖動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 如何使用Matrix對bitmap的旋轉(zhuǎn)與鏡像水平垂直翻轉(zhuǎn)

    如何使用Matrix對bitmap的旋轉(zhuǎn)與鏡像水平垂直翻轉(zhuǎn)

    本篇文章是對使用Matrix對bitmap的旋轉(zhuǎn)與鏡像水平垂直翻轉(zhuǎn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • Kotlin的枚舉與異常示例詳解

    Kotlin的枚舉與異常示例詳解

    這篇文章主要給大家介紹了關(guān)于Kotlin的枚舉與異常的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Kotlin具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Kotlin語言中CompileSdkVersion與targetSdkVersion的區(qū)別淺析

    Kotlin語言中CompileSdkVersion與targetSdkVersion的區(qū)別淺析

    這篇文章主要介紹了Kotlin語言中CompileSdkVersion和targetSdkVersion有什么區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02

最新評論