【帶著canvas去流浪(6)】繪製雷達圖

来源:https://www.cnblogs.com/dashnowords/archive/2019/04/04/10656750.html
-Advertisement-
Play Games

示例代碼托管在: "http://www.github.com/dashnowords/blogs" 博客園地址: "《大史住在大前端》原創博文目錄" 華為雲社區地址: "【你要的前端打怪升級指南】" [TOC] 一. 任務說明 使用原生 繪製雷達圖。(截圖以及數據來自於百度Echarts官方示例庫 ...


目錄

示例代碼托管在:http://www.github.com/dashnowords/blogs

博客園地址:《大史住在大前端》原創博文目錄

華為雲社區地址:【你要的前端打怪升級指南】

一. 任務說明

使用原生canvasAPI繪製雷達圖。(截圖以及數據來自於百度Echarts官方示例庫【查看示例鏈接】)。

二. 重點提示

雷達圖繪製的看起來並不複雜,無非就是一些路徑點的連線,其中的難點都在於一些細節。

  1. 坐標轉換

    為了避免在繪製過程中不斷根據夾角來計算某個數據點的坐標,我們可以讓坐標系先移動到繪圖中心,然後在繪製過程中逐步旋轉並使用context.lineTo(x,y)來連線即可,這樣做的好處是很明顯的。比如在繪製背景六邊形的時候,每次旋轉後,路徑點壓根就不需要移動,直接在迴圈中每次都調用context.lineTo( )方法連線至同一個數據點即可,看起來位移沒有變,實際上隨著坐標系的旋轉,連線繞過的是多邊形的軌跡。

  2. 文字的對齊

    為了讓文字保持正常的方向,我們需要將坐標系的旋轉恢復到初始狀態再進行繪製。繪製的過程中可以根據繪製點和中心連線相對於x軸的角度來動態修改其繪製時的相對點(left,right,center),否則就會出現下圖的結果,也就是文字區域的中心到圖形中心的距離的確是一致的,但這並不是我們想要的效果。

  1. canvas坐標系

    請時刻記得canvas坐標系的初始方向是x軸向右,y軸向下,和普通笛卡爾坐標系是不一樣的,尤其是在旋轉角度和坐標計算的時候,很容易出現和預期角度不相符的結果。

三. 示例代碼

//options數據來自於百度Echarts官方示例庫
start(options);

/**
 * 繪製圖表
 */
function start(options) {
    drawBg(options);
    drawData(options);//繪製雷達圖
    drawText(options);//繪製文字
}

function drawBg(options) {
    let length = options.radar.indicator.length;
    let angleStep = -2 * Math.PI / length;
    context.strokeStyle="#b2b2b2";
    context.lineWidth = 1;
    //調整坐標系
    //移動中心點
    context.translate(500,300);
    //將x軸旋轉至豎直向上
    context.rotate(-90 * 2 * Math.PI / 360);
    //每次以不同旋轉半徑繪製多個由大到小的圖形
    for(let r = 200; r > 0 ; r -=40){
        //移動至第一個繪圖點
        context.save();
        context.beginPath();
        context.moveTo(r,0);
        
        //轉動坐標系繪製所有點
         for(let i = 0; i < length; i++){
            context.rotate(angleStep);
            context.lineTo(r,0);
         }
        context.closePath();
        context.stroke();
        //明暗色替換填充,此處從大到小切換顏色覆蓋式繪製即可
        context.fillStyle = Math.round(r / 40) % 2 ? 'white':'#eaeaea';
        context.fill();
        context.restore();
    }
}

/**
 * 繪製數據
 */
function drawData(options) {
   //解構賦值拿到數據關鍵點
   let {radar:{indicator:indicators},series:[{data:data}]} = options;
   let colors = ['#c43e3a','#364c5a'];
   let length = indicators.length;
   let angleStep = -2 * Math.PI / length;

   for(let i = 0; i < data.length; i++){
       
       context.save();
       context.beginPath();
       context.moveTo(200 * data[i].value[0] / indicators[0].max,0);
    
       //遍歷每組數據
       for(let j = 1; j < data[i].value.length; j++){
           context.rotate(angleStep);
           context.lineTo(200 * data[i].value[j] / indicators[j].max,0);
       }
       context.restore();
       context.lineTo(200 * data[i].value[0] / indicators[0].max,0);
       context.strokeStyle = colors[i];
       context.lineWidth = 2;
       context.stroke();
   }
   context.restore();
}

//繪製文字
function drawText(options) {
   let {radar:{indicator:indicators}} = options;
   let length = indicators.length;
   let angleStep = 2 * Math.PI / length;
   let r = 220;
   context.fillStyle = 'black';
   context.font = "14px bold 黑體";
   context.textAlign = 'center';
   context.rotate(90 * Math.PI * 2 / 360);
   for(let i = 0; i < indicators.length; i++){
     let curAngle = -90*2*Math.PI/360 - angleStep*i;
       //根據方向調整文字的對齊點
     let cos = Math.cos(curAngle);
     if (Math.abs(cos) < 10e-4) {
        context.textAlign = 'center';
     }else if(cos > 0){
        context.textAlign = 'left';
     }else{
        context.textAlign = 'right';
     }
     console.log(indicators[i].name, Math.cos(curAngle))
      context.fillText(indicators[i].name, r * Math.cos(curAngle), r * Math.sin(curAngle));
   }
}

瀏覽器中可查看效果:

百度Echarts官方示例庫中有這樣一個雷達圖的示例,展示了在雷達圖上表現時間維度的示例,感興趣的讀者可以自行查看。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有關關係資料庫範式的講解,有一篇非常好的文章,推薦給大家,可以幫助大家理解範式的含義、作用。解釋一下關係資料庫的第一第二第三範式? - 知乎用戶的回答 - 知乎https://www.zhihu.com/question/24696366/answer/29189700 ...
  • 1.無論何時只要有多個查詢在同一時刻修改數據,都會產生併發控制的問題 2.討論mysql在兩個層面,伺服器層和存儲引擎層,如何併發控制讀寫 3.舉了個mbox郵箱文件的例子,說如果有多個進程同時對mbox文件寫東西,那麼在文件的末尾會,交叉混亂的添加,比如進程1寫了幾行,進程2也寫了幾行,互相交叉, ...
  • 筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 (本篇內圖片均來自丁奇老師的講解,如有侵權,請聯繫我刪除) 16) --“order by”是怎麼工作的? 在林老師的課程中,第15講是前面問題的答疑,我打算最後將答疑問題統一整理出來,所以就繼續這些內容的筆記了。 全欄位排序: 假設有一個表是 ...
  • pt table checksum Verify MySQL replication integrity. pt table checksum performs an online replication consistency check by executing checksum queries ...
  • 一、項目簡介 基於Vue2.0+Vuex+vue-router+webpack2.0+es6+vuePhotoPreview+wcPop等技術架構開發的仿微信界面聊天室——vueChatRoom,實現了微信聊天下拉刷新、發送消息、表情(動圖),圖片、視頻預覽,打賞、紅包等功能。 二、技術棧 MVVM ...
  • JavaScript 數組: 1、它是值的有序集合 2、是無類型的,接受任意類型,且同個數組可以擁有多種類型 3、索引是基於 0 的 32 位數值,最大可能索引為 2^32-2 4、是動態的,在改變數組大小時不需重新分配空間 5、可以是稀疏的,即索引不一定要連續,元素與元素之間允許有空缺 6、有一個 ...
  • 3 運算符 按照個數分類可分為:一元運算符、二元運算符、三元運算符; 按照功能分類可分為:算數運算符、自增運算符、比較運算符、邏輯運算符、賦值運算符; 3.1 算數運算符 算術運算符包含了加減乘除,符號表示如下: 3.2 自增(自減)運算符 自增運算符 1 前置自增運算符 2 後置自增運算符 區別: ...
  • 一、Express路由簡介 路由表示應用程式端點 (URI) 的定義以及響應客戶端請求的方式。它包含一個請求方時(methods)、路徑(path)和路由匹配時的函數(callback); 二、Express路由方法 Express方法源於 HTTP 方法之一,附加到 express 類的實例。它可 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...