首頁 web前端 js教程 在D3.js中如何實現動態進度條

在D3.js中如何實現動態進度條

Jun 04, 2018 pm 03:38 PM
javascript 進度

D3是一個被資料驅動的文檔。這篇文章主要介紹了基於D3.js 繪製動態進度條的方法,需要的朋友可以參考下

D3 是什麼

D3 的全名是(Data-Driven Documents),顧名思義可以知道是一個被資料驅動的文檔。聽名字有點抽象,說簡單一點,其實就是一個 JavaScript 的函數庫,使用它主要是用來做資料視覺化的。如果你不知道什麼是 JavaScript ,請先學習 JavaScript,推薦阮一峰老師的教學。

JavaScript 檔案的字尾名通常為 .js,故 D3 也常用 D3.js 稱呼。 D3 提供了各種簡單易用的函數,大大簡化了 JavaScript 操作資料的難度。由於它本質上是JavaScript ,用JavaScript 也是可以實現所有功能的,但它能大大減少你的工作量,尤其是在資料視覺化方面,D3 已經將產生可視化的複雜步驟精簡到了幾個簡單的函數,你只需要輸入幾個簡單的數據,就能夠轉換為各種絢麗的圖形。有過 JavaScript 基礎的朋友一定很容易理解它。

在網站頁面載入以及表單提交時,常使用進度條表達載入程序來優化使用者體驗,常見的進度條有矩形進度條和圓形進度條,如下圖所示:

 

我們經常使用svg或canvas來實現動態圖形的繪製,但繪製過程相對較繁瑣。對於直觀漂亮的進度條,社區也有提供成熟的方案例如highcharts/ECharts等等,但基於配置的開發方式終究無法實現100%的自訂繪製。本文將帶你使用D3.js從零一步一步實現動態進度條,並分享程式碼邏輯原理。

基礎需求

  • #了解svg如何繪製基礎圖形

  • 了解D3.js v4版本

  • 了解如何使用D3.js (v4)繪製svg的基礎圖形

##繪製圓形進度條

對於一個圓形進度條,我們先對其進行任務拆分:

  • 繪製嵌套圓弧

  • 圓心處的即時資料展示

  • #展現動畫

  • ##設計
1.繪製巢狀圓弧

對於圓形,svg提供現成的circle 標籤供使用,但是其劣勢在於,對於圓形進度條使用circle 可以滿足,但對圖形進一步擴展時例如繪製半圓, circle 的處理就棘手了。 D3.js提供arc 相關API對圓形的繪製方法進行了封裝:

var arc = d3.arc()
   .innerRadius(180)
   .outerRadius(240)
   //.startAngle(0)
   //.endAngle(Math.PI)
arc(); // "M0,-100A100,100,0,0,1,100,0L0,0Z"
登入後複製

上述程式碼實作了兩個巢狀圓的繪製邏輯, d3.arc() 傳回一個圓弧建構函數,並透過鍊式呼叫設定內圓與外圓的半徑大小,起始角度與結束角度。執行 arc() 建構函式即可取得用於綁定在 上的路徑資料。完整程式碼如下:

<!--html-->
<svg width="960" height="500"></svg>
<script>
 var arcGenerator = d3.arc().innerRadius(80).outerRadius(100).startAngle(0);
 var picture = d3.select(&#39;svg&#39;).append(&#39;g&#39;).attr(&#39;transform&#39;,&#39;translate(480,250)&#39;);
</script>
登入後複製

上述程式碼實作了2個步驟:

1.產生0度作為起點的圓弧建構器arcGenerator

2.設定transform 圖形偏移量,讓圖形在畫布中央

目前畫布上還沒有任何元素,接下來我們實際圖形的繪製。

var backGround = picture.append("path")
  .datum({endAngle: 2 * Math.PI})
  .style("fill", "#FDF5E6")
  .attr("d", arcGenerator);
登入後複製

我們將畫布picture 新增 元素,依據endAngle() 特性,使用datum() 方法將{endAngle:Math.PI} 也就是終點角度2π 綁定到 元素上,並將圓弧構造器賦值給path 路徑d 。這樣就產生了指定背景顏色的圓弧,實際圖形如下:

第一個圓弧畫好了,那麼依據svg的層級關係z-index ,所謂的進度條其實就是覆蓋在第一層圓弧之上的第二層圓弧。同理可得:

var upperGround = picture.append(&#39;path&#39;)
  .datum({endAngle:Math.PI / 2})
  .style(&#39;fill&#39;,&#39;#FFC125&#39;)
  .attr(&#39;d&#39;,arcGenerator)
登入後複製

程式碼執行後可得:

 

2.圓心處的即時資料展示

第一部分我們已經實作了基於兩個path 的巢狀圓。第二部分我們來實現圓心處的即時數據展示。在進度條進行載入時,我們在圓心處新增資料來表達目前的載入進度,使用 標籤做展示即可:

var dataText = g.append(&#39;text&#39;)
  .text(12)
  .attr(&#39;text-anchor&#39;,&#39;middle&#39;)
  .attr(&#39;dominant-baseline&#39;,&#39;middle&#39;)
  .attr(&#39;font-size&#39;,&#39;38px&#39;)
登入後複製

#暫時設定資料為12,設定水平置中垂直置中,效果如下圖:

 

3.展現動畫

通过1,2两部分内容我们已经知道了:

  • 绘制进度条的实质是改变上层弧的角度

  • 当弧度是 2π 时为整圆,当弧度是 π 时为半圆

  • 圆形中的数据即为当前弧度相对 2π 的百分比

综上我们只要改变弧度值和数值同时设定改变过程所需时长即可实现所谓"动画"。在ECharts提供的官方实例中,通过 setInterval 来实现每隔固定一段时间进行数据更新,其实在D3.js中同样提供了类似方法来实现类似 setInterval 的功能:

d3.interval(function(){
 foreground.transition().duration(750).attrTween(&#39;d&#39;,function(d){
  var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
  return function(t){
   d.endAngle = compute(t);
   return arcGenerator(d);
  }
  
 })
},1000)
登入後複製

对这段代码进行拆解:

  • d3.interval() 方法提供了 setInterval() 的功能

  • selection.transition.duration() 设置了当前DOM属性过渡变化为指定DOM属性的过程所需时间,毫秒为单位

  • transation.attrTween 为插值功能API,那么何谓插值?

概括来说,在给定的离散数据中补插函数,可以使这条连续函数通过全部数据点。举个例子,给定一个p,想实现其背景颜色的从左边红(red)到右边绿(green)的线性渐变,每一区域的色值该如何计算呢?只需:

var compute = d3.interpolate(d3.rgb(255,0,0),d3.rgb(0,255,0));
登入後複製

compute 即为插值函数,参数范围为[0,1],只要你输入该范围内的数字,那么 compute 函数将返回对应的颜色值。这样的插值有什么用呢?可看下图:

假设上图的p长度width为100,那么将[0,100]依比例关系转化为[0,10]的范围数据并输入 compute 函数中,即可得到某一区域对应的颜色。当然,对于线性面积的处理我们不应该使用离散数据作为输入和输出,所以D3.js提供更方便的线性渐变API d3.linear 等,这里就不展开描述了。

言归正传,代码 d3.interpolate(d.endAngle,Math.random() * Math.PI * 2); 实现了如下插值范围:

["当前角度值","随机角度值"] //表达区间而非数组

而后返回一个参数为 t 的函数,那么该函数的作用是什么呢?

t 参数与 d 类似,是D3.js内部实现的插值,其范围为[0,1]。 t 参数根据设置的 duration() 时长自动计算在[0,1]内合适的插值数量,并返回插值结果,实现线性平稳的过渡动画效果。

完成滚动条的动画加载效果,我们接下来写圆心实时数据的变化逻辑,只要实现简单的赋值即可,完整代码如下:

d3.interval(function(){
  foreground.transition().duration(750).attrTween(&#39;d&#39;,function(d){
   var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
   return function(t){
    d.endAngle = compute(t);
    var data = d.endAngle / Math.PI / 2 * 100;
    //设置数值
    d3.select(&#39;text&#39;).text(data.toFixed(0) + &#39;%&#39;);
    //将新参数传入,生成新的圆弧构造器
    return arcGenerator(d);
   }
  })
 },2000)
登入後複製

最终效果如下:

4.美化

1,2,3部分我们实现了最基本的进度条样式和功能,但样式看起来还是很单调的,我们接下来我们对进度条进行线性渐变处理。我们使用D3.js提供的线性插值API:

var colorLinear = d3.scaleLinear().domain([0,100]).range(["#EEE685","#EE3B3B"]);
登入後複製

colorLinear 同样是一个插值函数,我们输入[0,100]区间中的数值,就会返回对应["#EEE685","#EE3B3B"]区间内的颜色值。比如当进度条显示进度为"80%"时:

var color = colorLinear(80);
//color即为"80%"对应的色值
登入後複製

实现了颜色取值后,我们只需在进度条变化时,将原有颜色改变即可:

d3.interval(function(){
  foreground.transition().duration(750).attrTween(&#39;d&#39;,function(d){
   var compute = d3.interpolate(d.endAngle,Math.random() * Math.PI * 2);
   return function(t){
    d.endAngle = compute(t);
    var data = d.endAngle / Math.PI / 2 * 100;
    //设置数值
    d3.select(&#39;text&#39;).text(data.toFixed(0) + &#39;%&#39;);
    //将新参数传入,生成新的圆弧构造器
    return arcGenerator(d);
   }
  })
  .styleTween(&#39;fill&#39;,function(d){
   return function(t){
    var data = d.endAngle / Math.PI / 2 * 100;
    //返回数值对应的色值
    return colorLinear(data);
   }
  })
 },2000)
登入後複製

styleTween 与 attrTween 类似,是实现改变样式的插值函数。采用链式调用的形式同时对进度条数值和颜色的设置即可。最终实现的效果如下:

综上我们实现了在不同数值下颜色变化的圆形进度条,可常用于告警,提醒等业务场景。

绘制矩形进度条

矩形进度条相比圆形进度条简单了很多,同样基于插值原理,平滑改变矩形的长度即可。直接上代码:

<head>
 <style>
  #slider {
   height: 20px;
   width: 20px;
   background: #2394F5;
   margin: 15px;
  }
 </style>
</head>
<body>
 <p id=&#39;slider&#39;></p>
 <script>
  d3.interval(function(){
   d3.select("#slider").transition()
    .duration(1000)
    .attrTween("width", function() {
     var i = d3.interpolate(20, 400);
     var ci = d3.interpolate(&#39;#2394F5&#39;, &#39;#BDF436&#39;);
     var that = this;
     return function(t) {
      that.style.width = i(t) + &#39;px&#39;;
      that.style.background = ci(t);
     };
    });
  },1500)
 </script>
</body>
登入後複製

实现的效果如下:

 

总结

基於D3.js繪製進度條的關鍵點在於插值,從而正確地使圖形平滑過渡。如果一定要使用svg或純css實現矩形和圓形的進度條當然也是可行的,但對於路徑和動畫的處理,以及css的書寫要求都複雜了不少。我們觀察到使用D3.js繪製上述兩種進度條的邏輯程式碼幾乎完全使用js實現,同時程式碼量可以控制在20行左右並可封裝復用,已經非常精煉了,在自訂圖表開發上非常有優勢。

對於進度條的衍生版儀錶板圖表,相比基礎進度條增加了刻度描述和指針計算,但萬變不離其宗,只要掌握插值原理和使用,處理類似圖表都將得心應手。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

基於express中路由規則及取得請求參數的方法

##js提取中文拼音首字母的封裝工具類別_javascript技巧

詳解vuex的簡單使用

################# ####

以上是在D3.js中如何實現動態進度條的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles