Heim > Artikel > Web-Frontend > So implementieren Sie einen dynamischen Fortschrittsbalken in D3.js
D3 ist ein datengesteuertes Dokument. In diesem Artikel wird hauptsächlich die Methode zum Zeichnen dynamischer Fortschrittsbalken basierend auf D3.js vorgestellt. Freunde, die sie benötigen, können sich auf
Was ist D3
Wir verwenden oft SVG oder Canvas, um dynamische Grafiken zu zeichnen, aber der Zeichenprozess ist relativ umständlich. Für intuitive und schöne Fortschrittsbalken bietet die Community auch ausgereifte Lösungen wie Highcharts/ECharts usw. an, aber die konfigurationsbasierte Entwicklungsmethode kann keine 100 % individuelle Zeichnung erreichen. In diesem Artikel erfahren Sie Schritt für Schritt, wie Sie mithilfe von D3.js einen dynamischen Fortschrittsbalken von Grund auf implementieren und die Prinzipien der Codelogik teilen.
Grundlegende Anforderungen
Zeichnen Sie einen kreisförmigen Fortschrittsbalken
Für einen kreisförmigen Fortschrittsbalken teilen wir zunächst die Aufgaben auf:1. Verschachtelte Bögen zeichnen
Für Kreise stellt SVG vorgefertigte Kreis-Tags zur Verfügung, aber das ist der Nachteil für Kreise Der Fortschrittsbalken kann durch die Verwendung von Kreisen erfüllt werden, aber wenn die Grafik weiter erweitert wird, beispielsweise durch das Zeichnen eines Halbkreises, wird die Verarbeitung von Kreisen schwierig. D3.js bietet eine bogenbezogene API zur Kapselung der Kreiszeichnungsmethode:var arc = d3.arc() .innerRadius(180) .outerRadius(240) //.startAngle(0) //.endAngle(Math.PI) arc(); // "M0,-100A100,100,0,0,1,100,0L0,0Z"Der obige Code implementiert die Zeichenlogik von zwei verschachtelten Kreisen d3.arc(). Gibt einen Bogenkonstruktor zurück und legt den Radius des inneren und äußeren Kreises, den Startwinkel und den Endwinkel durch Kettenaufrufe fest. Führen Sie den arc()-Konstruktor aus, um Pfaddaten für die Bindung an 98953a78f52873edae60a617ec082494 zu erhalten. Der vollständige Code lautet wie folgt:
<!--html--> <svg width="960" height="500"></svg> <script> var arcGenerator = d3.arc().innerRadius(80).outerRadius(100).startAngle(0); var picture = d3.select('svg').append('g').attr('transform','translate(480,250)'); </script>Der obige Code implementiert 2 Schritte: 1 Generieren Sie einen Bogenkonstruktor mit 0 Grad als Startpunkt arcGenerator2. Stellen Sie den Versatz der Transformationsgrafik so ein, dass sich die Grafik in der Mitte der Leinwand befindet. Als nächstes zeichnen wir die tatsächliche Grafik.
var backGround = picture.append("path") .datum({endAngle: 2 * Math.PI}) .style("fill", "#FDF5E6") .attr("d", arcGenerator);Wir fügen dem Canvas-Bild das 98953a78f52873edae60a617ec082494-Element hinzu, verwenden Sie die datum()-Methode, um {endAngle: Math.PI} Das heißt, der Endpunktwinkel 2π ist an das 98953a78f52873edae60a617ec082494-Element gebunden und der Bogenkonstruktor ist dem Pfadpfad d zugewiesen. Dadurch wird ein Bogen mit einer bestimmten Hintergrundfarbe generiert. Die eigentliche Grafik sieht wie folgt aus: Der erste Bogen wird gezeichnet, dann entsprechend der hierarchischen Beziehung Z-Index von SVG, Der sogenannte Fortschrittsbalken ist eigentlich die zweite Bogenschicht, die die erste Bogenschicht bedeckt. Auf die gleiche Weise erhalten Sie:
var upperGround = picture.append('path') .datum({endAngle:Math.PI / 2}) .style('fill','#FFC125') .attr('d',arcGenerator)Nachdem Sie den Code ausgeführt haben, erhalten Sie:
2. Echtzeit-Datenanzeige im Mittelpunkt des Kreises
Im ersten Teil haben wir einen verschachtelten Kreis basierend auf zwei Pfaden implementiert. Im zweiten Teil implementieren wir die Echtzeit-Datenanzeige in der Mitte des Kreises. Wenn der Fortschrittsbalken geladen wird, fügen wir Daten in der Mitte des Kreises hinzu, um den aktuellen Ladefortschritt auszudrücken, und verwenden das Tagvar dataText = g.append('text') .text(12) .attr('text-anchor','middle') .attr('dominant-baseline','middle') .attr('font-size','38px')
Stellen Sie die Daten vorübergehend auf 12 ein und stellen Sie die horizontale und vertikale Zentrierung ein. Der Effekt ist wie folgt:
3. Animation anzeigen
通过1,2两部分内容我们已经知道了:
绘制进度条的实质是改变上层弧的角度
当弧度是 2π 时为整圆,当弧度是 π 时为半圆
圆形中的数据即为当前弧度相对 2π 的百分比
综上我们只要改变弧度值和数值同时设定改变过程所需时长即可实现所谓"动画"。在ECharts提供的官方实例中,通过 setInterval 来实现每隔固定一段时间进行数据更新,其实在D3.js中同样提供了类似方法来实现类似 setInterval 的功能:
d3.interval(function(){ foreground.transition().duration(750).attrTween('d',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('d',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('text').text(data.toFixed(0) + '%'); //将新参数传入,生成新的圆弧构造器 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('d',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('text').text(data.toFixed(0) + '%'); //将新参数传入,生成新的圆弧构造器 return arcGenerator(d); } }) .styleTween('fill',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='slider'></p> <script> d3.interval(function(){ d3.select("#slider").transition() .duration(1000) .attrTween("width", function() { var i = d3.interpolate(20, 400); var ci = d3.interpolate('#2394F5', '#BDF436'); var that = this; return function(t) { that.style.width = i(t) + 'px'; that.style.background = ci(t); }; }); },1500) </script> </body>
实现的效果如下:
总结
Der entscheidende Punkt beim Zeichnen eines Fortschrittsbalkens basierend auf D3.js ist die Interpolation, um den Übergang von Grafiken korrekt zu glätten. Wenn Sie SVG oder reines CSS verwenden müssen, um rechteckige und kreisförmige Fortschrittsbalken zu implementieren, ist dies natürlich auch möglich, aber die Verarbeitung von Pfaden und Animationen sowie die Schreibanforderungen von CSS sind viel komplizierter. Wir haben festgestellt, dass der Logikcode zum Zeichnen der beiden oben genannten Fortschrittsbalken fast vollständig mit js implementiert ist. Gleichzeitig kann die Codemenge auf etwa 20 Zeilen gesteuert und gekapselt und wiederverwendet werden bereits sehr verfeinert und ist bei der Entwicklung benutzerdefinierter Diagramme sehr nützlich.
Für die abgeleitete Version des Dashboard-Diagramms des Fortschrittsbalkens werden im Vergleich zum Basis-Fortschrittsbalken eine Skalenbeschreibung und eine Zeigerberechnung hinzugefügt, aber sie bleiben gleich, solange Sie das Prinzip und die Verwendung beherrschen Interpolation können Sie problemlos mit ähnlichen Diagrammen umgehen.
Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.
Verwandte Artikel:
Methoden zum Abrufen von Anforderungsparametern und Routingregeln basierend auf Express
Detaillierte Erklärung der einfachen Verwendung von Vuex
Das obige ist der detaillierte Inhalt vonSo implementieren Sie einen dynamischen Fortschrittsbalken in D3.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!