糸滑りのような動効原理を説明するベッセル曲線を深く浅く説明する


作者:哈哈将-个推Android高级开発技师
前言
アプリ開発市場はすでに「野蛮な成長」時代に別れを告げ、人々はアプリの外形革新に満足せず、全方面のユーザー体験に目を向けている.この過程で、モバイルインターネット製品の新しいトレンドとして、どのようにクールで滑らかなアニメーション効果を実現するかが開発者たちの新しい課題となっている.実現方法は実は簡単です.本文はあなたのために理論の基礎と具体的な応用を分析します.この文章を読んで、あなたのアプリもクールなアニメ効果を達成することができます.
まず2つの例を見てみましょう.
  • 携帯電話QQ未読メッセージ赤点ドラッグ効果.
  • 小説はアプリのページをめくる効果を読みます.

  • 概要
    実戦を始める前に、理論の基礎を理解しておきましょう.アニメの究極の武器はベッセル曲線だ.滑らかな曲線で、4つの位置の任意の点座標に基づいて描画されます.1962年、フランスのエンジニアピエール・ベッセル(Pierre Bézier)はこのベクトルが曲線を描く方法を率先して研究し、自動車の本体設計に応用する詳細な計算式を与えた.したがって、この式に従って描画される曲線は、ベッセル曲線と命名されます.
    核心思想.
    ベッセル曲線はコンピュータグラフィックで最も多く用いられるパラメータ曲線の一つである.カーブ上の4つのポイント(開始点、終了点、および2つの分離された中間点)を制御することで、グラフィックを作成、編集します.重要な役割は、カーブの中央にある制御線です.この線は仮想的で、真ん中はベッセル曲線と交差し、両端は制御端点です.両端の端点を移動すると、ベッセル曲線は曲線の曲率(曲げの程度)を変えることができます.中間点(つまり仮想の制御線を移動する)を移動すると、ベッセル曲線は開始点と終了点がロックされた状態で均一に移動します.注意:ベッセルカーブ上のすべての制御点、ノードは編集できます.
    げんり
    この中には共通の公式があります.この公式はもう先輩がまとめてくれました.
    ここで、P 0は起点、Pnは中点、Piは制御点である.
    いちじベッセルきょくせん
    1次これは比較的簡単で、ネット上で数学の公式を直接入力できるツールが見つからないので、手作業で導いた.
    最後の式はB(t)=(1−t)Po+tP 1,t−>[0,1]である.
    にじベッセルきょくせん
    まずアニメーション効果を見ます.
    赤い線の部分に注目してください.この線は私たちの単位時間で実行されるベッセル曲線の効果図です.この赤い線は実際には無数の点から構成されており、tの変化に伴い、赤い線の変換過程は非常に滑らかである.
    最後に得られた式は次のとおりです.
    ベゼル曲線の描画は、何段(1段を除く)でも段階的に降格し、最終的に1段に下がる必要があります.「2次ベッセル曲線解析」というテキストでは、最初のステップから2番目のステップへのプロセスがステップダウンします.ベッセル曲線の最終経路は、1次ベースラインの上流を歩く赤い小さな点から形成される.
    三次ベッセル曲線
    2次の導出過程があれば,3次の導出は容易になる.紙面の制限のため、導出過程はここでは展開されません.興味があれば、自分で導くことができます.
    最後の赤色曲線は青色の1次曲線から得られ、青色の1次曲線は緑色の1次曲線から得られ、最後の緑色の1次曲線は最も外側のP 0,P 1,P 2,P 3から構成される.アニメーション効果:
    よんだんベッセルきょくせん
    5次ベッセル曲線
    結論:従来のベッセル曲線上の点は高数の二項式展開と同様に、各線分上の点に対して制御点を介して接面操作を行い、連続する2点の間は無限に近いため、描画中に非常に滑らかで過度に現れることが分かった.
    Androidでのベッセル曲線の使用
    Androidではベッセル曲線を使うのが簡単で、Androidにはベッセル曲線のAPIが内蔵されており、開発者が直接呼び出すことができます.主に2つのAPIがあります.
    quadTo
    Path path = new Path(); path.moveTo(startX, startY); path.quadTo(eventX, eventY, endX, endY); canvas.drawPath(path, paint); ここで(startX,startY)を起点とし,(endX,endY)を終点とし,(eventX,eventY)を制御点とする.
    cubicTo
    Path path = new Path(); path.moveTo(startX, startY); path.cubicTo(leftX, leftY, rightX, rightY, endX, endY); canvas.drawPath(path, paint); このメソッドを呼び出すと、3次ベッセル曲線が描画されます.(startX,startY)を起点とし,(endX,endY)を終点とし,(leftX,leftY)と(rightX,rightY)を2つの制御点とする.
    多段ベッセル曲線:Androidシステムでは最高3段のベッセル曲線しか描けませんが、もっと高い段を描こうとしたらどうしますか?実は簡単です.本当に高次曲線を使う必要がある場合は、人工的に3級に降格すればいいです.
    実戦
    やっと実戦コーナーに着きました.このコーナーには2つのdemoがあります.一つはベッセル曲線の擬円効果で、もう一つは網易雲音楽のクジラ雲効果を模倣している.
    効果実装1:ベッセル曲線で円を描く例
    前述したように、ベッセル曲線の汎用式をまとめた.インターネットで資料を閲覧する過程で,(4/3)tan(π/(2 n))は,nセグメントの3次Bessel曲線が円形にフィットすることを意味し,曲線端点からこの端点に最も近い制御点までの最適距離は(4/3)tan(π/(2 n))であることを見出した.みんなが興味があれば自分で導き出すことができます.導出過程は複雑ではない.ベッセル曲線には重要な性質がある.すなわち、曲線方程式におけるt=0.5の点が円弧上に必ず落ちるからである.座標系を3次方程式に持ち込むだけです.
    最後に,t=0.5のとき,円形方程式X 2+Y 2=R^2に基づいてh=(4/3)(sqrt(2)−1)≒0.552284749831が得られることが分かった.上記の理論的基礎があって、円を描くのはとても楽で、私たちはまず下書き紙の中でこのようなモデルを得ました.
    上図によれば、この円は、P 0->P 3,P 3->P 6,P 6->P 9,P 9->P 11の4段の3次ベッセル曲線からなる.3次ベッセル曲線の構図はAndroid内蔵で、APIを直接呼び出せばいいです.コアコードは以下の通りです.
    public HeartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context) }
    @Override
    protected void init(Context context) {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
    
        mPath = new Path();
      //   12   。
        mCurPointList = new ArrayList<>();
        mCurPointList.add(new PointF(0, dpToPx(-89)));
        mCurPointList.add(new PointF(dpToPx(50), dpToPx(-89)));
        mCurPointList.add(new PointF(dpToPx(90), dpToPx(-49)));
        mCurPointList.add(new PointF(dpToPx(90), 0));
        mCurPointList.add(new PointF(dpToPx(90), dpToPx(50)));
        mCurPointList.add(new PointF(dpToPx(50), dpToPx(90)));
        mCurPointList.add(new PointF(0, dpToPx(90)));
        mCurPointList.add(new PointF(dpToPx(-49), dpToPx(90)));
        mCurPointList.add(new PointF(dpToPx(-89), dpToPx(50)));
        mCurPointList.add(new PointF(dpToPx(-89), 0));
        mCurPointList.add(new PointF(dpToPx(-89), dpToPx(-49)));
        mCurPointList.add(new PointF(dpToPx(-49), dpToPx(-89)));
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        drawCoordinate(canvas);
    
        canvas.translate(mWidth / 2, mHeight / 2);
    
        mPath.reset();
        for (int i = 0; i < 4; i++) {
            if (i == 0) {
                mPath.moveTo(mCurPointList.get(i * 3).x, mCurPointList.get(i * 3).y);
            } else {
                mPath.lineTo(mCurPointList.get(i * 3).x, mCurPointList.get(i * 3).y);
            }
    
            int endPointIndex;
            if (i == 3) {
                endPointIndex = 0;
            } else {
                endPointIndex = i * 3 + 3;
            }
    
            mPath.cubicTo(mCurPointList.get(i * 3 + 1).x, mCurPointList.get(i * 3 + 1).y,
                    mCurPointList.get(i * 3 + 2).x, mCurPointList.get(i * 3 + 2).y,
                    mCurPointList.get(endPointIndex).x, mCurPointList.get(endPointIndex).y);
        }
    
        canvas.drawPath(mPath, mPaint);
    
    }
    

    }成果展示
    効果実現2:網易雲音楽クジラ雲効果を例に
    GIFに変換すると、画像が少し歪む可能性がありますが、具体的な実現構想を妨げることはありません.このGIFによると、3つの機能が必要であることがわかりました.
    1.背景色と歌の画像を組み合わせて、画像の変化によって変化する.
    2.歌の真ん中の画像は円形の画像で、自動的に回転することができます.
    3.図形の外輪は動感3 Dで囲む効果がある.
    第一に、実現は簡単です.
    二つ目も難しくない.画像を円形にカットしたり、GitHubの既存のオープンソースライブラリを使用したり、プロパティアニメーションコードを追加したりすることができます.
    public void handleRotate(){
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivShowPic, "rotation", 0f, 360f);
        objectAnimator.setDuration(20 * 1000);        
        objectAnimator.setRepeatMode(ValueAnimator.RESTART);        
        objectAnimator.setInterpolator(new LinearInterpolator());        
        objectAnimator.setRepeatCount(-1);        
        objectAnimator.start();
    }
    

    動感3 Dリング効果を見ると回転します.
    3点目はどうやってメロディーを踊るのか?!前の2つのニーズを考慮しないで、私たちは徐々にジャンプメロディーの特効を分析します.ダイナミックマップは文章の最初の部分で見られたので,まず静的マップから着手することを提案した.
    我々は可能な実現構想(公式実現構想を代表しない):この動効外層は1周に4本の線分が不規則に鼓動し、各線の背後には円があり、各円は4本のベッセル曲線から構成されていると推測した.
    最初のステップはまず円を描きます.ブラシのアトリビュートを次のアトリビュートに設定するだけで、中空の円を描くことができます.
    mPaint.setStyle(Paint.Style.STROKE);
    よりスムーズなオービット効果を達成するには、各ベッセル曲線の対応する2つの制御点を絶えずデバッグする必要があります.具体的なパラメータは、ビジネスシーンに基づいて決定できます.本文ではdemoは参照にすぎない.
    第2のステップでは、この円がベッセル曲線からなる擬円であることを分析した.Androidシステムでは毎秒60フレームがフルフレームであるため、1秒÷60フレームであれば、16ミリ秒(ms)/フレームがフルフレームであるという限界が得られ、すなわち、フレームあたり16 msより速いとスムーズである.ここでは80ミリ秒ごとにリフレッシュするように設定しています.
    public void onPlay(View view){ scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { diyBezierView.post(new Runnable() { @Override public void run() { diyBezierView.play(); } }); } },0,80, TimeUnit.MILLISECONDS); 得られた効果は以下の通りである.
    第3歩の雛形はすでに完成して、後続の私達のやり方は更に上に2つの円を追加して、3つの円がどのような効果があるかを見ます.
    4番目のステップの最後のステップはもちろん前の2点を合わせて、合わせてから最終的な効果を見ることができます.
    実際の効果と予想される効果には一定の違いがあります.主な原因は、関数座標やブラシのプロパティの問題です.以上が具体的な実現構想であり、参考に供する.
    まとめ
    クールなアニメーションの実現過程は私たちが想像していたほど複雑ではありません.実際、多くの複雑な特効は異なるアニメーションを組み合わせたものであり、滑らかなダイナミック効果はベッセル曲線の応用から離れられない.この文章がクールで滑らかなダイナミックな効果を出したいあなたを助けることができることを望んでいます.
    どのように実戦Demoを獲得します
    https://github.com/LiuLei0571/jingyun_breizer(よろしければプログラマーのお兄さんにstarをあげますよ)
    あるいは「個推技術学院」の微信公衆番号にも注目することができる.
    (マイクロ信号:getuitech)
    回答キーワード「曲線」
    クジラ雲の特効アニメーションdemoを手に入れることができます!