亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何在CocosCreator里畫個炫酷的雷達(dá)圖

 更新時間:2021年04月15日 16:28:38   作者:文弱書生陳皮皮  
這篇文章主要介紹了如何在CocosCreator里畫個炫酷的雷達(dá)圖,對Graphics感興趣的同學(xué),一定要看看,并且把代碼實踐一下

前言

雷達(dá)圖(Radar Chart) 也稱為網(wǎng)絡(luò)圖、星圖或蜘蛛網(wǎng)圖。

是以從同一點開始的軸上表示的三個或更多個定量變量的二維圖表的形式顯示多元數(shù)據(jù)的圖形方法。

適用于顯示三個或更多的維度的變量。

雷達(dá)圖常用于📚數(shù)據(jù)統(tǒng)計或?qū)Ρ?,對于查看哪些變量具有相似的值、變量之間是否有異常值都很有用。

同時在不少游戲中都有雷達(dá)圖的身影,可以很直觀地展示并對比一些數(shù)據(jù)。

例如王者榮耀中的對戰(zhàn)資料中就用到了:

那么在本篇文章中,皮皮就來分享下在 Cocos Creator 中如何利用 Graphics 組件來繪制炫酷的雷達(dá)圖~

文中會對原始代碼進(jìn)行一定的削減以保證閱讀體驗。

雷達(dá)圖組件:https://gitee.com/ifaswind/eazax-ccc/blob/master/components/RadarChart.ts


預(yù)覽

先來看看效果吧~

在線預(yù)覽:https://ifaswind.gitee.io/eazax-cases/?case=radarChart

兩條數(shù)據(jù)

緩動數(shù)據(jù)

花里胡哨

藝術(shù)就是爆炸

逐漸偏離主題

正文

Graphics 組件

在我們正式開始制作雷達(dá)圖之前,讓我們先來大概了解一下 Cocos Creator 引擎中的 Graphics 組件。

Graphics 組件繼承于 cc.RenderComponent,利用該組件我們可以實現(xiàn)畫板和表格之類的功能。

屬性(Properties)

下面是我們本次將會用到的屬性:

  • lineCap:設(shè)置或返回線條兩端的樣式(無、圓形線帽或方形線帽)
  • lineJoin:設(shè)置或返回兩條線相交時的拐角樣式(斜角、圓角或尖角)
  • lineWidth:設(shè)置或返回當(dāng)前畫筆的粗細(xì)(線條的寬度)
  • strokeColor:設(shè)置或返回當(dāng)前畫筆的顏色
  • fillColor:設(shè)置或返回填充用的顏色(油漆桶)

函數(shù)(Functions)

下面是我們本次將會用到的函數(shù):

  • moveTo(x, y):抬起畫筆并移動到指定位置(不創(chuàng)建線條)
  • lineTo(x, y):放下畫筆并創(chuàng)建一條直線至指定位置
  • circle(cx, cy, r):在指定位置(圓心)畫一個圓
  • close():閉合已創(chuàng)建的線條(相當(dāng)于 lineTo(起點)
  • stroke():繪制已創(chuàng)建(但未被繪制)的線條(將線條想象成默認(rèn)透明的,此行為則是賦予線條顏色)
  • fill():填充當(dāng)前線條包圍的區(qū)域(如果線條沒有閉合則會嘗試”模擬閉合“起點和終點)
  • clear():擦掉當(dāng)前畫板上的所有東西

Graphics 組件文檔:http://docs.cocos.com/creator/manual/zh/components/graphics.html?h=graphics

畫網(wǎng)格

先來看看一個標(biāo)準(zhǔn)的雷達(dá)圖有啥特點:

發(fā)現(xiàn)了嗎?雷達(dá)圖的基本特點如下:

  • 有 3 條或以上的軸線
  • 軸與軸之間的夾角相同
  • 每條軸上除中心點外應(yīng)至少有 1 個刻度
  • 每條軸上都有相同的刻度
  • 刻度與刻度之間的距離也相同
  • 軸之間的刻度相連形成網(wǎng)格線

計算軸線角度

先算出軸之間的夾角度數(shù) [ 360 ÷ 軸數(shù) ],再計算所有軸的角度:

this.angles = [];
// 軸間夾角
const iAngle = 360 / this.axes;
for (let i = 0; i < this.axes; i++) {
    // 計算
    const angle = iAngle * i;
    this.angles.push(angle);
}

計算刻度坐標(biāo)

雷達(dá)圖至少擁有 3 條軸,且每條軸上都應(yīng)有 1 個或以上的刻度(不包含中心點)

所以我們需使用一個二維數(shù)組來保存所有刻度的坐標(biāo),從最外層(即軸線的末端)的刻度開始記錄,方便我們繪制時讀?。?/p>

// 創(chuàng)建一個二維數(shù)組
let scalesSet: cc.Vec2[][] = [];
for (let i = 0; i < 軸上刻度個數(shù); i++) {
    // 用來保存當(dāng)前層上的刻度坐標(biāo)
    let scales = [];
    // 計算刻度在軸上的位置
    const length = 軸線長度 - (軸線長度 / 軸上刻度個數(shù) * i);
    for (let j = 0; j < this.angles.length; j++) {
        // 將角度轉(zhuǎn)為弧度
        const radian = (Math.PI / 180) * this.angles[j];
        // 根據(jù)三角公式計算刻度相對于中心點(0, 0)的坐標(biāo)
        const pos = cc.v2(length * Math.cos(radian), length * Math.sin(radian));
        // 推進(jìn)數(shù)組
        scales.push(pos);
    }
    // 推進(jìn)二維數(shù)組
    scalesSet.push(scales);
}

繪制軸線和外網(wǎng)格線

軸線

連接中心點 (0, 0) 和最外層 scalesSet[0] 的刻度即為軸線:

// 遍歷全部最外層的刻度
for (let i = 0; i < scalesSet[0].length; i++) {
    // 畫筆移動至中心點
    this.graphics.moveTo(0, 0);
    // 創(chuàng)建線條
    this.graphics.lineTo(scalesSet[0][i].x, scalesSet[0][i].y);
}

外網(wǎng)格線

連接所有軸上最外層 scalesSet[0] 的刻度即形成外網(wǎng)格線:

// 畫筆移動至第一個點
this.graphics.moveTo(scalesSet[0][0].x, scalesSet[0][0].y);
for (let i = 1; i < scalesSet[0].length; i++) {
    // 創(chuàng)建線條
    this.graphics.lineTo(scalesSet[0][i].x, scalesSet[0][i].y);
}
// 閉合當(dāng)前線條(外網(wǎng)格線)
this.graphics.close();

填充并繪制

這里需要注意先填充顏色再繪制線條,要不然軸線和網(wǎng)格線就被擋住了:

// 填充線條包圍的空白區(qū)域
this.graphics.fill();
// 繪制已創(chuàng)建的線條(軸線和外網(wǎng)格線)
this.graphics.stroke();

于是現(xiàn)在我們就有了這么個玩意兒:

繪制內(nèi)網(wǎng)格線

當(dāng)刻度大于 1 個時就需要繪制內(nèi)網(wǎng)格線,從刻度坐標(biāo)集的下標(biāo) 1 開始繪制:

// 刻度大于 1 個時才繪制內(nèi)網(wǎng)格線
if (scalesSet.length > 1) {
    // 從下邊 1 開始(下標(biāo) 0 是外網(wǎng)格線)
    for (let i = 1; i < scalesSet.length; i++) {
        // 畫筆移動至第一個點
        this.graphics.moveTo(scalesSet[i][0].x, scalesSet[i][0].y);
        for (let j = 1; j < scalesSet[i].length; j++) {
            // 創(chuàng)建線條
            this.graphics.lineTo(scalesSet[i][j].x, scalesSet[i][j].y);
        }
        // 閉合當(dāng)前線條(內(nèi)網(wǎng)格線)
        this.graphics.close();
    }
    // 繪制已創(chuàng)建的線條(內(nèi)網(wǎng)格線)
    this.graphics.stroke();
}

就這樣我們雷達(dá)圖的底子就畫好啦:

畫數(shù)據(jù) 

編寫畫線邏輯之前,先確定一下我們需要的數(shù)據(jù)結(jié)構(gòu):

  • 數(shù)值數(shù)組(必須,小數(shù)形式的比例,至少包含 3 個值)
  • 線的寬度(可選,不指定則使用默認(rèn)值)
  • 線的顏色(可選,不指定則使用默認(rèn)值)
  • 填充的顏色(可選,不指定則使用默認(rèn)值)
  • 節(jié)點的顏色(可選,不指定則使用默認(rèn)值)

具體的數(shù)據(jù)結(jié)構(gòu)如下(導(dǎo)出類型方便外部使用):

/**
 * 雷達(dá)圖數(shù)據(jù)
 */
export interface RadarChartData {

    /** 數(shù)值 */
    values: number[];

    /** 線的寬度 */
    lineWidth?: number;

    /** 線的顏色 */
    lineColor?: cc.Color;

    /** 填充的顏色 */
    fillColor?: cc.Color;

    /** 節(jié)點的顏色 */
    joinColor?: cc.Color;

}

繪制數(shù)據(jù)

繪制數(shù)據(jù)比較簡單,我們只需要算出數(shù)據(jù)點在圖表中的位置,并將數(shù)據(jù)連起來就好了。

draw 函數(shù)中我們接收一份或以上的雷達(dá)圖數(shù)據(jù),并按照順序遍歷繪制出來(⚠️長代碼警告):

/**
 * 繪制數(shù)據(jù)
 * @param data 數(shù)據(jù)
 */
public draw(data: RadarChartData | RadarChartData[]) {
    // 處理數(shù)據(jù)
    const datas = Array.isArray(data) ? data : [data];

    // 開始繪制數(shù)據(jù)
    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;

        // 計算節(jié)點坐標(biāo)
        let coords = [];
        for (let j = 0; j < this.axes; j++) {
            const value = datas[i].values[j] > 1 ? 1 : datas[i].values[j];
            const length = value * this.axisLength;
            const radian = (Math.PI / 180) * this.angles[j];
            const pos = cc.v2(length * Math.cos(radian), length * Math.sin(radian))
            coords.push(pos);
        }

        // 創(chuàng)建線條
        this.graphics.moveTo(coords[0].x, coords[0].y);
        for (let j = 1; j < coords.length; j++) {
            this.graphics.lineTo(coords[j].x, coords[j].y);
        }
        this.graphics.close(); // 閉合線條
        
        // 填充包圍區(qū)域
        this.graphics.fill();
        // 繪制線條
        this.graphics.stroke();

        // 繪制數(shù)據(jù)節(jié)點
        for (let j = 0; j < coords.length; j++) {
            // 大圓
            this.graphics.strokeColor = datas[i].lineColor || defaultOptions.lineColor;
            this.graphics.circle(coords[j].x, coords[j].y, 2);
            this.graphics.stroke();
            // 小圓
            this.graphics.strokeColor = datas[i].joinColor || defaultOptions.joinColor;
            this.graphics.circle(coords[j].x, coords[j].y, .65);
            this.graphics.stroke();
        }

    }
}

到這里我們已經(jīng)成功制作了一個可用的雷達(dá)圖:

但是!我們的征途是星辰大海!必須加點料!

完全靜態(tài)的雷達(dá)圖實在是太無趣太普通,得想想辦法讓它動起來!

我們的雷達(dá)圖數(shù)據(jù)的數(shù)值是數(shù)組形式,想到怎么樣才能讓這些數(shù)值動起來了嗎?

得益于 Cocos Creator 為我們提供的 Tween 緩動系統(tǒng),讓復(fù)雜的數(shù)據(jù)動起來變得異常簡單!

我們只需要這樣,這樣,然后那樣,是不是很簡單?

cc.tween 支持緩動任意對象的任意屬性

緩動系統(tǒng):http://docs.cocos.com/creator/manual/zh/scripting/tween.html

另外我在《一個全能的挖孔 Shader》中也是使用了緩動系統(tǒng)來讓挖孔動起來~

在線預(yù)覽:https://ifaswind.gitee.io/eazax-cases/?case=newGuide

我的思路是:

  1. 將當(dāng)前的數(shù)據(jù)保存到當(dāng)前實例的 this.curDatas
  2. 接收到新的數(shù)據(jù)時,使用 cc.tweenthis.curData 的屬性進(jìn)行緩動
  3. update 中調(diào)用 draw 函數(shù),每幀都重新繪制 this.curDatas 中的數(shù)據(jù)

每幀更新

// 當(dāng)前雷達(dá)圖數(shù)據(jù)
private curDatas: RadarChartData[] = [];

protected update() {
    if (!this.keepUpdating) return;
    // 繪制當(dāng)前數(shù)據(jù)
    this.draw(this.curDatas);
}

緩動數(shù)據(jù)

/**
 * 緩動繪制
 * @param data 目標(biāo)數(shù)據(jù)
 * @param duration 動畫時長
 */
public to(data: RadarChartData | RadarChartData[], duration: number) {
    // 處理重復(fù)調(diào)用
    this.unscheduleAllCallbacks();
    
    // 包裝單條數(shù)據(jù)
    const datas = Array.isArray(data) ? data : [data];

    // 打開每幀更新
    this.keepUpdating = true;

    // 動起來!
    for (let i = 0; i < datas.length; i++) {
        // 數(shù)值動起來!
        // 遍歷數(shù)據(jù)中的全部數(shù)值,逐個讓他們動起來!
        for (let j = 0; j < this.curDatas[i].values.length; j++) {
            // 限制最大值為 1(即 100%)
            const value = datas[i].values[j] > 1 ? 1 : datas[i].values[j];
            cc.tween(this.curDatas[i].values)
                .to(duration, { [j]: value })
                .start();
        }
        // 樣式動起來!
        // 沒有指定則使用原來的樣式!
        cc.tween(this.curDatas[i])
            .to(duration, {
                lineWidth: datas[i].lineWidth || this.curDatas[i].lineWidth,
                lineColor: datas[i].lineColor || this.curDatas[i].lineColor,
                fillColor: datas[i].fillColor || this.curDatas[i].fillColor,
                joinColor: datas[i].joinColor || this.curDatas[i].joinColor
            })
            .start();
    }

    this.scheduleOnce(() => {
        // 關(guān)閉每幀更新
        this.keepUpdating = false;
    }, duration);
}

數(shù)值和樣式都動起來了:

雷達(dá)圖組件:https://gitee.com/ifaswind/eazax-ccc/blob/master/components/RadarChart.ts

以上就是如何在CocosCreator里畫個炫酷的雷達(dá)圖的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator畫個雷達(dá)圖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ES6新特性七:數(shù)組的擴(kuò)充詳解

    ES6新特性七:數(shù)組的擴(kuò)充詳解

    這篇文章主要介紹了ES6新特性之?dāng)?shù)組的擴(kuò)充,結(jié)合實例形式分析了ES6數(shù)組操作的常見方法與相關(guān)使用技巧,需要的朋友可以參考下
    2017-04-04
  • JS運動特效之完美運動框架實例分析

    JS運動特效之完美運動框架實例分析

    這篇文章主要介紹了JS運動特效之完美運動框架,結(jié)合實例形式分析了javascript針對運動中的元素屬性檢測與判斷相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • 用JS寫的一個TableView控件代碼

    用JS寫的一個TableView控件代碼

    JS寫的一個TableView控件代碼,方便輸出表格。
    2010-01-01
  • 判斷js對象是否擁有某一個屬性的js代碼

    判斷js對象是否擁有某一個屬性的js代碼

    js對象是否擁有某一個屬性的判斷方法有很多,下面為大家介紹個比較實用的技巧,希望對大家有所幫助
    2013-08-08
  • JavaScript封裝單向鏈表的示例代碼

    JavaScript封裝單向鏈表的示例代碼

    這篇文章主要介紹了JavaScript如何封裝單向鏈表,幫助大家更好的理解和使用JavaScript,感興趣的朋友可以了解下
    2020-09-09
  • Javascript & DHTML DOM基礎(chǔ)和基本API

    Javascript & DHTML DOM基礎(chǔ)和基本API

    DOM是文檔對象模型(Document Object Model,是基于瀏覽器編程(在本教程中,可以說就是DHTML編程)的一套API接口,W3C出臺的推薦標(biāo)準(zhǔn),每個瀏覽器都有一些細(xì)微的差別,其中以Mozilla的瀏覽器最與標(biāo)準(zhǔn)接近。
    2008-07-07
  • 簡述JS瀏覽器的三種彈窗

    簡述JS瀏覽器的三種彈窗

    本文給大家簡單介紹了JS瀏覽器的三種彈窗,簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-07-07
  • 詳解CocosCreator消息分發(fā)機制

    詳解CocosCreator消息分發(fā)機制

    這篇文章主要介紹了詳解CocosCreator消息分發(fā)機制,詳細(xì)介紹了各模塊的設(shè)計,同學(xué)們一定要自己看下
    2021-04-04
  • js優(yōu)化針對IE6.0起作用(詳細(xì)整理)

    js優(yōu)化針對IE6.0起作用(詳細(xì)整理)

    js優(yōu)化針對IE6.0起作用,總結(jié)一下幾點:字符串拼接、for 循環(huán)、減少頁面的重繪、減少作用域鏈上的查找次數(shù)、避免雙重解釋等等,需要了解的朋友可以參考下,或許會有所幫助
    2012-12-12
  • 原生微信小程序/uniapp使用空格占位符無效的解決辦法

    原生微信小程序/uniapp使用空格占位符無效的解決辦法

    最近需要在字體中間加空白占位符,在嘗試使用 之后,還是不能使用,下面這篇文章主要給大家介紹了關(guān)于原生微信小程序/uniapp使用空格占位符無效的解決辦法,需要的朋友可以參考下
    2023-02-02

最新評論