CocosCreatorでクールなレーダーチャートを描く方法

CocosCreatorでクールなレーダーチャートを描く方法

序文

レーダー チャートは、ネットワーク チャート、スター チャート、スパイダー ウェブ チャートとも呼ばれます。

これは、同じ点から始まる軸上で表される 3 つ以上の定量的変数の 2 次元グラフの形式で多変量データを表示するグラフィカルな方法です。

3 つ以上の次元を表示する変数に適用されます。

レーダー チャートは、データの統計や比較によく使用されます。どの変数が同様の値を持っているか、変数間に外れ値があるかどうかを確認するのに役立ちます。

同時に、レーダーチャートは多くのゲームで使用されており、非常に直感的にデータを表示および比較できます。

たとえば、King of Glory の戦闘データが使用されます。

この記事では、Pipi が Cocos Creator のグラフィックス コンポーネントを使用してクールなレーダー チャートを描画する方法を紹介します。

読みやすさを確保するために、元のコードは削減されます。

レーダーチャート コンポーネント: https://gitee.com/ifaswind/eazax-ccc/blob/master/components/RadarChart.ts


プレビュー

まずは効果を見てみましょう〜

オンラインプレビュー: https://ifaswind.gitee.io/eazax-cases/?case=radarChart

2つのデータ

緩和データ

ベルとホイッスル

芸術は爆発だ

だんだんと話題が逸れていく

文章

グラフィックコンポーネント

レーダー チャートの作成を始める前に、Cocos Creator エンジンのグラフィックス コンポーネントを見てみましょう。

Graphics コンポーネントはcc.RenderComponentを継承します。このコンポーネントを使用すると、描画ボードや表などの機能を実装できます。

プロパティ

今回使用するプロパティは以下のとおりです。

  • lineCap : 線の両端のスタイルを設定または返します (なし、丸いキャップ、または四角いキャップ)
  • lineJoin : 2本の線が交差するときの角のスタイル(ベベル、丸み、または鋭角)を設定または返します。
  • lineWidth : 現在のブラシの太さ(線の幅)を設定または返します。
  • strokeColor : 現在のブラシの色を設定または返します
  • fillColor : 塗りつぶしの色(ペイントバケツ)を設定または返します。

機能

今回使用する関数は以下のとおりです。

  • moveTo(x, y) : ペンを持ち上げて指定された位置に移動します(線は作成しません)
  • lineTo(x, y) : ペンを下ろして指定した位置まで直線を描く
  • circle(cx, cy, r) : 指定された位置(円の中心)に円を描きます。
  • close() : 作成されたラインを閉じます( lineTo(起點)と同等)
  • stroke() : 作成された(しかし描画されていない)線を描画します(線はデフォルトで透明であると考えてください。この動作により線に色が付きます)
  • fill() : 現在の線で囲まれた領域を塗りつぶします (線が閉じていない場合は、開始点と終了点を「閉じているようにシミュレート」しようとします)
  • clear() : 現在の描画ボード上のすべてを消去します

グラフィックス コンポーネントのドキュメント: http://docs.cocos.com/creator/manual/zh/components/graphics.html?h=graphics

グリッドを描く

まず、標準的なレーダーチャートの特徴を見てみましょう。

見つかりましたか?レーダーチャートの基本的な機能は次のとおりです。

  • 軸が3つ以上ある
  • 軸間の角度は同じです
  • 各軸には、中心点の他に少なくとも 1 つのスケール マークが必要です。
  • 各軸に同じスケール
  • 鱗の間の距離も同じです
  • 軸間の目盛りはグリッド線を形成するように接続されています

軸角度を計算する

まず軸間の角度 [ 360 ÷ 軸數] を計算し、次にすべての軸の角度を計算します。

this.angles = [];
// 軸間の角度 const iAngle = 360 / this.axes;
(i = 0 とします; i < this.axes; i++) {
    // 計算 const angle = iAngle * i;
    this.angles.push(角度);
}

スケール座標を計算する

レーダー チャートには少なくとも 3 つの軸があり、各軸には 1 つ以上のスケール (中心点を除く) が必要です

したがって、描画時に読み取れるように、最も外側のスケール (つまり、軸の端) から始めて、すべてのスケールの座標を保存する 2 次元配列を使用する必要があります。

// 2次元配列を作成します。let scalesSet: cc.Vec2[][] = [];
for (let i = 0; i < 軸上のスケールの数; i++) {
    // 現在のレイヤーのスケール座標を保存するために使用されます。let scales = [];
    // 軸上のスケールの位置を計算します。const length = axis length - (axis length / number of scales on the axis * i);
    (j = 0 とします; j < this.angles.length; j++) {
        // 角度をラジアンに変換 const radian = (Math.PI / 180) * this.angles[j];
        // 三角関数の公式に従って、中心点 (0, 0) を基準としたスケールの座標を計算します。const pos = cc.v2(length * Math.cos(radian), length * Math.sin(radian));
        // 配列をプッシュする scales.push(pos);
    }
    // 2次元配列をプッシュします scalesSet.push(scales);
}

軸線と外側のグリッド線を描く

中心点(0, 0)と最も外側のscalesSet[0]を結ぶスケールが軸です。

// 最も外側のスケールをすべてトラバースします for (let i = 0; i < scalesSet[0].length; i++) {
    // ブラシを中心点に移動します this.graphics.moveTo(0, 0);
    // 線を作成します this.graphics.lineTo(scalesSet[0][i].x, scalesSet[0][i].y);
}

外側のグリッド線

すべての軸上の最も外側のscalesSet[0]スケールを接続すると、外側のグリッド線が形成されます。

// ブラシを最初のポイントに移動します this.graphics.moveTo(scalesSet[0][0].x, scalesSet[0][0].y);
(i = 1; i < scalesSet[0].length; i++) の場合 {
    // 線を作成します this.graphics.lineTo(scalesSet[0][i].x, scalesSet[0][i].y);
}
// 現在の行(外側のグリッド線)を閉じる
this.graphics.close();

塗りつぶして描く

ここでは、最初に色を塗りつぶしてから線を描くように注意する必要があります。そうしないと、軸とグリッド線がブロックされます。

// 線で囲まれた空白領域を塗りつぶします this.graphics.fill();
// 作成した線(軸線と外側のグリッド線)を描画します
this.graphics.stroke();

つまり、次のようになります。

内側のグリッド線を描く

スケールの数が 1 より大きい場合は、スケール座標セットの下付き文字 1 から始めて、内側のグリッド線を描画する必要があります。

// スケールの数が 1 より大きい場合にのみ内側のグリッド線を描画します if (scalesSet.length > 1) {
    // 下から 1 から開始します (下付き文字 0 は外側のグリッド線です)
    (i = 1 とします; i < scalesSet.length; i++) {
        // ブラシを最初のポイントに移動します this.graphics.moveTo(scalesSet[i][0].x, scalesSet[i][0].y);
        (j = 1; j < scalesSet[i].length; j++) の場合 {
            // 線を作成します this.graphics.lineTo(scalesSet[i][j].x, scalesSet[i][j].y);
        }
        // 現在の行(内側のグリッド線)を閉じる
        this.graphics.close();
    }
    // 作成した線(内側のグリッド線)を描画します
    this.graphics.stroke();
}

このようにして、レーダーチャートのベースが描画されます。

図面データ

線描画ロジックを記述する前に、まず必要なデータ構造を決定しましょう。

  • 数値配列(必須、小数形式の比率、少なくとも 3 つの値)
  • 線の幅(オプション、指定しない場合はデフォルト値が使用されます)
  • 線の色(オプション、指定されていない場合はデフォルト値が使用されます)
  • 塗りつぶし色(オプション、指定しない場合はデフォルト値が使用されます)
  • ノードの色(オプション、指定されていない場合はデフォルト値が使用されます)

具体的なデータ構造は以下のとおりです(外部使用にはエクスポートタイプが便利です)。

/**
 * レーダーチャートデータ */
エクスポートインターフェースRadarChartData {

    /** 価値 */
    値: 数値[];

    /** 線の幅 */
    線幅?: 数値;

    /** 線の色 */
    線の色?: cc.Color;

    /** 塗りつぶし色 */
    塗りつぶしの色?: cc.Color;

    /** ノードの色 */
    cc.Color を結合しますか?

}

データのプロット

データのプロットは比較的簡単です。グラフ上のデータ ポイントの位置を把握し、データを接続すればよいだけです。

draw関数では、1 つ以上のレーダー チャート データを受け取り、順番に描画します (⚠️ 長いコード警告):

/**
 * 描画データ * @param data データ */
パブリック描画(データ: RadarChartData | RadarChartData[]) {
    // データを処理 const datas = Array.isArray(data) ? data : [data];

    // データの描画を開始します for (let i = 0; i < datas.length; i++) {
        // 染料をロードします this.graphics.strokeColor = datas[i].lineColor || defaultOptions.lineColor;
        this.graphics.fillColor = datas[i].fillColor || defaultOptions.fillColor;
        this.graphics.lineWidth = datas[i].lineWidth || defaultOptions.lineWidth;

        // ノード座標を計算する let coords = [];
        (j = 0; j < this.axes; j++) の場合 {
            定数値 = datas[i].values[j] > 1 ? 1 : datas[i].values[j];
            定数長さ = 値 * this.axisLength;
            const ラジアン = (Math.PI / 180) * this.angles[j];
            const pos = cc.v2(長さ * Math.cos(ラジアン), 長さ * Math.sin(ラジアン))
            座標をプッシュします。
        }

        // 線を作成します this.graphics.moveTo(coords[0].x, coords[0].y);
        (j = 1; j < coords.length; j++) の場合 {
            this.graphics.lineTo(座標[j].x, 座標[j].y);
        }
        this.graphics.close(); // 線を閉じます // 囲まれた領域を塗りつぶします this.graphics.fill();
        // 線を描画します this.graphics.stroke();

        // データノードを描画する for (let j = 0; j < coords.length; j++) {
            // 大きな円 this.graphics.strokeColor = datas[i].lineColor || defaultOptions.lineColor;
            this.graphics.circle(座標[j].x, 座標[j].y, 2);
            this.graphics.stroke();
            // 小さな円 this.graphics.strokeColor = datas[i].joinColor || defaultOptions.joinColor;
            this.graphics.circle(座標[j].x, 座標[j].y, .65);
            this.graphics.stroke();
        }

    }
}

これまでに、使用可能なレーダー チャートを作成することができました。

しかし!私たちの旅は星の海へ!いくつかの材料を追加する必要があります!

完全に静的なレーダーチャートはあまりにも退屈で平凡です。アニメーション化する方法を考えなければなりません。

レーダーチャートデータの値は配列形式になっています。これらの値をどのように動かすか考えたことはありますか?

Cocos Creator が提供するTween イージング システムのおかげで、複雑なデータをアニメーション化することが非常に簡単になりました。

これを、これを、そしてあれをやるだけ。簡単ですよね?

cc.tweenあらゆるオブジェクトのあらゆるプロパティの緩和をサポートします

イージング システム: http://docs.cocos.com/creator/manual/zh/scripting/tween.html

また、「万能穴掘りシェーダー」のイージングシステムも利用して穴掘りの動きを作ってみました~

オンラインプレビュー: https://ifaswind.gitee.io/eazax-cases/?case=newGuide

私の考えは:

  1. 現在のデータを現在のインスタンスのthis.curDatasに保存します
  2. 新しいデータを受信したら、 cc.tweenを使用してthis.curDataのプロパティを緩和します。
  3. update時にdraw関数を呼び出して、フレームごとにthis.curDatasのデータを再描画します。

すべてのフレームを更新

// 現在のレーダーチャートデータ private curDatas: RadarChartData[] = [];

保護された更新() {
    if (!this.keepUpdating) 戻り値:
    // 現在のデータを描画します this.draw(this.curDatas);
}

緩和データ

/**
 * スローモーション描画* @param data ターゲットデータ* @paramduration アニメーション期間*/
パブリック to(データ: RadarChartData | RadarChartData[], 期間: 数値) {
    // 繰り返しの呼び出しを処理します this.unscheduleAllCallbacks();
    
    // 単一のデータ部分をパックします const datas = Array.isArray(data) ? data : [data];

    // 各フレームの更新をオンにします this.keepUpdating = true;

    // 動く!
    (i = 0 とします; i < datas.length; i++) {
        // 値をアニメーション化します。
        // データ内のすべての値を走査し、1つずつ移動させます。
        (j = 0 とします; j < this.curDatas[i].values.length; j++) {
            // 最大値を 1 (つまり 100%) に制限します
            定数値 = datas[i].values[j] > 1 ? 1 : datas[i].values[j];
            cc.tween(this.curDatas[i].values)
                .to(期間, { [j]: 値 })
                。始める();
        }
        // 動きのあるスタイル!
        // 指定されていない場合は、元のスタイルが使用されます。
        cc.tween(this.curDatas[i])
            .to(期間, {
                線幅: datas[i].lineWidth || this.curDatas[i].lineWidth,
                線の色: datas[i].lineColor || this.curDatas[i].lineColor,
                塗りつぶし色: datas[i].fillColor || this.curDatas[i].fillColor,
                結合カラー: datas[i].結合カラー || this.curDatas[i].結合カラー
            })
            。始める();
    }

    this.scheduleOnce(() => {
        // 各フレームの更新をオフにします this.keepUpdating = false;
    }、 間隔);
}

値とスタイルの両方がアニメーション化されます。

レーダーチャート コンポーネント: https://gitee.com/ifaswind/eazax-ccc/blob/master/components/RadarChart.ts

上記は、CocosCreator でクールなレーダーチャートを描く方法の詳細です。CocosCreator でレーダーチャートを描く方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Unity は物理エンジンを使用してマルチロータードローンの飛行をシミュレートします
  • Android 向け 2D 物理エンジン Box2d を使用する簡単な例
  • CocosCreator ソースコードの解釈: エンジンの起動とメインループ
  • CocosCreator 一般的なフレームワーク設計リソース管理
  • CocosCreatorでリストを作成する方法
  • CocosCreator の新しいリソース管理システムの分析
  • CocosCreator スケルトンアニメーション ドラゴンボーン
  • CocosCreatorでシューティングゲームを作る詳しい解説
  • CocosCreator MVCアーキテクチャの詳細な説明
  • CocosCreator で物理エンジン ジョイントを使用する方法

<<:  MySql Group Byは複数のフィールドのグループ化を実装します

>>:  Linux テキスト検索コマンド find の詳細な使用方法

推薦する

ホストNginx + Docker WordPress Mysqlを設定するための詳細な手順

環境Linux 3.10.0-693.el7.x86_64 Docker バージョン 18.09.0...

docker ベースの redis-sentinel クラスターの構築例

1. 概要Redis Cluster は、Redis ノードのグループ間での高可用性とシャーディング...

Ubuntuがインターネットに接続できない場合の解決策

問題の説明:デスクトップ コンピューターとキャンパス ネットワークを使用して、有線モードでインターネ...

Web開発で使用される基本的な概念と技術の紹介

本日は、Web 開発で使われる基本的な概念と技術を初心者向けに紹介します。A から Z まで合計 2...

WebpackはTypeScriptコードをパッケージ化するためのスキャフォールディングを構築します

フォルダを作成するディレクトリ構造: dabaots npm init -yを初期化して packa...

Gokudōゲームにおけるフロントエンド知識のまとめ

背景日本語を学び始めた当初は、日本語の50音を覚えるのは簡単ではなく、特にカタカナを覚えるのは困難で...

node-media-serverを使用してシンプルなストリーミングメディアサーバーを構築する

node-media-server を使用するプロセスの一部を記録します。この記事の環境はWindo...

CocosCreator ソースコードの解釈: エンジンの起動とメインループ

目次序文準備行く!文章プロセスを開始するメインループまとめ要約する序文準備皆さんは、こんなことを考え...

HTML チュートリアル: DOCTYPE の省略形

HTML コードを書くとき、最初の行は DOCTYPE にする必要がありますが、DOCTYPE は通...

MySQLのサブクエリユニオンの効率性についての簡単な説明と

最近の製品テストでは、同時呼び出し数が 10 未満の場合に応答時間が 100 ミリ秒以内に維持できな...

CentOS7 64 ビットでの MySQL 5.7 のインストールと設定のチュートリアル

インストール環境: CentOS7 64ビットMINI版、MySQL5.7をインストール1. YUM...

jsは前のページに戻り、コードを更新します

1. Javascript は前のページ history.go(-1) に戻り、2 つのページを返し...

mysql 基本操作文コマンドの詳細な説明

1. MySQLに接続するフォーマット: mysql -h ホストアドレス -u ユーザー名 -p ...

HTMLはキャンバスを使用して箇条書きスクリーン機能を実装します

導入最近、大きな課題をこなす際に、弾幕プレイヤーを作る必要がありました。他の人のソースコードを借りて...

MySQL ツリー構造データベース テーブル設計

目次序文1. 基本データ2. 継承駆動設計3. 左右の値のエンコーディングに基づく設計4. ツリー構...