ایجاد نمودار میله‌ای گروه‌بندی شده با استفاده از کتابخانه D3

 

 

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

 

در ابتدا باید اشاره کنیم که برای رسم این نمودار از مجموعه داده زیر استفاده کرده‌ایم:

 

var colorsData = [

{year: 1396, red: 154080, blue: 132751},

{year: 1397, red: 370450, blue: 238893},

{year: 1398, red: 637979, blue: 419548},

{year: 1399, red: 642944, blue: 394671},

{year: 1400, red: 412980, blue: 986148},

{year: 1401, red: 602589, blue: 1338746}

];

 

کد ایجاد نمودار میله‌ای گروه‌بندی شده در کتابخانه D3:

 

var margin = {top: 20, right: 30, bottom: 40, left: 70};
var width = 650 - margin.right - margin.left;
var height = 400 - margin.top - margin.bottom;
 
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
 
var g = svg.append('g')
.attr('transform', `translate(${margin.left + 20}, ${margin.top})`);
 
var x = d3.scaleBand()
.domain(colorsData.map(d => d.year))
.range([0, width])
.padding([0.2]);
 
g.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x).tickSize(0));
 
var y = d3.scaleLinear()
.domain([0, 1500000])
.range([height, 0]);
 
g.append('g')
.call(d3.axisLeft(y));
 
var color = d3.scaleOrdinal()
.domain(colorsData.map(d => d.year))
.range(['#e41a1c','#377eb8'])
 
g.selectAll('.redBar')
.data(colorsData)
.join('rect')
.attr('class', 'redBar')
.attr('x', d => x(d.year))
.attr('width', x.bandwidth() / 2)
.attr('y', d => y(d.red))
.attr('height', d => height - y(d.red))
.attr('fill', color('red'))
.append("title")
.text(d => d3.format(',')(d.red));
 
g.selectAll('.blueBar')
.data(colorsData)
.join('rect')
.attr('class', 'blueBar')
.attr('x', d => x(d.year) + x.bandwidth() / 2)
.attr('width', x.bandwidth() / 2)
.attr('y', d => y(d.blue))
.attr('height', d => height - y(d.blue))
.attr('fill', color('blue'))
.append("title")
.text(d => d3.format(',')(d.blue));
 
var legend = svg.append('g')
.attr('transform', `translate(${(width + margin.right + margin.left) / 2}, 5)`);
 
var legendEntries = ['قرمز', 'آبی'];
var legendColors = ['#e41a1c', '#377eb8'];
 
legend.selectAll('.legendEntry')
.data(legendEntries)
.join('rect')
.attr('class', 'legendEntry')
.attr('x', (d, i) => i * 60)
.attr('y', 0)
.attr('width', 15)
.attr('height', 15)
.attr('fill', (d, i) => legendColors[i]);
 
legend.selectAll('.legendText')
.data(legendEntries)
.join('text')
.attr('class', 'legendText')
.attr('x', (d, i) => i * 50 - 25)
.attr('y', 10)
.text(d => d)
.style('font-size', '12px');
 
svg.append('text')
.attr('x', (width + margin.right + margin.left) / 2)
.attr('y', height + margin.top + margin.bottom - 5)
.attr('text-anchor', 'middle')
.style('font-size', '14px')
.style('font-weight', 'bold')
.text('سال');
 
svg.append('text')
.attr('transform', 'rotate(-90)')
.attr('x', 0 - (height + margin.top + margin.bottom) / 2)
.attr('y', 20)
.attr('text-anchor', 'middle')
.style('font-size', '14px')
.style('font-weight', 'bold')
.text('تعداد');
 
svg.node()

 

خروجی کد:

 

 

تنظیمات اولیه برای رسم نمودار میله‌ای گروه‌بندی شده در کتابخانه D3

 

در ابتدا SVG را ایجاد می‌کنیم و یک گروه داخلی (g) برای اضافه کردن محتوا به SVG تعریف می‌کنیم. این تنظیمات شامل  مرزها و فضای پرشده می‌باشد.

 

var margin = {top: 20, right: 30, bottom: 40, left: 70};
var width = 650 - margin.right - margin.left;
var height = 400 - margin.top - margin.bottom;
 
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
 
var g = svg.append('g')
.attr('transform', `translate(${margin.left + 20}, ${margin.top})`);

 

  • var margin = {top: 20, right: 30, bottom: 40, left: 70} مشخص کردن فاصله‌ها
  • var width = 650 - margin.right - margin.left مشخص کردن عرض svg
  • var height = 400 - margin.top - margin.bottom مشخص کردن ارتفاع svg
  • var svg = d3.create('svg') ایجاد تگ SVG
  • attr('width', width + margin.right + margin.left) مقداردهی به عرض SVG
  • attr('height', height + margin.top + margin.bottom) مقداردهی به ارتفاع SVG
  • var g = svg.append('g') -> ایجاد تگ g برای گروه‌بندی عناصری که به SVG اضافه خواهند شد
  • attr('transform', `translate(${margin.left + 20}, ${margin.top})`) جابجا کردن تگ g
  • var colorsData مقداردهی به متغیر با استفاده از داده‌ها

 

مقیاس‌بندی محورهای نمودار میله‌ای گروه‌بندی شده در کتابخانه D3

 

در مرحله بعد، مقیاس‌بندی برای محورهای x و y انجام می‌دهیم. این مقیاس‌ها به ترتیب برای تاریخ (ماه) و تعداد استفاده می‌شوند.

 

var x = d3.scaleBand()
.domain(colorsData.map(d => d.year))
.range([0, width])
.padding([0.2]);
 
var y = d3.scaleLinear()
.domain([0, 1500000])
.range([height, 0]);

 

  • var x = d3.scaleBand() مشخص کردن محدوده مقیاس محور افقی با استفاده از تابع scaleBand
  • domain(colorsData.map(d => d.year))  مشخص کردن دامنه مقیاس محور افقی با استفاده از شروع و پایان داده‌ها
  • .range([0, width]) محدوده‌ای که lمحور افقی در svg اشغال می‌کند.
  • padding(0.2) فاصله بین میله‌ها (فاصله بین مقادیر)
  • var y = d3.scaleLinear() مشخص کردن مقیاس محور عمودی با استفاده از تابع scaleLinear
  • domain([0, 1500000])  مشخص کردن دامنه مقیاس محور عمودی با استفاده از شروع و پایان داده‌ها
  • range([height, 0]) محدوده‌ای که محور عمودی در svg اشغال می‌کند

 

ایجاد محورهای نمودار میله‌ای گروه‌بندی شده در کتابخانه D3

 

پس از مقیاس‌بندی، محورهای x و y را با استفاده از توابع d3.axisBottom() و d3.axisLeft() ایجاد می‌کنیم و به مختصات SVG اضافه می‌کنیم.

 

g.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x).tickSize(0));
 
g.append('g')
.call(d3.axisLeft(y));

 

  • g.append('g') -> افزودن گروه g برای رسم محور افقی در svg
  • attr('transform', `translate(0, ${height})`) جابجایی گروه g
  • call(d3.axisBottom(x).tickSize(0))ایجاد محور افقی
  • g.append('g') -> افزودن گروه g برای رسم محور عمودی در svg
  • call(d3.axisLeft(y)) استفاده از axisLeft برای ایجاد محور عمودی و مقداردهی با آن با استفاده از مقیاس‌هایی که قبلا تعریف کرده‌ایم

 

مشخص کردن رنگ میله‌ها

 

برای مشخص کردن رنگ هر یک از میله‌ها از تابع d3.scaleOrdinal() استفاده می‌کنیم.

 

var color = d3.scaleOrdinal()
.domain(colorsData.map(d => d.year))
.range(['#e41a1c','#377eb8'])

 

  • var color = d3.scaleOrdinal() مقیاس‌بندی رنگ‌ها براساس دو دسته موجود در داده‌ها
  • domain(colorsData.map(d => d.year)) دامنه مقیاس پذیری براساس سال
  • range(['#e41a1c','#377eb8']) محدوده رنگ‌ها

 

رسم میله‌های نمودار میله‌ای گروه‌بندی شده در کتابخانه D3

 

در این بخش میله‌های نمودار را برای هر دسته از داده‌ها ایجاد می‌کنیم. ابتدا میله‌های رنگ قرمز را ایجاد می‌کنیم.

 

g.selectAll('.redBar')
.data(colorsData)
.join('rect')
.attr('class', 'redBar')
.attr('x', d => x(d.year))
.attr('width', x.bandwidth() / 2)
.attr('y', d => y(d.red))
.attr('height', d => height - y(d.red))
.attr('fill', color('red'))
.append("title")
.text(d => d3.format(',')(d.red));

 

  • g.selectAll('.redBar') انتخاب تمام المان‌های با کلاس redBar
  • data(colorsData) متصل کردن داده‌ها به المان‌های انتخاب شده
  • join('rect') اضافه کردن تگ rect با استفاده از داده‌های مشخص شده
  • attr('class', 'redBar') اضافه کردن کلاس redBar
  • attr('x', d => x(d.year)) مشخص کردن شروع المان در محور افقی
  • attr('width', x.bandwidth() / 2) مشخص کردن عرض میله‌ها
  • attr('y', d => y(d.red)) مشخص کردن شروع المان در محور عمودی
  • attr('height', d => height - y(d.red)) مشخص کردن ارتفاع میله‌ها
  • attr('fill', color('red')) مشخص کردن رنگ میله‌ها

 

ایجاد میله‌های رنگ آبی

 

g.selectAll('.blueBar')
.data(colorsData)
.join('rect')
.attr('class', 'blueBar')
.attr('x', d => x(d.year) + x.bandwidth() / 2)
.attr('width', x.bandwidth() / 2)
.attr('y', d => y(d.blue))
.attr('height', d => height - y(d.blue))
.attr('fill', color('blue'))
.append("title")
.text(d => d3.format(',')(d.blue));

 

  • g.selectAll('.blueBar') انتخاب تمام المان‌های با کلاس blueBar
  • data(colorsData) متصل کردن داده‌ها به المان‌های انتخاب شده
  • join('rect') اضافه کردن تگ rect با استفاده از داده‌های مشخص شده
  • attr('class', 'blueBar') اضافه کردن کلاس blueBar
  • attr('x', d => x(d.year) + x.bandwidth() / 2) مشخص کردن شروع المان در محور افقی
  • attr('width', x.bandwidth() / 2) مشخص کردن عرض میله‌ها
  • attr('y', d => y(d.blue)) مشخص کردن شروع المان در محور عمودی
  • attr('height', d => height - y(d.blue)) مشخص کردن ارتفاع میله‌ها
  • attr('fill', color('blue')) مشخص کردن رنگ میله‌ها

 

ایجاد راهنمای نمودار در کتابخانه D3

 

در این بخش راهنمای نمودار را اضافه می‌کنیم.

 

legend.selectAll('.legendEntry')
.data(legendEntries)
.join('rect')
.attr('class', 'legendEntry')
.attr('x', (d, i) => i * 60)
.attr('y', 0)
.attr('width', 15)
.attr('height', 15)
.attr('fill', (d, i) => legendColors[i]);
 
legend.selectAll('.legendText')
.data(legendEntries)
.join('text')
.attr('class', 'legendText')
.attr('x', (d, i) => i * 50 - 25)
.attr('y', 10)
.text(d => d)
.style('font-size', '12px');

 

  • var legend = svg.append('g') ایجاد تگ g برای گروه‌بندی المان‌های موجود در راهنمای نمودار
  • attr('transform', `translate(${(width + margin.right + margin.left) / 2}, 5)`) جابجا کردن تگ g
  • var legendEntries = ['قرمز', 'آبی']; نام رنگ‌های موجود در راهنما
  • var legendColors = ['#e41a1c', '#377eb8'] مشخص کردن رنگ‌های راهنما
  • legend.selectAll('.legendEntry') انتخاب تمام المان‌ها با کلاس legendEntry
  • data(legendEntries) مشخص کردن منبع داده
  • join('rect') تلفیق داده‌ها با تگ rect
  • attr('class', 'legendEntry') مشخص کردن کلاس legendEntry برای هر المان
  • attr('x', (d, i) => i * 60) مشخص کردن شروع مربع در محور افقی
  • attr('y', 0) مشخص کردن شروع مربع در محور عمودی
  • attr('width', 15) مشخص کردن عرض مریع
  • attr('height', 15) مشخص کردن ارتفاع مربع
  • attr('fill', (d, i) => legendColors[i]) مشخص کردن رنگ هر مربع
  • legend.selectAll('.legendText') انتخاب متن تمام راهنما
  • data(legendEntries) مشخص کردن منبع داده
  • join('text') تلفیق داده‌ها با متن‌ها
  • attr('class', 'legendText') اضافه کردن کلاس legendText
  • attr('x', (d, i) => i * 50 - 25) مشخص کردن شروع متن در محور افقی
  • attr('y', 10) مشخص کردن شروع متن در محور عمودی
  • text(d => d) مشخص کردن متن هر راهنما
  • style('font-size', '12px') اندازه متن

 

ایجاد برچسب‌های محور افقی و عمودی نمودار میله‌ای گروه‌بندی شده در کتابخانه D3

 

و در انتها برچسب محورهای عمودی و افقی را اضافه می‌کنیم.

 

svg.append('text')
.attr('x', (width + margin.right + margin.left) / 2)
.attr('y', height + margin.top + margin.bottom - 5)
.attr('text-anchor', 'middle')
.style('font-size', '14px')
.style('font-weight', 'bold')
.text('سال');
 
svg.append('text')
.attr('transform', 'rotate(-90)')
.attr('x', 0 - (height + margin.top + margin.bottom) / 2)
.attr('y', 20)
.attr('text-anchor', 'middle')
.style('font-size', '14px')
.style('font-weight', 'bold')
.text('تعداد');

 

  • g.append('text') ایجاد متن در تگ g برای محور افقی
  • attr('x', (width + margin.right + margin.left) / 2) شروع متن در محور افقی
  • attr('y', height + margin.top + margin.bottom - 5) شروع متن در محور عمودی
  • attr('text-anchor', 'middle') مشخص کردن نقطه مرجع قرار گیری متن
  • style('font-size', '14px') اندازه قلم
  • style('font-weight', 'bold') پررنگ کردن قلم
  • text('سال') متن نمایش داده شده به عنوان برچسب محور افقی
  • g.append('text') -> ایجاد متن در تگ g برای محور عمودی
  • attr('transform', 'rotate(-90)') -> چرخش متن
  • attr('x', 0 - (height + margin.top + margin.bottom) / 2) شروع متن در محور افقی
  • attr('y', 20) شروع متن در محور عمودی
  • attr('text-anchor', 'middle') مشخص کردن نقطه مرجع قرار گیری متن
  • style('font-size', '14px') اندازه فونت
  • style('font-weight', 'bold') پررنگ کردن قلم
  • text('تعداد') متن نمایش داده شده در عنوان