كيف يمكن عمل المخططات الدائرية باستخدام D3.js

1 min read

D3.js هي مكتبة خاصة بـJavaScript، يتم استخدامها على نطاق واسع في تمثيل البيانات باستخدام HTML، وSVG، وCSS، ويكون العمل من خلالها ضروريًّا في بعض الأحيان، وبخاصة عندما تكون بحاجة إلى تنفيذ تصميمات معتادة ولكن بشكل مميز.

تسمح لك D3.js بالتعامل مع HTML، إلا أن الأمر لا يتوقف عند هذا الحد، إذ إنها أيضًا تستخدم مع SVG حتى يتسنى إظهار أي تغيرات في البيانات على العناصر المرتبطة بها.

هناك العديد من أشكال SVG، مثل الدوائر والمستطيلات والمسارات والنصوص، وتعتبر هذه الأشكال بمثابة كتل بناء التصميمات. على سبيل المثال: يتكون مخطط الأعمدة من عدد من المستطيلات، ويتكون المخطط المبعثر من دوائر مبعثرة في أجزاء مختلفة من المساحة المتاحة لتنفيذ التصميم.

فيما يلي، سنوضح كيف يتم تنفيذ مخططات دائرية، ومخططات دائرية مفرغة تشبه المخططات الدائرية جدًّا مع اختلاف واحد فقط هو أن المنتصف فارغ، عن طريق SVG. SVG هو شكل متقدم مقارنة بالدوائر والمستطيلات، نظرًا إلى أنه يعتمد على أوامر تستخدم في عمل الشكل التقديري الذي نريده.

مثلما يظهر في الشكل السابق، فإن مخطط الدائرة المفرغة من المنتصف يتشكل من مسارات متعددة تشبه الأقواس بلون مختلف. لحسن الحظ، تقدم d3.js معادلات تساعد على رسم الأقواس.

يتم رسم الأقواس باستخدام أربعة مقاييس رئيسية، وهي زاوية البدء وزاوية النهاية والقطر الداخلي والقطر الخارجي، وتكثر الزوايا الموجود في القطر عنها في الدرجات، وعليه فإن دائرة كاملة تعادل ٢ π بدلًا من ٣٦٠ درجة،

من أجل رسم قوس، دعنا نبدأ بإضافة علامة SVG في مستندات html الخاصة بنا:

<svg id=”svg_donut” width=”600″ height=”400″></svg>

الآن، من أجل رسم قوس يبدأ من الصفر، يمتد إلى ثلاثة أرباع ويصل إلى دوران كامل، بقطر داخلي ٥٠ بيكسل وقطر خارجي ١٠٠ بيكسل، نحتاج إلى كتابة كود JavaScript التالي:

var vis = d3.select(“#svg_donut”);
var arc = d3.svg.arc()
.innerRadius(50)
.outerRadius(100)
.startAngle(0)
.endAngle(1.5*Math.PI);

vis.append(“path”)
.attr(“d”, arc)
.attr(“transform”, “translate(300,200)”);

 

في الكود السابق، نختار أولًا عنصر SVG الخاص بنا باستخدام svg_donut#، ثم نحفظ ما اخترنا إلى متغير اسمه vis.

d3.svg .arc() is the d3.js هي المعادلة التي نستخدمها بدلًا من أوامر SVG، ونضيف الأربعة مقاييس السابق ذكرهم ونحفظ النتيجة في متغير اسمه arc.

الآن، من أجل عمل مسار وإلحاقه بعنصر SVG، نستخدم

vis.append(“path”)

ثم نضيف arc إلى صفته d، ويمكن أن نفكر في صفة d باعتبارها بديلًا عن أمر SVG.

التعامل مع زوايا نصف قطرية أمر ممل، ولحسن الحظ، فإن d3.js تقدم معادلات أخرى تسمى مقاييس، تساعد بشكل أساسي على تنفيذ مقياس واحد مقارنة بآخر. على سبيل المثال: بدلًا من الحصول على دوران كلي يبدأ من ٠ ويمتد إلى ٢ π، فإننا نريده أن يكون من ٠ إلى ١٠٠، وعليه فإن كل ما نحتاج إليه هو كتابة الكود التالي:

var myScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);

وهكذا: myScale(0) = 0, myScale(100) = 2 π, myScale(75) = 1.5 π، وعليه، فإن الكود المكتوب أعلاه يمكن كتابته كما يلي:

var vis = d3.select(“#svg_donut”);
var myScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
var arc = d3.svg.arc()
.innerRadius(50)
.outerRadius(100)
.startAngle(myScale(0))
.endAngle(myScale(75));

vis.append(“path”)
.attr(“d”, arc)
.attr(“transform”, “translate(300,200)”);

 

حتى الآن، تعلمنا كيف نصنع قوسًا.

المخطط الدائري ومخطط الدائرة المفرغة من المنتصف يتم تنفيذهما من خلال أقواس متعددة، وتمثل زاوية كل منهم قيمة عنصر واحد مما لدينا من بيانات مقارنة بقيم البيانات الكلية، بكلمات أخرى: إذا كان لدينا ٣ أنواع هواتف محمولة (أ) و(ب) و(ج)، ويمتلك النوع (أ) ٥٠٪ من حصة السوق، بينما يمتلك كل من (ب) و(ج) ٢٥٪.

يمكننا الآن تمثيلهم في المخطط كثلاث أقواس بزوايا π، وπ/2 وπ/2 تباعًا، ومن أجل تطبيق هذا باستخدام d3.js، فإننا نكون بحاجة إلى مصفوفة من البيانات نربطها بالأقواس.

var cScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);

data = [[0,50,”#AA8888″], [50,75,”#88BB88″], [75,100,”#8888CC”]]

var vis = d3.select(“#svg_donut”);

var arc = d3.svg.arc()
.innerRadius(50)
.outerRadius(100)
.startAngle(function(d){return cScale(d[0]);})
.endAngle(function(d){return cScale(d[1]);});

vis.selectAll(“path”)
.data(data)
.enter()
.append(“path”)
.attr(“d”, arc)
.style(“fill”, function(d){return d[2];})
.attr(“transform”, “translate(300,200)”);

تتكون مصفوفة البيانات من ٣ عناصر بيانات، كل منهم يتم التعامل معه باعتباره مصفوفة من ٣ قيم، ويبدأ العنصر الأول من الصفر ويمتد إلى ٥٠٪ من مخطط الدائرة المفرغ بلون خلفية #AA8888، وينبغي أن تأتي زاوية البدء للعنصر الثاني بعد الأولى فورًا، أي ٥٠٪ وتصل إلى ٧٥٪ بلون خلفية #88BB88. بشكل مشابه، ينتقل العنصر الثالث من ٧٥٪ إلى ١٠٠٪، بلون خلفية #8888CC.


من أجل إضافة أقواس بشكل ديناميكي استنادًا إلى ما لديك من بيانات، نختار المسار ونربط البيانات بالاختيارات ثم نضيف مسارات جديدة وفقًا للتالي:
vis.selectAll(“path”).data(data).enter().

نحصل على زاوية البدء وزاوية النهاية من عناصر البيانات مثلما تظهر باللون الأحمر.

تظهر الدائرة المفرغة كما يلي:

يمكن أن يستخدم نفس الكود بالضبط لعمل مخطط دائري، الاختلاف الوحيد هو أن القيمة المعطاة لـinnerRadius() ينبغي أن يتم ضبطها عند الصفر، يظهر مخطط الدائرة كالتالي: