در این مقاله، قصد داریم نحوهی ایجاد یک نمودار حبابی (Bubble Chart) را که جمعیت استانهای ایران را بهصورت بصری نمایش میدهد، با استفاده از کتابخانهی D3.js بررسی کنیم. این نمودار حبابی به ما کمک میکند تا تفاوتهای جمعیتی استانهای مختلف را با اندازههای مختلف دایرهها نمایش دهیم.
کد کامل:
خروجی:
تنظیمات اولیه و ایجاد عنصر SVG
در این خطوط، عرض و ارتفاع نمودار را تنظیم میکنیم. این مقادیر تعیینکننده اندازه نهایی نمودار خواهند بود. پس از آن مقادیر را به برای ایجاد عنصر SVG به تابع سازنده (create) کتابخانه D3 ارجاع میدهیم.
تعریف مقیاس برای اندازه دایرهها
در اینجا از مقیاس d3.scaleSqrt
برای تعیین اندازه دایرهها استفاده میکنیم. دامنهی این مقیاس از صفر تا حداکثر جمعیت در دادههایمان است، و بازهی خروجی آن از 0 تا 100 پیکسل برای شعاع دایرهها است.
تنظیم نیروهای D3 برای محاسبه موقعیت دایرهها
در اینجا، از شبیهسازی نیروها در D3 استفاده میکنیم. این شبیهسازی شامل سه نیرو است:
forceX
وforceY
برای جذب دایرهها به مرکز نمودار.forceCollide
برای جلوگیری از تداخل دایرهها، که شعاع هر دایره را با استفاده ازradiusScale
تنظیم میکند.
d3.forceSimulation(iranPopulation)
: این خط یک شبیهسازی نیروی D3 ایجاد میکند که بر روی آرایهiranPopulation
اعمال میشود. هر عنصر از این آرایه یک نقطه داده در شبیهسازی است که نیروها بر روی آن اعمال میشوند..force("x", d3.forceX(width / 2).strength(0.05))
: این خط یک نیرویx
به شبیهسازی اضافه میکند که تمام نقاط داده را به سمت مرکز افقی نمودار جذب میکند.d3.forceX(width / 2)
نیرویی ایجاد میکند که همه نقاط را به مقدارwidth / 2
در محور x جذب میکند..strength(0.05)
: این قسمت قدرت نیرویx
را تنظیم میکند. قدرت نیرو تعیین میکند که چقدر سریع نقاط داده به مرکز افقی جذب شوند. مقدار 0.05 نسبتاً ضعیف است و باعث میشود نقاط به آرامی به سمت مرکز حرکت کنند..force("y", d3.forceY(height / 2).strength(0.05))
: این خط یک نیرویy
به شبیهسازی اضافه میکند که تمام نقاط داده را به سمت مرکز عمودی نمودار جذب میکند.d3.forceY(height / 2)
نیرویی ایجاد میکند که همه نقاط را به مقدارheight / 2
در محور y جذب میکند..strength(0.05)
: این قسمت قدرت نیرویy
را تنظیم میکند. قدرت نیرو تعیین میکند که چقدر سریع نقاط داده به مرکز عمودی جذب شوند. مقدار 0.05 نسبتاً ضعیف است و باعث میشود نقاط به آرامی به سمت مرکز حرکت کنند..force("collide", d3.forceCollide(d => radiusScale(d.population) + 2))
: این خط یک نیروی تداخل (collide) به شبیهسازی اضافه میکند که از همپوشانی نقاط داده جلوگیری میکند.d3.forceCollide
یک نیروی تداخل ایجاد میکند.d => radiusScale(d.population) + 2
: این تابع برای هر نقطه داده (d) شعاع دایره را با استفاده ازradiusScale
محاسبه میکند و سپس 2 واحد به آن اضافه میکند. این کار اطمینان حاصل میکند که نقاط داده به اندازه کافی فاصله دارند تا دایرهها با هم تداخل نکنند..on("tick", ticked)
: این خط تابعticked
را بهعنوان هندلر برای رویدادtick
در شبیهسازی تنظیم میکند. هر بار که شبیهسازی بهروز میشود (یا به اصطلاح یک "تیک" میزند)، تابعticked
فراخوانی میشود تا موقعیتهای نقاط داده بهروز شود و نمودار مجدداً رسم شود.
تابع ticked برای بهروزرسانی موقعیت دایرهها
در این تابع، دایرهها و برچسبها را در هر تیک شبیهسازی بهروزرسانی میکنیم:
- ابتدا دایرهها را براساس دادهها و مقیاس شعاع ایجاد و بهروزرسانی میکنیم.
- سپس برچسبها را برای هر دایره ایجاد میکنیم و موقعیت و متن آنها را تنظیم میکنیم.
var u = svg.selectAll("circle")
: این خط تمام عناصرcircle
موجود در SVG را انتخاب میکند..data(iranPopulation)
: این خط دادهها (آرایهiranPopulation
) را به انتخابcircle
اتصال میدهد..join("circle")
: این خط عناصرcircle
جدید را برای هر عنصر دادهای که وجود ندارد ایجاد میکند و اطمینان حاصل میکند که هر عنصر دادهای یک دایره مرتبط دارد..attr("r", d => radiusScale(d.population))
: این خط شعاع هر دایره را بر اساس جمعیت استان تنظیم میکند. تابعradiusScale
مقدار جمعیت را به شعاع دایره تبدیل میکند..attr("cx", d => d.x)
: این خط موقعیت افقی (x) دایره را بر اساس مختصات x محاسبه شده توسط شبیهسازی تنظیم میکند..attr("cy", d => d.y)
: این خط موقعیت عمودی (y) دایره را بر اساس مختصات y محاسبه شده توسط شبیهسازی تنظیم میکند..attr("fill", "steelblue")
: این خط رنگ دایرهها را به "steelblue" تنظیم میکند.var labels = svg.selectAll(".circle-label")
: این خط تمام عناصرtext
با کلاسcircle-label
موجود در SVG را انتخاب میکند..data(iranPopulation)
: این خط دادهها (آرایهiranPopulation
) را به انتخابtext
اتصال میدهد..join("text")
: این خط عناصرtext
جدید را برای هر عنصر دادهای که وجود ندارد ایجاد میکند و اطمینان حاصل میکند که هر عنصر دادهای یک برچسب متن مرتبط دارد..attr("class", "circle-label")
: این خط کلاسcircle-label
را به هر عنصرtext
اضافه میکند تا بتوان آنها را با این کلاس شناسایی کرد..attr("x", d => d.x)
: این خط موقعیت افقی (x) برچسب متن را بر اساس مختصات x محاسبه شده توسط شبیهسازی تنظیم میکند..attr("y", d => d.y)
: این خط موقعیت عمودی (y) برچسب متن را بر اساس مختصات y محاسبه شده توسط شبیهسازی تنظیم میکند..attr('text-anchor', 'middle')
: این خط متن برچسب را در مرکز دایره تراز میکند..attr('font-size', 10)
: این خط اندازه فونت متن برچسب را به 10 تنظیم میکند..text(d => d.province)
: این خط متن برچسب را به نام استان تنظیم میکند.
در این مقاله، نحوه ایجاد یک نمودار حبابی برای نمایش جمعیت استانهای ایران با استفاده از کتابخانه D3.js را بررسی کردیم. این نوع نمودار به ما امکان میدهد تا با استفاده از اندازه دایرهها، جمعیت هر استان را بهصورت بصری مقایسه کنیم. با استفاده از نیروهای D3، موقعیت دایرهها بهطور خودکار محاسبه و بهینهسازی میشود تا تداخل نداشته باشند و بهصورت منظم در نمودار قرار گیرند.