تجسم فضایی با نمودارهای متحرک با استفاده از پورتال نقشه ابری GIS و D3.js

تجسم فضایی با نمودارهای متحرک با استفاده از پورتال نقشه ابری GIS و D3.js

نویسنده: Marko Polovina ، توسعه‌دهنده Frontend در GIS Cloud GIS Cloud API برای تعامل با سایر چارچوب‌ها و کتابخانه‌ها، انعطاف‌پذیر و باز بوده و همیشه بوده است. D3.js (کتابخانه JS اسناد مبتنی بر داده) یک استثنا نیست. با استفاده از D3.js می‌توانیم نمودارهای تعاملی ایجاد کنیم و در نتیجه داده‌هایی را که مصرف می‌کنیم بهتر درک کنیم. با GIS Cloud API و ادغام D3.js ، یک Map Portal (برنامه GIS سفارشی) ایجاد کردیم که بهترین اتصال را از هر دو چارچوب دارد. نتیجه نقشه خطوط لوله آب غنی از اطلاعات است که با دو نوع نمودار یکپارچه شده است . نمودار هیستوگرام و دونات

 

 

 

نحوه شروع ساخت یک برنامه GIS با نمودارهای تعاملی

ابتدا باید برنامه Map Portal خود را راه اندازی کنید . برای اینکه بتوانید این کار را انجام دهید، باید داده ها را آپلود کنید و یک نقشه در GIS Cloud Map Editor ایجاد کنید، به اپلیکیشن App builder بروید و با استفاده از نقشه های ایجاد شده پورتال نقشه خود را بسازید . اگر به دستورالعمل های اضافی در مورد نحوه ایجاد پورتال نقشه خود نیاز دارید، به این مثال

نگاهی بیندازید یا مستقیماً با ما تماس بگیرید . هنگامی که پرتال نقشه شما فعال شد، نقشه شما با داده ها پر شد و کار با سفارشی سازی و نام تجاری پورتال اولیه تمام شد، زمان شروع کدنویسی فرا رسیده است. کتابخانه D3.js را به همراه فایل های app.js و app.css (در حال حاضر خالی) به پورتال نقشه خود اضافه کنید. به GIS Cloud Manager بروید

 

و تب Apps را از داشبورد باز کنید. پورتال نقشه خود را از لیست برنامه ها پیدا کنید، روی Edit کلیک کنید، تب Advanced را باز کنید، به پایین اسکرول کنید و پوشه برنامه را باز کنید. کتابخانه D3.js خود را در مرورگر منبع آپلود کنید.

در فایل app.json (که پس از باز کردن پورتال خود در App Builder و ذخیره تغییرات به صورت خودکار ایجاد می‌شود)، می‌توانیم همه فایل‌های جاوا اسکریپت و CSS را بارگیری کنیم. برای کد JS، فضای نام خود را تنظیم کنید. سپس، اولین تابع را در app.js اضافه کنید که یک پنجره مودال با دو نمودار نشان می دهد.


{
   "responsive": true,
   "scripts": {
       "namespace": "gcd3",
       "init": ["d3/d3.js"],
       "app": ["app.js"]
   },
   "styles": [
       "app.css"
   ],
   "sections": {
       "top": {
           "logo": {},
           "menu": {
               "items": [{
                   "label_i18n": "Show graph",
                   "href": "javascript:;",
                   "onclick": "gcd3.show();"
               }]
           }
       }
   }
}

 

درک داده ها

فراموش نکنید که هیچ راه جهانی برای تجسم داده ها، روی نقشه یا نمودار وجود ندارد. ابتدا سعی کنید داده ها را درک کنید. گاهی اوقات تصمیم گیری در مورد اینکه با داده ها چه کاری انجام دهید تا بقیه کار دشوارتر باشد.

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

اکنون برای درک بهتر میزان انواع خطوط لوله آب در مناطق مختلف، تجسم نقشه و نمودار را ترکیب می کنیم. در پایان، ما نمودارها و نقشه ابری GIS را برای دستیابی به تجسم داده های تعاملی ادغام خواهیم کرد..

پاسخ به درخواست ویژگی ها در GIS Cloud:

نمودار هیستوگرام و انیمیشن ها

ما تصمیم گرفتیم با یکی از محبوب ترین انواع نمودار – هیستوگرام شروع کنیم. پس از بارگذاری نقشه، آن نمودار را در پنجره مودال GIS Cloud نمایش خواهیم داد.

برای این منظور از آبجکت jQuery Deferred در پس زمینه استفاده می کنیم. می توانید از آن استفاده کنید تا منتظر بمانید تا GIS Cloud UI آماده شود.


const loadGraph = () => {
   // show graph in modal window
   const modalWindow = giscloud.ui.modal({
       content: "
     
",
       title: "Pipelines",
       overlay: false,
       draggable: true,
       extraClass: "gc-histogram-modal"
   });
};
 
gcd3.show = () => {
    giscloud.ui.ready.then(() => {
        const viewer = giscloud.ui.map;
        // if histogram is visible, don't try to create a new one
        if ($("#gc-histogram").length > 0) {
            return;
        }
        // load graph if viewer is ready (for menu click)
        if (viewer.mapId) {
            return loadGraph();
        }
        // load graph when viewer is ready
        viewer.bind("ready", loadGraph);
    });
};
 
gcd3.show();

پس از آن، در داخل تابع loadGraph ، داده های ویژگی را برای لایه “Pipelines” بارگذاری کنید.

برای رسیدن به این هدف از روش d3.json استفاده می کنیم. داده های ویژگی را برای نمودار آماده کنید.


d3.json("/rest/1/layers/3432375/features.json", features => {
   const fields = [];
   const graphData = [];
 
   features.data.forEach(feature => {
       if (
           fields.filter(field => {
               return field === feature.data.water_type;
           }).length === 0
       ) {
           // add field
           fields.push(feature.data.water_type);
           // add field to graph data list
           graphData.push({
               field: feature.data.water_type,
               counter: 1,
           });
       } else {
           // add new record to a field in graph data list
           graphData[fields.indexOf(feature.data.water_type)].counter =
               graphData[fields.indexOf(feature.data.water_type)].counter + 1;
       }
   });
 
   histogram(fields, graphData);
});

اکنون داده های گراف آماده است و می توانیم یک نمودار هیستوگرام ایجاد کنیم. حاشیه‌های نمودار را تغییر دهید و آن را تنظیم کنید که برای شما مناسب‌تر است.

برای محور “y” ما از ۲۰۰۰ به عنوان عدد بالا استفاده می کنیم. می توانید آن را به حداکثر نوع خط لوله یا هر عدد دیگری تغییر دهید. در انتهای کد یک انیمیشن ساده خواهید دید.


const histogram = (fields, graphData) => {
   // set the dimensions and margins of the graph
   const margin = {
           top: 10,
           right: 20,
           bottom: 90,
           left: 60,
       },
       width = 550 - margin.left - margin.right,
       height = 400 - margin.top - margin.bottom;
 
   // append the svg object to the body of the page
   const svg = d3
       .select("#gc-histogram")
       .append("svg")
       .attr("width", width + margin.left + margin.right)
       .attr("height", height + margin.top + margin.bottom)
       .append("g")
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
   // X axis: scale and draw:
   const x = d3
       .scaleBand()
       .range([0, width])
       .domain(fields)
       .padding(0.05);
   svg.append("g")
       .attr("transform", "translate(0," + height + ")")
       .call(d3.axisBottom(x))
       .selectAll("text")
       .attr("transform", "translate(-10,0)rotate(-45)")
       .style("text-anchor", "end");
   // Y axis: scale and draw:
   const y = d3
       .scaleLinear()
       .range([height, 0])
       .domain([0, 2000]);
   svg.append("g").call(d3.axisLeft(y));
 
   // append the bar rectangles to the svg element
   svg.selectAll("mybar")
       .data(graphData)
       .enter()
       .append("rect")
       .attr("x", d => x(d.field))
       .attr("y", d => y(0))
       .attr("width", x.bandwidth())
       .attr("height", d => height - y(0))
       .style("fill", "rgb(0, 151, 198)");
 
   // text label for the x axis
   svg.append("text")
       .attr(
           "transform",
           "translate(" + width / 2 + " ," + (height + margin.top + 70) + ")",
       )
       .style("text-anchor", "middle")
       .text("Pipeline type");
 
   // text label for the y axis
   svg.append("text")
       .attr("transform", "rotate(-90)")
       .attr("y", 0 - margin.left)
       .attr("x", 0 - height / 2)
       .attr("dy", "1em")
       .style("text-anchor", "middle")
       .text("Number of pipelines");
 
   // Animation
   svg.selectAll("rect")
       .transition()
       .duration(800)
       .attr("y", d => y(d.counter))
       .attr("height", d => height - y(d.counter))
       .delay((d, i) => i * 100);
};

 

GIS Cloud و ادغام D3.js

اکنون که یک نمودار با یک انیمیشن ایجاد کردیم، زمان آن رسیده است که یک ادغام ساده با GIS Cloud انجام دهیم. نقشه ما می تواند رویدادهای زیادی را ثبت کند، می توانید لیست گسترده رویدادها را در اینجا بیابید .

در مثال ما، می‌خواهیم به این نتیجه برسیم که پس از کلیک کاربر بر روی یک ویژگی تصادفی روی نقشه، یک ستون نمودار بر اساس نوع خط لوله انتخاب شود.

برای آن عمل، از رویداد  featureClick استفاده کنید. نوع ویژگی و ستون های نمودار را مقایسه کنید تا تصمیم بگیرید که چه نوع خط لوله فعال است. کد جدید خود را در تابع هیستوگرام قرار دهید .

 


const viewer = giscloud.ui.map;
viewer.bind("featureClick", onFeatureClick);
 
const onFeatureClick = evt => {
   giscloud.features.byId(evt.layerId, evt.featureId).done(feature => {
       svg.selectAll("rect").each((d, i, elements) => {
           if (d.field === feature.data.water_type) {
               elements[i].style.fill = "rgba(0, 151, 198, 0.4)";
           } else {
               elements[i].style.fill = "rgb(0, 151, 198)";
           }
       });
   });
};

در این مرحله، ما می خواهیم کار مشابهی را در جهت دیگر انجام دهیم. وقتی کاربر بر روی ستون نمودار کلیک می کند، نقشه بر اساس نوع خط لوله در نمای محدوده ویژگی بزرگنمایی می کند .

بیایید یک رویداد d3.js را به متغیر  svg اضافه کنیم.


svg.selectAll("mybar")
.on("click", onClick)
.on("mouseover", onMouseOver)
.on("mouseleave", onMouseLeave);

رویدادهای MouseOver و MouseLeave رنگ ستون نمودار و نوع مکان نما را تغییر می دهند.


const onMouseOver = (d, i, elements) => {
   elements[i].style.fill = "rgba(0, 151, 198, 0.4)";
   elements[i].style.cursor = "pointer";
};
 
const onMouseLeave = (d, i, elements) => {
   elements[i].style.fill = "rgb(0, 151, 198)";
};

رویداد onClick که برای ستون نمودار استفاده می شود، نقشه را در محدوده ویژگی بزرگنمایی می کند.


const onClick = (d, i, elements) => {
   zoomToFeatures(d.field);
};
 
const zoomToFeatures = value => {
   const viewer = giscloud.ui.map;
   // get bounds for filtered features
   giscloud.geoutils
       .featureBounds(3432375, {
           where: "water_type" + "='" + value + "'",
           srid: viewer.instance.epsg,
       })
       .done(response => {
           if (response.bounds.left == 0 || response.bounds.right == 0) {
               return;
           }
 
           // apply bounds
           viewer.bounds(
               new giscloud.Bounds(
                   response.bounds.left,
                   response.bounds.bottom,
                   response.bounds.right,
                   response.bounds.top,
               ),
           );
       });
};

 

نمودار دونات

همانطور که برای نمودار هیستوگرام انجام دادیم، نمودار دونات را در پنجره مودال GIS Cloud نمایش خواهیم داد. اما اکنون، ما کار متفاوتی انجام خواهیم داد.

این نوع نمودار می‌تواند داده‌های «پاک‌تر» را نمایش دهد، اگر نوع خط لوله جدیدی را وارد کنیم – OTHER .

اگر کمتر از ۱۰۰ خط لوله برای یک نوع خط لوله خاص وجود دارد، باید آن نوع خط لوله را در رده OTHER قرار دهیم . سپس باید تعداد خطوط لوله را روی رویداد MouseOver چاپ کنیم و نمودار دونات ما آماده است.


graphData = graphData.reduce((obj, item) => {
   if (item.counter 

 


d3.selectAll("path").on("mousemove", d => {
   div.style("left", d3.event.pageX + 10 + "px");
   div.style("top", d3.event.pageY - 25 + "px");
   div.style("display", "inline-block");
   div.html("Number of pipelines" + "
" + d.data.value);
});
 
d3.selectAll("path").on("mouseout", d => {
   div.style("display", "none");
});

 

نتیجه

در این پروژه، می‌خواهیم به شما نشان دهیم که چگونه می‌توانید GIS Cloud API و برنامه‌ها را با سایر فریم‌ورک‌ها ادغام کنید. با استفاده از D3.js، می توانید نمودارهای تعاملی بسازید و آنها را با نقشه های GIS Cloud و داده های مکانی متصل کنید.

اینجا را کلیک کنید تا پورتال نقشه را که در این پروژه ایجاد کرده ایم باز کنید و انیمیشن های نمودار را امتحان کنید!

اگر می خواهید برنامه Map Portal خود را بسازید و در مورد ادغام های احتمالی بیشتر بدانید، ثبت نام کنید و برنامه های GIS Cloud و API را کاوش کنید! همچنین، در صورت داشتن هرگونه سوال، نظر یا ایده ای برای نمونه توسعه جدید

، دریغ نکنید با ما تماس بگیرید . کد نویسی مبارک!

بدون دیدگاه

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

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

خانهدربارهتماسارتباط با ما