ماجرا از وقتی شروع شد که یک پروژه‌­­چی(!) به این صورت تعریف شد که یک سری مجموعه داده داریم که هر سطر آن شامل یک tag، امتیاز و url یک تصویر هست و میخواهیم این داده ها را به شکل زیر (با مقداری تفاوت) دربیاوریم به طوری که هر سطر متناظر با یکی از عناصر(دایره های کوچک درون شکل) باشد و شعاع هر عنصر هم متناسب با امتیاز آن سطر باشد و هرچه به سمت بیرون حرکت میکنیم، اندازه آنها بزرگتر شود. البته میخواهیم عناصر به صورت حلزونی قرار بگیرند نه به شکل تصویر زیر که در دوایر متحدالمرکز قرارگرفته اند. همچنین میخواهیم درکنار هر عنصر، tag متناظر با آن هم متناسب با سایز آن عنصر نوشته شود.

نمونه ای از هدفمان (با مقداری اغماض)

راه‌حل‌ها

درادامه مراحلی که طی شد تا به جواب قابل قبولی دست پیدا کنم را شرح می­دهم و ابزارهایی که از آنها استفاده شد را معرفی میکنم:

۱) ابزارهای ساده و تقریبا مشابه

درابتدا نمونه‌­هایی مشابه با کارمان پیدا کردم که آشنایی با آنها ضرر ندارد!

a) در دو سایت https://chirpty.com/  و https://orbit.livasch.com/ میتوان آیدی توییتر یک نفر را داد و تصویری شامل افراد مرتبط به آن فرد که به صورت دایره ای دور فرد قرارگرفته‌­اند را تحویل گرفت (:

نمونه ای از سایت chirpty.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 پیدا کنید. دراین قسمت سه اسلاید وجود دارد که هرسه مفیدفایده هستند :

https://gephi.org/users/

شکل حلزونی

برای درآوردن گراف به شکل حلزونی، میتوان از همان پلاگین Circular Layout استفاده کرد که چیدمان Radial Axis Layout را هم دراختیار ما میگذارد که با تغییر برخی optionهای آن (که در شکل زیر نشان داده شده است)، میتوان به شکل حلزونی موردنظر دست یافت. با استفاده از قسمت rankingهم میتوان راس­ها را از براساس فیلدی خاص، مرتب کرد و درنهایت به شکل زیر دست یافت:

اضافه کردن تصاویر

برای قراردادن image مربوطه درون دایره‌­ها، راه مشخصی پیدا نکردم. پلاگینی برای این کار وجود دارد ولی ظاهرا کار نمیداد و نتوانستم با آن کار کنیم. البته که به‌­نظر، این پلاگین هم برای تصاویری هست که در حافظه موجود داریم نه تصاویر اینترنتی:

https://github.com/chrisxue815/gephi-plugin-image-preview

۳) D3.js

در این مرحله تقریبا به نتیجه مطلوب رسیدم . اما چگونه؟

با جستجوی بیشتر، به D3 رسیدم (مخفف Data-Driven Documents) که یک کتابخانه­ جاوا اسکریپت و متخصص مصورسازی داده‌هاست و از آن برای رسم گراف­ها، جداول، نمودارها و … استفاده میشود مخصوصا برای داده­های live و تعاملی.

بهتر است درابتدا برای یادگیری اولیه کار با این کتابخانه، لینک­ زیر را بخوانید:

https://d3js.org/#properties

اگر حس میکنید برخی مطالب مطرح شده در لینک بالا را درست متوجه نشده‌­اید (که کاملا طبیعی   است!) میتوانید به صورت موردی به این منبع نیز مراجعه کنید:

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هستند، فیلدهایشان تشخیص و درنهایت داده ها در یک آرایه قرار میگیرند.

درنهایت با داده­ هایی تستی، نتیجه به شکل زیر درآمد:

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *