ماجرا از وقتی شروع شد که یک پروژهچی(!) به این صورت تعریف شد که یک سری مجموعه داده داریم که هر سطر آن شامل یک tag، امتیاز و url یک تصویر هست و میخواهیم این داده ها را به شکل زیر (با مقداری تفاوت) دربیاوریم به طوری که هر سطر متناظر با یکی از عناصر(دایره های کوچک درون شکل) باشد و شعاع هر عنصر هم متناسب با امتیاز آن سطر باشد و هرچه به سمت بیرون حرکت میکنیم، اندازه آنها بزرگتر شود. البته میخواهیم عناصر به صورت حلزونی قرار بگیرند نه به شکل تصویر زیر که در دوایر متحدالمرکز قرارگرفته اند. همچنین میخواهیم درکنار هر عنصر، tag متناظر با آن هم متناسب با سایز آن عنصر نوشته شود.
راهحلها
درادامه مراحلی که طی شد تا به جواب قابل قبولی دست پیدا کنم را شرح میدهم و ابزارهایی که از آنها استفاده شد را معرفی میکنم:
۱) ابزارهای ساده و تقریبا مشابه
درابتدا نمونههایی مشابه با کارمان پیدا کردم که آشنایی با آنها ضرر ندارد!
a) در دو سایت https://chirpty.com/ و https://orbit.livasch.com/ میتوان آیدی توییتر یک نفر را داد و تصویری شامل افراد مرتبط به آن فرد که به صورت دایره ای دور فرد قرارگرفتهاند را تحویل گرفت (:
b) برای پاورپوینت Templateهای وجوددارد که نزدیک به هدف ماست:
https://slidemodel.com/templates/spiral-chart-diagram-powerpoint/
https://www.slideteam.net/hm-five-staged-spiral-chart-diagram-flat-powerpoint-design.html
c) نرم افزاری به نام ConceptDraw که گویا مخصوص ارائه و اسلاید است و قالبهای متفاوتی برای این کار ارائه میکند. مثلا لینک زیر یک مقدار شبیه به آن نمودار دایرهای است که میخواهیم:
https://www.conceptdraw.com/How-To-Guide/bubble-chart-maker
۲) gephi
یک ابزاری که از آن کمک گرفتم، نرمافزار gephi بود که از سایتش https://gephi.org/ قابل بارگیری است و برای مصورسازی گرافها قابل استفاده است. در تصاویر زیر میتوانید محیط نرم افزار و برخی نمونه های کار با آن را مشاهده کنید:
در ابتدای کار دقت کنید که دادههای ورودی که به نرمافزار میدهیم باید طبق فرمت خاصی باشد تا gephi بتواند یالها، راسها، فیلدهای مربوط به آن راس و … را تشخیص دهد. میتوان برای دستگرمی، از دادههای آمادهای که به طور پیشفرض در نرمافزار هست، استفاده کرد. (برای مثال یک مجموعه داده به نام les miserables که شامل شخصیتهای رمان بینوایان و ارتباطات بین آنهاست.)
دست به کار شوید!
با دادن فایل دادهها، نرمافزار گرافی به صورت خام رسم میکند که میتوان با ابزارهای مختلفی که در نرمافزار موجود هست، آن را به دلخواه تغییر داد. مثلا میتوان در منوی Ranking -> nodes ، شعاع دایرهها (راسها) را براساس یک ویژگی آنها مرتب کرد. در منوی layout میتوان چیدمان گراف را تغییر داد و مثلا راسها را به صورت دایره ای، حلزونی، خطی و … سامان داد ( برای استفاده ازCircular layout باید پلاگینی به همین نام را نصب کرد). در نوار پایین محیط نرمافزار میتوان فیلدی دلخواه از فیلدهای رئوس (درمورد دادههای ما tagهر سطر) را انتخاب کرد و مقدارش را در کنار آن راس نمایش داد. تنظیمات دیگر مثل تنظیم تراکم و فاصله راسها، تنظیمات یالها و یا حذف آنها، تغییر رنگ راسها و … را میتوانید در لینک زیر و در قسمت Official Tutorial پیدا کنید. دراین قسمت سه اسلاید وجود دارد که هرسه مفیدفایده هستند :
شکل حلزونی
برای درآوردن گراف به شکل حلزونی، میتوان از همان پلاگین Circular Layout استفاده کرد که چیدمان Radial Axis Layout را هم دراختیار ما میگذارد که با تغییر برخی optionهای آن (که در شکل زیر نشان داده شده است)، میتوان به شکل حلزونی موردنظر دست یافت. با استفاده از قسمت rankingهم میتوان راسها را از براساس فیلدی خاص، مرتب کرد و درنهایت به شکل زیر دست یافت:
اضافه کردن تصاویر
برای قراردادن image مربوطه درون دایرهها، راه مشخصی پیدا نکردم. پلاگینی برای این کار وجود دارد ولی ظاهرا کار نمیداد و نتوانستم با آن کار کنیم. البته که بهنظر، این پلاگین هم برای تصاویری هست که در حافظه موجود داریم نه تصاویر اینترنتی:
https://github.com/chrisxue815/gephi-plugin-image-preview
۳) D3.js
در این مرحله تقریبا به نتیجه مطلوب رسیدم . اما چگونه؟
با جستجوی بیشتر، به D3 رسیدم (مخفف Data-Driven Documents) که یک کتابخانه جاوا اسکریپت و متخصص مصورسازی دادههاست و از آن برای رسم گرافها، جداول، نمودارها و … استفاده میشود مخصوصا برای دادههای live و تعاملی.
بهتر است درابتدا برای یادگیری اولیه کار با این کتابخانه، لینک زیر را بخوانید:
اگر حس میکنید برخی مطالب مطرح شده در لینک بالا را درست متوجه نشدهاید (که کاملا طبیعی است!) میتوانید به صورت موردی به این منبع نیز مراجعه کنید:
https://www.tutorialspoint.com/d3js/d3js_selections.htm
سپس برای ایده گرفتن و دیدن نمونه کارهای مرتبط، به این دو صفحه هم نگاهی بیاندازید:
https://www.pubnub.com/blog/fun-with-d3js-data-visualization-eye-candy-with-streaming-json/
http://bl.ocks.org/eesur/be2abfb3155a38be4de4
پیادهسازی
درادامه به قطعات کلیدی کدی که نوشتم، میپردازم:
(همانطور که ابتدا گفتیم، هر موجودیت دارای آدرس یک تصویر، یک tag و یک size است.)
var vis = svg.selectAll('circle')
.data(nodes);vis.enter().append('svg:circle')
.attr('style', 'color: yellow')
.attr('transform', function (d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function (d) {
return d.r;
})
.attr('class', function (d) {
return d.className;
});
در لایه ی زیرِ هر تصویرِ دایره ای، یک دایره به رنگ مشکی قرار دارد. با این قطعه کد، جوری برنامه ریزی شده است که این دایره ی مشکی طوری در زیر تصاویر قرار بگیرد که به عنوان border برای تصاویر ما عمل کند.
——————————————————————————–
vis.enter().append('svg:image')
.attr("xlink:href", function (d) {
return d.img;
})
.attr("height", function (d) {
return d.r * 2;
})
.attr("width", function (d) {
return d.r * 2;
})
.attr('transform', function (d) {
return 'translate(' + (d.x - d.r) + ',' + (d.y - d.r) + ')';
});
این قطعه، مربوط به گرفتن تصویر از urlمربوطه و تنظیم مکان قرار گیری و اندازه های طول و عرض تصویر است.
—————————————————————–
vis.enter().append("text")
.attr("class", "nodetext")
.attr("x", function (d) {
return d.x
})
.attr("y", function (d) {
return d.y + d.r;
})
.attr("fill", tcBlack)
.attr("font-size", function (d) {
return d.r / 5;
})
.text(function (d) {
return d.name;
});
مربوط به tagی که در کنار تصویر و با رنگ زرد قرار میگیرد. اندازه فونت آن متناسب با اندازه تصویر تنظیم شده است.
———————————————————————
function processData(data) {
var obj = data.countries_msg_vol;
var newDataSet = [];
var prop;
for (let i = 0; i < obj.length; i++) {
prop = obj[i];
newDataSet.push({name: prop.hero, className: prop.hero.toLowerCase(), size: prop.size, img: prop.img},);
}
return {children: newDataSet};
}
موجودیت ها که به صورت jsonهستند، فیلدهایشان تشخیص و درنهایت داده ها در یک آرایه قرار میگیرند.
درنهایت با داده هایی تستی، نتیجه به شکل زیر درآمد: