最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

D3.js實現(xiàn)雷達圖的方法詳解

 更新時間:2016年09月22日 08:41:02   投稿:daisy  
大家應(yīng)該都知道基本圖表一共有六種,分別是柱狀圖、折線圖、散點圖、氣泡圖、餅圖和雷達圖。前面五種圖形都已經(jīng)介紹過如何實現(xiàn)了,今天我們一起來看看最后的雷達圖。有需要的朋友們可以參考學(xué)習(xí)下。

前言

再簡單介紹下D3.js,D3.js 是一個基于數(shù)據(jù)操作文檔JavaScript庫。D3幫助你給數(shù)據(jù)帶來活力通過使用HTML、SVG和CSS。D3重視Web標準為你提供現(xiàn)代瀏覽器的全部功能,而不是給你一個專有的框架。結(jié)合強大的可視化組件和數(shù)據(jù)驅(qū)動方式Dom操作。這里也可以看到它是用SVG來呈現(xiàn)圖表的,所以使用D3.js是需要一定的SVG基礎(chǔ)的。

本文依然是先把簡單的畫圖框架搭起來,添加SVG畫布。這里和餅圖有點類似,為了方便后面的繪制,我們把組合這些元素的g元素移動到畫布的中心:

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>雷達圖</title>
  <style>
   .container {
    margin: 30px auto;
    width: 600px;
    height: 300px;
    border: 1px solid #000;
   }

  </style>
 </head>
 <body>
  <div class="container">
   <svg width="100%" height="100%"></svg>
  </div>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script>
   window.onload = function() {
    var width = 600, height = 300;
    // 創(chuàng)建一個分組用來組合要畫的圖表元素
    var main = d3.select('.container svg').append('g')
      .classed('main', true)
      .attr('transform', "translate(" + width/2 + ',' + height/2 + ')');

   };
   function getColor(idx) {
    var palette = [
     '#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80',
     '#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa',
     '#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050',
     '#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089'
    ]
    return palette[idx % palette.length];
   }
  </script>
 </body>
</html>

這里為什么我會說雷達圖和餅圖會有點類似呢?看一下下面這張圖。

可以看到,雷達圖的網(wǎng)軸(藍色部分)是由多個正多邊形所組成的,而正多邊形的繪制正好是可以利用圓半徑的特性來繪制的,所以從一開始把繪制的原點移動到畫布的中心是很方便后面的繪制工作的。

模擬數(shù)據(jù)

我們先模擬一些原始數(shù)據(jù)。

var data = {
 fieldNames: ['語文','數(shù)學(xué)','外語','物理','化學(xué)','生物','政治','歷史'],
 values: [
  [10,20,30,40,50,60,70,80]
 ]
};

計算網(wǎng)軸坐標并繪制

在前面的其他圖表的實現(xiàn)中,都有比例尺或者布局這樣的東西來為我們轉(zhuǎn)化數(shù)據(jù)提供便利,雷達圖是否也存在這樣的工具函數(shù)呢?答案是沒有!沒有!沒有!重要的事情說三遍!(-_-) 所以,我們只能開動自己的小腦瓜自己算了。

// 設(shè)定一些方便計算的常量
var radius = 100,
 // 指標的個數(shù),即fieldNames的長度
 total = 8,
 // 需要將網(wǎng)軸分成幾級,即網(wǎng)軸上從小到大有多少個正多邊形
 level = 4,
 // 網(wǎng)軸的范圍,類似坐標軸
 rangeMin = 0,
 rangeMax = 100,
 arc = 2 * Math.PI;
// 每項指標所在的角度
var onePiece = arc/total;
// 計算網(wǎng)軸的正多邊形的坐標
var polygons = {
 webs: [],
 webPoints: []
};
for(var k=level;k>0;k--) {
 var webs = '',
   webPoints = [];
 var r = radius/level * k;
 for(var i=0;i<total;i++) {
  var x = r * Math.sin(i * onePiece),
   y = r * Math.cos(i * onePiece);
  webs += x + ',' + y + ' ';
  webPoints.push({
   x: x,
   y: y
  });
 }
 polygons.webs.push(webs);
 polygons.webPoints.push(webPoints);
} 

計算網(wǎng)軸的坐標就是計算一個個多邊形的各點坐標,為了后面添加polygon元素時方便繪制(points屬性的賦值),我們需要在求點坐標的時候順便把它們拼成字符串。上述代碼的for循環(huán)中,外層循環(huán)代表一個多邊形,內(nèi)層循環(huán)代表多邊形上的點,多邊形與多邊形之間差異僅僅在于它們的外圓的半徑不同,而同一多邊形的點與點之間的差異在于它們的角度不同。點的坐標由半徑乘以角度的正弦或者余弦來求得。

得到了計算好的坐標以后,我們就開始添加網(wǎng)軸。

// 繪制網(wǎng)軸
var webs = main.append('g')
  .classed('webs', true);
webs.selectAll('polygon')
  .data(polygons.webs)
  .enter()
  .append('polygon')
  .attr('points', function(d) {
   return d;
  });

添加一個g元素用來組合所有代表網(wǎng)軸的元素,選擇其中的polygon元素并綁定polygons.webs數(shù)組,enter()搭配append()添加新的polygon元素,對points屬性進行復(fù)制。完成這一系列在前面幾篇文章中已經(jīng)反復(fù)練習(xí)的操作以后,為了讓網(wǎng)軸更加的明顯,我們給它加一點樣式。

.webs polygon {
 fill: white;
 fill-opacity: 0.5;
 stroke: gray;
 stroke-dasharray: 10 5;
} 

我們得到了如下圖所示的網(wǎng)軸。

添加縱軸

接著我們把縱軸也添加上??v軸就是添加一根根的線條,連接中心點和最外層的多邊形上的點,需要的數(shù)據(jù)可以從polygons.webPoints[0]中取。

// 添加縱軸
var lines = main.append('g')
  .classed('lines', true);
lines.selectAll('line')
  .data(polygons.webPoints[0])
  .enter()
  .append('line')
  .attr('x1', 0)
  .attr('y1', 0)
  .attr('x2', function(d) {
   return d.x;
  })
  .attr('y2', function(d) {
   return d.y;
  });

雷達圖的坐標軸部分就完成了。

計算雷達圖區(qū)域并添加

雷達圖區(qū)域也是一個多邊形,只不過是一個不規(guī)則的多邊形。但是他的幾個點始終處在縱軸上,并且點在縱軸上的位置可以通過點所代表的值在縱軸范圍內(nèi)的占比計算出來的。

// 計算雷達圖表的坐標
var areasData = [];
var values = data.values;
for(var i=0;i<values.length;i++) {
 var value = values[i],
   area = '',
   points = [];
 for(var k=0;k<total;k++) {
  var r = radius * (value[k] - rangeMin)/(rangeMax - rangeMin);
  var x = r * Math.sin(k * onePiece),
   y = r * Math.cos(k * onePiece);
  area += x + ',' + y + ' ';
  points.push({
   x: x,
   y: y
  })
 }
 areasData.push({
  polygon: area,
  points: points
 });
}

計算完點的坐標以后我們就可以添加雷達圖區(qū)域了。為了使雷達圖更可觀,我們除了添加多邊形表示雷達圖的區(qū)域以外,也把多邊形在各縱軸上的點標記出來。

// 添加g分組包含所有雷達圖區(qū)域
var areas = main.append('g')
 .classed('areas', true);
// 添加g分組用來包含一個雷達圖區(qū)域下的多邊形以及圓點 
areas.selectAll('g')
 .data(areasData)
 .enter()
 .append('g')
 .attr('class',function(d, i) {
  return 'area' + (i+1);
 });
for(var i=0;i<areasData.length;i++) {
 // 依次循環(huán)每個雷達圖區(qū)域
 var area = areas.select('.area' + (i+1)),
   areaData = areasData[i];
 // 繪制雷達圖區(qū)域下的多邊形
 area.append('polygon')
   .attr('points', areaData.polygon)
   .attr('stroke', function(d, index) {
    return getColor(i);
   })
   .attr('fill', function(d, index) {
    return getColor(i);
   });
 // 繪制雷達圖區(qū)域下的點 
 var circles = area.append('g')
   .classed('circles', true);
 circles.selectAll('circle')
   .data(areaData.points)
   .enter()
   .append('circle')
   .attr('cx', function(d) {
    return d.x;
   })
   .attr('cy', function(d) {
    return d.y;
   })
   .attr('r', 3)
   .attr('stroke', function(d, index) {
    return getColor(i);
   }); 
}

這里為了體驗層次關(guān)系,我用areas包含住所有雷達圖區(qū)域,又在里面用一個g分組表示一個雷達圖區(qū)域,在雷達圖區(qū)域里包含組成該區(qū)域的多邊形和圓點。這里因為我們數(shù)據(jù)用一個雷達圖區(qū)域就表示了,所以這個for循環(huán)只會循環(huán)一次。給繪制好的區(qū)域加上樣式。

.areas polygon {
 fill-opacity: 0.5;
 stroke-width: 3;
}
.areas circle {
 fill: white;
 stroke-width: 3;
}

于是得到了下圖這個樣子的圖表。

計算文字標簽坐標并添加

為了讓上面的圖表更完整一些,我們給它加上文字標簽。文字標簽標注在網(wǎng)軸的外圍,所以可以以計算網(wǎng)軸多邊形點坐標的同樣的原理計算文字標簽的坐標。

// 計算文字標簽坐標
var textPoints = [];
var textRadius = radius + 20;
for(var i=0;i<total;i++) {
 var x = textRadius * Math.sin(i * onePiece),
   y = textRadius * Math.cos(i * onePiece);
 textPoints.push({
  x: x,
  y: y
 });
} 

計算好坐標以后再添加到畫布中。

// 繪制文字標簽
var texts = main.append('g')
  .classed('texts', true);
texts.selectAll('text')
  .data(textPoints)
  .enter()
  .append('text')
  .attr('x', function(d) {
   return d.x;
  })
  .attr('y', function(d) {
   return d.y;
  })
  .text(function(d,i) {
   return data.fieldNames[i];
  }); 

最后的樣子是這樣的。

總結(jié)

以上就是利用D3.js實現(xiàn)雷達的全部內(nèi)容,希望這篇文章對大家的學(xué)習(xí)和工作能有所幫助。如果有疑問大家可以留言交流,感興趣的朋友們請大家繼續(xù)關(guān)注腳本之家。

相關(guān)文章

  • BootstrapValidator實現(xiàn)注冊校驗和登錄錯誤提示效果

    BootstrapValidator實現(xiàn)注冊校驗和登錄錯誤提示效果

    這篇文章主要為大家詳細介紹了Bootstrap Validator實現(xiàn)注冊校驗和登錄錯誤提示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 類似CSDN圖片切換效果腳本

    類似CSDN圖片切換效果腳本

    原來的腳本當只有一張圖片時會彈出JavaScript腳本錯誤,特此將自己修改完的版本貼出。
    2009-09-09
  • JS面向?qū)ο蟮某绦蛟O(shè)計相關(guān)知識小結(jié)

    JS面向?qū)ο蟮某绦蛟O(shè)計相關(guān)知識小結(jié)

    這篇文章主要介紹了JS面向?qū)ο蟮某绦蛟O(shè)計,現(xiàn)在很多代碼都是基于面向?qū)ο髮崿F(xiàn),需要的朋友可以參考下
    2018-05-05
  • 打字效果動畫的4種實現(xiàn)方法(超簡單)

    打字效果動畫的4種實現(xiàn)方法(超簡單)

    下面小編就為大家?guī)硪黄蜃中Ч麆赢嫷?種實現(xiàn)方法(超簡單)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • ES5新增數(shù)組的實現(xiàn)方法

    ES5新增數(shù)組的實現(xiàn)方法

    這篇文章主要介紹了ES5新增數(shù)組的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 使用pdf-lib.js實現(xiàn)pdf添加自定義水印功能

    使用pdf-lib.js實現(xiàn)pdf添加自定義水印功能

    pdf-lib是一個強大的JavaScript庫,允許在任何JavaScript環(huán)境中創(chuàng)建和修改PDF文檔,下面就跟隨小編一起來學(xué)習(xí)一下如何使用pdf-lib實現(xiàn)pdf添加自定義水印功能吧
    2024-11-11
  • 使用Vue3實現(xiàn)一個Upload組件的示例代碼

    使用Vue3實現(xiàn)一個Upload組件的示例代碼

    這篇文章主要介紹了使用Vue3實現(xiàn)一個Upload組件的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • JavaScript實現(xiàn)通訊錄功能

    JavaScript實現(xiàn)通訊錄功能

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)通訊錄功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • JavaScript建立一個語法高亮輸入框?qū)崿F(xiàn)思路

    JavaScript建立一個語法高亮輸入框?qū)崿F(xiàn)思路

    通常網(wǎng)站自帶的textarea編輯器不能滿足我們的需求比如高亮顯示代碼等,在這篇文章中,我將使用JavaScript庫ACE來創(chuàng)建一個輸入框效果,該腳本允許開發(fā)人員創(chuàng)建支持語法高亮的輸入框,感興趣的你可不要錯過了哈
    2013-02-02
  • js下將字符串當函數(shù)執(zhí)行的方法

    js下將字符串當函數(shù)執(zhí)行的方法

    js下將字符串當函數(shù)執(zhí)行的方法,需要的朋友可以參考下。
    2011-07-07

最新評論

鹿泉市| 花莲市| 长乐市| 台南县| 米脂县| 东安县| 剑川县| 庆元县| 申扎县| 工布江达县| 宝兴县| 潞西市| 文山县| 黔南| 涿鹿县| 武邑县| 平武县| 章丘市| 航空| 如东县| 巴东县| 永修县| 合山市| 浦江县| 阳泉市| 温泉县| 色达县| 常宁市| 孙吴县| 慈利县| 滕州市| 长垣县| 如皋市| 金秀| 永登县| 望奎县| 洛隆县| 乌恰县| 济宁市| 凉城县| 德钦县|