ایجاد نمودار میله‌ای افقی با کتابخانه D3

در این مقاله، قصد داریم نحوه ایجاد یک نمودار میله‌ای افقی را با استفاده از کتابخانه D3.js نشان دهیم. این نمودار، جمعیت استان‌های ایران را نمایش می‌دهد. مراحل زیر، کد کامل و توضیحات مربوط به هر قسمت را شامل می‌شود. پایه کدها بر گرفته از این آموزش می‌باشد.

 

کد کامل:

 

var margin = {top: 20, right: 30, bottom: 40, left: 90};
var width = 700 - margin.left - margin.right;
var height = 600 - margin.top - margin.bottom;
 
var svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
 
var x = d3.scaleLinear()
.domain([0, 14000000])
.range([ 0, width]);
svg.append("g")
.attr("transform", "translate(100," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
 
var y = d3.scaleBand()
.range([0, height])
.domain(iranPopulation.map(function(d) { return d.province; }))
.padding(.2);
svg.append("g")
.call(d3.axisLeft(y))
.attr("transform", "translate(100,0)")
 
svg.selectAll("myRect")
.data(iranPopulation)
.enter()
.append("rect")
.attr("x", x(0) )
.attr("y", function(d) { return y(d.province); })
.attr("width", function(d) { return x(d.population); })
.attr("height", y.bandwidth() )
.attr("fill", "#69b3a2")
.attr("transform", "translate(102,0)")
.append("title")
.text(d => d.population.toLocaleString())
 
svg.node()

 

خروجی:

 

 

تعریف حاشیه‌ها و ابعاد SVG

 

ابتدا، حاشیه‌ها و ابعاد نمودار را تعریف می‌کنیم. حاشیه‌ها شامل فاصله‌های بالا، راست، پایین و چپ می‌شود که به منظور ایجاد فضای کافی برای محورها و عناوین استفاده می‌شود.

 

var margin = {top: 20, right: 30, bottom: 40, left: 90};
var width = 700 - margin.left - margin.right;
var height = 600 - margin.top - margin.bottom;

 

ایجاد عنصر SVG

 

عنصر SVG اصلی را با استفاده از D3.js ایجاد کرده و ابعاد آن را مشخص می‌کنیم.

 

var svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)

 

ایجاد مقیاس محور X

 

مقیاس خطی محور X را براساس جمعیت استان‌ها تعریف می‌کنیم. دامنه مقیاس از 0 تا 14 میلیون نفر تنظیم شده است.

 

var x = d3.scaleLinear()
.domain([0, 14000000])
.range([ 0, width]);
 
svg.append("g")
.attr("transform", "translate(100," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");

 

  • var x = d3.scaleLinear() در اینجا، مقیاس خطی (scaleLinear) را برای محور X تعریف می‌کنیم. این مقیاس مشخص می‌کند که چگونه مقادیر داده‌ها به موقعیت‌های پیکسلی در نمودار تبدیل شوند.
  • domain([0, 14000000]): دامنه ورودی مقیاس را تنظیم می‌کند. در اینجا، دامنه ورودی از 0 تا 14 میلیون نفر جمعیت تنظیم شده است. این مقدار باید به گونه‌ای تنظیم شود که بیشترین جمعیت در داده‌ها را پوشش دهد.
  • range([0, width]): دامنه خروجی مقیاس را تنظیم می‌کند. در اینجا، دامنه خروجی از 0 تا عرض نمودار تنظیم شده است. این بدان معناست که مقدار 0 در جمعیت به پیکسل 0 در عرض نمودار و مقدار 14 میلیون نفر به عرض کامل نمودار ترجمه می‌شود.
  • svg.append("g"): یک عنصر g (گروه) جدید به SVG اضافه می‌کند. گروه‌ها به عنوان کانتینرهایی برای عناصر دیگر SVG عمل می‌کنند و به شما اجازه می‌دهند تا چندین عنصر را با هم مدیریت کنید.

  • attr("transform", "translate(100," + height + ")"): گروه را به موقعیت مناسب در SVG منتقل می‌کند. اینجا محور X به سمت پایین نمودار منتقل شده است. translate(100, height) به این معنی است که گروه به اندازه 100 پیکسل به سمت راست و به اندازه ارتفاع نمودار به سمت پایین منتقل شده است. این فاصله 100 پیکسلی به منظور جا دادن محور Y در سمت چپ نمودار در نظر گرفته شده است.

  • call(d3.axisBottom(x)): محور X را به گروه اضافه می‌کند و از مقیاس خطی x که قبلاً تعریف شده استفاده می‌کند. d3.axisBottom(x) یک محور افقی در پایین نمودار با استفاده از مقیاس x ایجاد می‌کند.

  • selectAll("text"): تمام عناصر متنی داخل محور X را انتخاب می‌کند.

  • attr("transform", "translate(-10,0)rotate(-45)"): موقعیت و زاویه متن‌های محور X را تنظیم می‌کند. translate(-10,0) متن را به اندازه 10 پیکسل به سمت چپ منتقل می‌کند تا از تداخل با میله‌های نمودار جلوگیری کند. rotate(-45) متن‌ها را به اندازه 45 درجه در خلاف جهت ساعت می‌چرخاند تا خواندن آن‌ها آسان‌تر شود.

  • style("text-anchor", "end"): تنظیم می‌کند که انتهای متن‌ها به موقعیت آن‌ها چسبیده باشد، به این معنی که متن‌ها در انتهای سمت راست خود قرار می‌گیرند. این تنظیم کمک می‌کند تا متن‌ها به خوبی در محور X جای بگیرند و با چرخش 45 درجه‌ای هماهنگ شوند.

 

ایجاد مقیاس محور Y

 

مقیاس محور Y را براساس نام استان‌ها تنظیم می‌کنیم. از روش scaleBand برای ایجاد فاصله‌های برابر بین میله‌ها استفاده می‌شود.

 

var y = d3.scaleBand()
.range([0, height])
.domain(iranPopulation.map(function(d) { return d.province; }))
.padding(.2);
 
svg.append("g")
.call(d3.axisLeft(y))
.attr("transform", "translate(100,0)");

 

  • var y = d3.scaleBand(): یک مقیاس باندی (band scale) ایجاد می‌کند. مقیاس باندی برای مقادیر دسته‌ای (categorical values) مانند نام استان‌ها استفاده می‌شود و فضا را به نوارهای باندی تقسیم می‌کند.
  • range([0, height]): دامنه خروجی مقیاس را تنظیم می‌کند. در اینجا دامنه خروجی از 0 تا ارتفاع نمودار تنظیم شده است. این بدان معناست که مقادیر دسته‌ای از بالا به پایین نمودار ترسیم می‌شوند.
  • domain(iranPopulation.map(function(d) { return d.province; })): دامنه ورودی مقیاس را تنظیم می‌کند. در اینجا دامنه ورودی از مقادیر دسته‌ای که نام استان‌ها هستند، تشکیل شده است. iranPopulation.map(function(d) { return d.province; }) یک آرایه از نام استان‌ها را از داده‌ها استخراج می‌کند.
  • padding(0.2): فاصله بین نوارهای باندی را تنظیم می‌کند. این مقدار باعث می‌شود که نوارها کمی فاصله داشته باشند و از چسبیدن به یکدیگر جلوگیری می‌کند.
  • svg.append("g"): یک عنصر g (گروه) جدید به SVG اضافه می‌کند. گروه‌ها به عنوان کانتینرهایی برای عناصر دیگر SVG عمل می‌کنند و به شما اجازه می‌دهند تا چندین عنصر را با هم مدیریت کنید.
  • .call(d3.axisLeft(y)): محور Y را به گروه اضافه می‌کند و از مقیاس باندی y که قبلاً تعریف شده استفاده می‌کند. d3.axisLeft(y) یک محور عمودی در سمت چپ نمودار با استفاده از مقیاس y ایجاد می‌کند.
  • .attr("transform", "translate(100,0)"): گروه محور Y را به سمت راست منتقل می‌کند. translate(100,0) به این معنی است که گروه به اندازه 100 پیکسل به سمت راست منتقل می‌شود. این فاصله 100 پیکسلی به منظور جا دادن محور Y و اطمینان از اینکه محور Y با نمودار تداخل نداشته باشد، در نظر گرفته شده است.

 

ایجاد مستطیل‌های نمودار

 

برای هر استان، یک مستطیل (میله) ایجاد می‌کنیم که عرض آن براساس جمعیت استان تعیین می‌شود. رنگ مستطیل‌ها را نیز تنظیم می‌کنیم.

 

svg.selectAll("myRect")
.data(iranPopulation)
.enter()
.append("rect")
.attr("x", x(0) )
.attr("y", function(d) { return y(d.province); })
.attr("width", function(d) { return x(d.population); })
.attr("height", y.bandwidth() )
.attr("fill", "#69b3a2")
.attr("transform", "translate(102,0)")
.append("title")
.text(d => d.population.toLocaleString())

 

  • svg.selectAll("myRect"): انتخاب تمام عناصر rect که به طور فرضی نام myRect دارند. چون در ابتدا هیچ عنصری وجود ندارد، این انتخاب خالی است.
  • .data(iranPopulation): اتصال داده‌های iranPopulation به انتخاب. هر عنصر داده با یک عنصر rect متناظر خواهد شد.
  • .enter(): یک مرحله ورود (enter) برای داده‌هایی که به هیچ عنصر DOM متصل نیستند. در اینجا، همه داده‌ها جدید هستند و هیچ عنصری در حال حاضر وجود ندارد، بنابراین همه داده‌ها وارد می‌شوند.
  • .append("rect"): برای هر عنصر داده‌ای که وارد شده است، یک عنصر rect جدید به SVG اضافه می‌کند.
  • .attr("x", x(0)): تنظیم مختصات افقی (x) مستطیل‌ها. تمام مستطیل‌ها از نقطه x(0) شروع می‌شوند، که برابر با مقدار 0 در مقیاس x است. این باعث می‌شود که همه مستطیل‌ها از سمت چپ شروع شوند.
  • .attr("y", function(d) { return y(d.province); }): تنظیم مختصات عمودی (y) مستطیل‌ها. این مقدار براساس نام استان‌ها (province) از مقیاس باندی y به دست می‌آید.
  • .attr("width", function(d) { return x(d.population); }): تنظیم عرض مستطیل‌ها براساس جمعیت استان‌ها. مقدار d.population از مقیاس x عبور داده می‌شود تا عرض متناظر با جمعیت استان محاسبه شود.
  • .attr("height", y.bandwidth()): تنظیم ارتفاع مستطیل‌ها برابر با پهنای باند مقیاس y که قبلاً تعریف شده است. این تضمین می‌کند که همه مستطیل‌ها ارتفاع یکسانی دارند و به طور مرتب در محور y قرار می‌گیرند.
  • .attr("fill", "#69b3a2"): تنظیم رنگ پرشدگی مستطیل‌ها به رنگ سبز-آبی (#69b3a2).
  • .attr("transform", "translate(102,0)"): انتقال همه مستطیل‌ها به سمت راست به اندازه 102 پیکسل. این کار باعث می‌شود که مستطیل‌ها به درستی نسبت به محور y تنظیم شوند و فاصله مناسب از محور را داشته باشند.
  • .append("title"): افزودن یک عنصر title به هر مستطیل. عنصر title در SVG برای نمایش ابزارک‌های توضیحی (tooltips) استفاده می‌شود که هنگام قرار گرفتن نشانگر ماوس بر روی عنصر نمایش داده می‌شوند.
  • .text(d => d.population.toLocaleString()): تنظیم متن عنوان به جمعیت استان به صورت قالب‌بندی شده (localeString) که نمایش بهتری از اعداد با جداکننده‌های هزارگان را فراهم می‌کند.

 

در این کد، ما از مقیاس‌های خطی برای محور X و مقیاس باندی برای محور Y استفاده کردیم. محور X براساس جمعیت تنظیم شده و محور Y نام استان‌ها را نمایش می‌دهد. مستطیل‌ها یا میله‌های نمودار براساس جمعیت هر استان تنظیم شده و به رنگ سبز نمایش داده می‌شوند. همچنین، برای هر میله، عنوانی اضافه شده که جمعیت استان را به صورت متنی نمایش می‌دهد.