تخصیص ویژگی به گرافیک-موسسه چشم انداز هزاره سوم ملل-آموزش کاربردی GIS و RS
ویژگیهای گرافیک شامل زوج مقدار/نام برای توصیف شی هستند. در بعضی موارد گرافیکها با برنامه نویسی ایجاد میشوند و در موارد دیگر، گرافیکها در نتیجهی یک عمل جستجوی QueryTask ایجاد میشوند. در این گونه موارد هر گرافیک ترکیبی از ویژگی و هندسه است و هر گرافیک را باید به درستی نماد گذاری کنید.
فیلدهای همراه هرلایه، در واقع همان ستونهای جدول اطلاعات توصیفی در ماژول ArcMap هستند که در اینجا به عنوان ویژگیها نام برده میشوند. در بعضی موارد میتوان با استفاده از outFields برای این فیلدها محدودیت گذاشت تا تنها این فیلدها برای ایجاد گرافیک استفاده شوند. البته در مواردی که گرافیکها با برنامه نویسی ایجاد میشوند شما باید ویژگیها را خودتان در کد با استفاده از متد Graphic.setAttributes() بنویسید. نمونهای از ایجاد گرافیک با برنامه نویسی را در زیر میبینید.
Graphic.setAttributes( {“XCoord”:evt.mapPoint.x, “YCoord”.evt.
mapPoint.y,”Plant”:”Mesa Mint”});
نمایش ویژگیهای گرافیک در یک پنجرهی اطلاعاتی
علاوه بر ویژگیها یا همان فیلدها گرافیکها میتوانند یک الگوی اطلاعاتی داشته باشند که این الگو نحوهی نمایش خصوصیات را در یک پنجره تعیین میکند. یک متغیر نقطهای در نمونه کد زیر ایجاد شده است و شامل زوج مقدار/کلید است. در این مثال، کلیدها شامل آدرس، شهر و ایالت هستند که هر کدام از این نامها یا کلیدها یک مقدار دارند. این متغیر نقطهای پارامتر سوم سازنده است. الگوی اطلاعاتی درواقع سبک پنجرهی اطلاعاتی را مشخص میکند. اینکه عنوان پنجرهی اطلاعاتی با چه رنگی یا با چه فونتی باشد و محتویات پنجره را مشخص میکند. محتویات پنجره اختیاری است و میتواند خالی باشد.
var pointESRI = new Point(Number(theX), Number(theY),msr);
var markerSymbol = new SimpleMarkerSymbol();
markerSymbol.setStyle(SimpleMarkerSymbol.STYLE_SQUARE);
markerSymbol.setSize(12);
markerSymbol.setColor(new Color([255,0,0]));
var pointAttributes = {address:”101 Main Street”, city:”Portland”, state:”Oregon”};
var pointInfoTemplate = new InfoTemplate(“Geocoding Results”);
//create point graphic using point and marker symbol
var pointGraphic = new Graphic(pointESRI, markerSymbol, pointAttributes).setInfoTemplate(pointInfoTemplate);
//add graphics to maps’ graphics layer
map.graphics.add(pointGraphic);
تصویر زیر حاصل اجرای کد قبلی است.
ایجاد گرافیک ها
وقتی هندسه، ویژگی و نمادگذاری را برای گرافیک تعیین کنید، یک شی گرافیکی با پارامترهای سازنده ایجاد میشود. این سازنده مربوط به شی Graphic است. در اینجا متغیرهایی مانند pointESRI برای هندسه، markerSymbol برای نمادگذاری، pointAttributes برای ویژگیهای نقطه و متغیر pointInfoTemplate را برای الگوی اطلاعاتی تعیین کردیم. همهی این متغیرها را به عنوان ورودی سازنده شی Graphic معرفی کردیم. یک گرافیک جدید به نام pointGraphic با استفاده از سازنده شی Graphic ایجاد کردیم. در نهایت گرافیکها به لایهی گرافیک اضافه شدند.
var pointESRI = new Point(Number(theX), Number(theY, msr);
var markerSymbol = new SimpleMarkerSymbol();
markerSymbol.setStyle(SimpleMarkerSymbol.STYLE_SQUARE);
markerSymbol.setSize(12);
markerSymbol.setColor(new Color([255,0,0]));
var pointAttributes = {address:”101 Main Street”, city:”Portland”, state:”Oregon”};
var pointInfoTemplate = new InfoTemplate(“Geocoding Results”);
//create the point graphic using point and marker symbol
var pointGraphic = new Graphic(pointESRI, markerSymbol,
pointAttributes).setInfoTemplate(pointTemplate);
//add graphics to maps’ graphics layer
map.graphics.add(pointGraphic);
اضافه کردن گرافیکها به لایهی گرافیک
قبل از آن که گرافیکها بر روی نقشه نمایش داده شوند، ابتدا باید به لایهی گرافیک اضافه شوند. هر نقشه یک لایهی گرافیک دارد که شامل آرایهای از گرافیکها است و تا زمانی که گرافیکی ایجاد نکنید این آرایه خالی خواهد بود. این لایه میتواند شامل هر نوع گرافیکی باشد. بدین معنی که شما میتوانید گرافیک نقطه، خط و پولیگون را همزمان در لایهی واحد قرار دهید. گرافیکها با متد Add() به لایه اضافه میشوند و با متد Remove از لایه پاک میشوند. اگر بخواهید همهی گرافیکها را پاک کنید از متد clear() استفاده کنید.
لایهی گرافیکی چندگانه
این نوع لایهها توسط API پشتیبانی میشوند. لایههای گرافیکی به آسانی اضافه یا پاک میشوند. مثلاً شما میتوانید گرافیکهای پولیگونی را جهت نمایش شهرستانها در لایهی گرافیکی قرار دهید. هم چنین میتوانید گرافیکهای نقطهای را در لایهی گرافیکی قرار دهید که این لایهی گرافیکی در لایهی گرافیکی دیگری قرار دارد. سپس با توجه به نیازتان، میتوانید این لایهی گرافیکی دوم را نیز اضافه کنید.
کار با گرافیکها
در این بخش گرافیکها را ایجاد و آنها بر روی نقشه نمایش میدهیم. در این نقشه تراکم جمعیتی شهرستانهای ایالت کلرادو را نشان میدهیم. همانگونه که در بخش بعدی توضیح میدهیم عملیات جستجو در ArcGIS Server اجرا میشود. جستجوهای مکانی و توصیفی انجام داده و عوارض و موقعیت جغرافیایی آنها را شناسایی میکنیم. در نهایت فیلدها را به عوارض گرافیکی اضافه کرده و آنها را در یک پنجره نمایش میدهیم.
مراحل زیر را دنبال کنید:
1- Sandbox جاوااسکریپت موجود در لینک https://developers.arcgis.com/en/ javascript/sandbox/sandbox.html را باز کنید.
2- محتویات تگ <script> را کاملا پاک کنید. طوری که فقط تگ باز <script> و تگ بستهی </script> بماند.
3- متغیرهای مورد استفادهی اپلیکیشن را تعریف کنید:
<script>
var map, defPopSymbol, onePopSymbol, twoPopSymbol,
threePopSymbol, fourPopSymbol, fivePopSymbol;
</script>
4- تابع require() را به صورت زیر اضافه کنید:
<script>
var map, defPopSymbol, onePopSymbol, twoPopSymbol,
threePopSymbol, fourPopSymbol, fivePopSymbol;
require([“esri/map”, “esri/tasks/query”, “esri/tasks/QueryTask”,
“esri/symbols/SimpleFillSymbol”, “esri/InfoTemplate”, “dojo/ domReady!”],
function(Map, Query, QueryTask, SimpleFillSymbol,
InfoTemplate) {
});
</script>
منابع esri/tasks/query و esri/tasks/ QueryTask جدید هستند ولی فعلاً در مورد این منابع توضیحی نمی دهیم تا درفصل بعدی به تفصیل توضیح دهیم. در اینجا همین قدر کافی است که بدانید این منابع برای انجام عملیات جستجوی مکانی و توصیفی در یک لایهی دادهای استفاده میشوند.
5- درون تابع require() شی map ایجاد کرده و نقشهی مبنای streets را قرار دهید.
<script>
var map, defPopSymbol, onePopSymbol, twoPopSymbol,
threePopSymbol, fourPopSymbol, fivePopSymbol;
require([“esri/map”, “esri/tasks/query”, “esri/tasks/
QueryTask”, “esri/symbols/SimpleFillSymbol”, “esri/InfoTemplate”,
“dojo/_base/Color”, “dojo/domReady!”],
function(Map, Query, QueryTask, SimpleFillSymbol,
InfoTemplate, Color) {
map = new Map(“map”, {
basemap: “streets”,
center: [-105.498,38.981], // long, lat
zoom: 6,
sliderStyle: “small”
});
});
</script>
6- درون تابع require() دقیقاً در زیر ایجاد شی map خطوط کد سیاه پررنگ زیر را اضافه کنید. این خطوط برای ایجاد یک نماد پولیگونی هستند. ابتدا یک شی SimpleFillSymbol ایجاد کرده و آن را به متغیر defPopSymbol تخصیص میدهیم؛ و از ترکیب رنگی RGB(255,255,255) استفاده کرده تا مطمئن شویم که زمینهی پولیگون کاملاً شفاف است. هم چنین میتوانید از مقدار 0 نیز برای این کار استفاده کنید. سپس اشیاء نماد را اضافه میکنیم.
map = new Map(“mapDiv”, {
basemap: “streets”,
center: [-105.498,38.981], // long, lat
zoom: 6,
sliderStyle: “small”
});
defPopSymbol = new SimpleFillSymbol().setColor(new
Color([255,255,255, 0])); //transparent
در بخش بعدی میبینید که عمل جستجو در اپلیکیشن به چه صورت استفاده میشود. در این بخش قصد داریم تا عمل جستجوی توصیفی (فیلدی) را بر روی لایهی مرزهای شهرستانها انجام دهیم.
7- خوب حالا برای انجام عمل جستجو، به سرویس نقشهای که لایهها در آنجا قرار دارند بروید. به لینک:
https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/ MapServer
بروید. در سرویس نقشهای که در لینک بالا میبینید، اطلاعات سرشماری ایالتهای آمریکا و شهرستانها و هم چنین لایهی بزرگراهها وجود دارد. در این سرویس، ID لایهی counties عدد 2 میباشد. روی لایهی counties بزنید تا اطلاعاتی در مورد این لایه به دست آورید. این لایه تعداد زیادی فیلد دارد اما میخواهیم نام ایالتها را جستجو کنیم و نیز اطلاعاتی در مورد تراکم جمعیت داشته باشیم، پس برای این جستجو از دو فیلد STATE_NAME و POP90_SQMI استفاده میکنیم.
8- به Sandbox بازمی گردیم. یک شی QueryTask جدید ایجاد میکنیم. کد ایجاد شی QueryTask را در زیر کد تعریف متغیر defPopSymbol مینویسیم. وقتی یک شی جدید QueryTask ایجاد میکنیم و این شی را مقداردهی اولیه میکنیم منحصراً به لایهی با ID=2 اشاره میکند که همان لایهی county سرویس نقشه است. در زیر خطوط کد لازم آمده است.
var queryTask = new QueryTask(“https://sampleserver1.arcgisonline.
com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/2”);
9- همهی اشیاء QueryTask به پارامترهای ورودی نیاز دارند تا بر اساس آنها بر روی لایه اعمال شوند. این کار با یک شی Query انجام میشود. قطعه کد زیر را درست زیر خط کد تعریف متغیر queryTask بنویسید.
Var query = new Query();
10- حال تعدادی ویژگی برای شی Query تعریف میکنیم. خطوط کد زیر را بعد از تعریف متغیر query بنویسید.
var query = new Query();
query.where = “STATE_NAME = ‘Colorado'”;
query.returnGeometry = true;
query.outFields = [“POP90_SQMI”];
11- ویژگی where برای ایجاد عبارت جستجو بر روی لایه استفاده میشود. در این تمرین میخواهیم سطرهایی با نام ایالت Colorado را در اپلیکیشن نشان دهیم. وقتی ویژگی returnGeometry را با مقدار true تنظیم میکنید، ArcGIS Server عوارضی که با جستجوی شما منطبق شدهاند را به صورت هندسی (پولیگونی) بر روی نقشه نمایش میدهد. این کار ضروری است چون میخواهیم این عوارض را در قالب گرافیکها بر روی نقشه نشان دهیم. در نهایت ویژگی outFields برای تعیین فیلدهایی است که باید همراه با هندسهی عارضه برگردانده شوند.
12- در این مرحله متد execute را جهت جستجو روی لایهی counties استفاده میکنیم. این عمل جستجو بر اساس پارامترهایی که در شی query تعیین کردیم انجام میشود. برای این کار کد زیر را استفاده کنید.
queryTask.execute(query, addPolysToMap);
13- در این مرحله بعد از فرستادن شی query به ArcGIS Server، از تابع callback با نام addPolysToMap استفاده میکنیم. همانطور که قبلاً گفتیم توابع callback توابعی هستند که با توجه به ورودی یک خروجی برمی گردانند و حالت واکنشی و پاسخگویی دارند. بعد از آنکه ArcGIS Server جستجو را انجام داد و نتایج را برگرداند، تابع addPolysToMap اجراء میشود. تابع addPolysToMap با توجه به شی featureSet که به عنوان پارامتر ورودی به این تابع فرستاده میشود، رکوردها را بر روی نقشه رسم میکند. بیائید نحوهی اجرای کد را بررسی کنیم. در ابتدا که شی queryTask اجرا میشود، ArcGIS Server یک شی featureSet برمیگرداند. شی featureSet شامل آرایهای از اشیاء گرافیکی است که در نتیجهی جستجو برگردانده میشوند. درون تابع addPolysToMap کد var features = featureSet.features; را میبینید. ویژگی features آرایهای از گرافیکها را برمیگرداند. از یک ساختار تکرار برای نمایش تک تک این گرافیکها بر روی نقشه استفاده میکنیم. با اضافه کردن خطوط کد زیر تابع callback ایجاد میشود.
Function addPolysToMap(featureSet) {
var features = featureSet.features;
var feature;
for (var i=0, il=features.length; i<il; i++) {
feature = features[i];
map.graphics.add(features[i].setSymbol(defPopSymbol));
}
}
متد add() هر گرافیکی که ایجاد میشود را به شی لایهی گرافیکی اضافه میکند.
14- با زدن دکمهی Run کد را اجرا کنید. تصویر زیر خروجی ما خواهد بود. میبینید که شهرها با نمادی که قبلاً ایجاد کردیم مشخص شده اند.
حال کدهای بیشتری برای رنگ بندی شهرها بر اساس جمعیتشان اضافه خواهیم کرد. به متغیر defPopSymbol درون تابع require() دقت کنید. چهار نماد جدید اضافه کردیم.
//defPopSymbol = new SimpleFillSymbol().setColor(new
Color([255,255,255, 0])); //transparent
onePopSymbol = new SimpleFillSymbol().setColor(new Color([255,255,128,
.85])); //yellow
twoPopSymbol = new SimpleFillSymbol().setColor(new Color([250,209,85,
.85]));
threePopSymbol = new SimpleFillSymbol().setColor(new
Color([242,167,46,.85])); //orange
fourPopSymbol = new SimpleFillSymbol().setColor(new Color([173,83,19,
.85]));
fivePopSymbol = new SimpleFillSymbol().setColor(new Color([107,0,0,
.85])); //dark maroon
نمادهایی باید ایجاد کنیم که به صورت طیف رنگی برای هر شهرستان نمایش داده میشوند. این طیف رنگی بر اساس تراکم جمعیت خواهد بود. هم چنین ما وضوح 0.85 را در نظر گرفتهایم. با این کار نقشهی مبنایی که زیر لایهی شهرستانها قرار دارد، با وضوح 85% دیده میشود. قبلاً اشیاء queryTask و Query را ایجاد کرده و از ویژگی outFields برای بازگشت فیلد POP90_SQMI استفاده کردیم. به مقادیر موجود در این فیلد بازگشتی نیاز داریم. این مقادیر بر اساس تراکم جمعیتی هر شهر میباشند و هر شهر با توجه به تراکم جمعیتی که دارد یک نماد منحصربفرد خواهد داشت. تابع addPolysToMap را مطابق کد زیر تغییر دهید. در ادامه عملکرد دقیق هر کدام از خطوط آمده است.
function addPolysToMap(featureSet) {
var features = featureSet.features;
var feature;
for (var i=0, il=features.length; i<il; i++) {
feature = features[i];
attributes = feature.attributes;
pop = attributes.POP90_SQMI;
if (pop < 10)
{
map.graphics.add(features[i].
setSymbol(onePopSymbol));
}
else if (pop >= 10 && pop < 95)
{ map.graphics.add(features[i].
setSymbol(twoPopSymbol));
}
else if (pop >= 95 && pop < 365)
{ map.graphics.add(features[i].
setSymbol(threePopSymbol));
}
else if (pop >= 365 && pop < 1100)
{ map.graphics.add(features[i].
setSymbol(fourPopSymbol));
}
else
{ map.graphics.add(features[i].
setSymbol(fivePopSymbol));
}
}
}
کد بالا اطلاعات تراکم جمعیتی موجود در هر گرافیک را استخراج میکند و این اطلاعات را درون متغیر pop ذخیره میکند. ساختار if/else به هر گرافیک یک نماد میدهد. برای مثال برای شهری با تراکم جمعیتی 400 نماد fourPopSymbol را خواهد گرفت. حلقهی for همهی شهرهای ایالت Colorado را بر اساس تراکم جمعیتی آنها پوشش میدهد. تصویر زیر اجرای کد را نشان میدهد.
حال میخواهیم ویژگیها را به یک گرافیک پیوست و ضمیمه کنیم و زمانی که گرافیکی کلیک شد، این ویژگیها در پنجرهی اطلاعاتی آن گرافیک نمایش داده شوند. پنجرهی اطلاعاتی یک پنجرهی پاپآپ است. پنجرههای پاپآپ در HTML وجود دارند که به صورت آنی و با اندازههای کوچک ظاهر میشوند. میتوانید در این پنجره اطلاعاتی غیر از ویژگیهای گرافیک کلیک شده نیز قرار دهید. اطلاعات این پنجرهها توسط شی InfoTemplate تعیین میشوند. با این شی هم عنوان پنجره و هم محتویات پنجره را میتوانیم تعیین کنیم. میخواهیم فیلدهای بیشتری را درون پنجره قرار دهیم. برای این کار خط کد query.outFields را به صورت زیر ویرایش کنید:
query.outFields = [“NAME”,”POP90_SQMI”,”HOUSEHOLDS”,”MALES”,”FEMALES”,”WHITE”,”BLACK”,”HISPANIC”];
سپس کد زیر را درست در زیر خط queryTask.execute بنویسید:
resultTemplate = InfoTemplate(“County Attributes”, “${*}”);
پارامتر County Attributes اولین پارامتری است که به سازنده فرستاده میشود. این پارامترعنوان پنجرهی پاپآپ را تعیین میکند. پارامتر دوم برای تعیین تمام زوجهای “مقدار/نام ” است که باید در محتویات پنجره نمایش داده شوند؛ بنابراین فیلدهایی که به query.outFields اضافه کردهایم، باید در پنجرهی اطلاعاتی نمایش داده شوند. هر بار که یک گرافیک کلیک میشود یک شی InfoTemplate جدید ایجاد میشود و شی InfoTemplate قبلی پاک میشود و یک شی جدید InfoTemplate برای گرافیک کلیک شده ایجاد میشود. سپس باید از متد Graphic.setInfoTemplate() برای تخصیص شی به گرافیک استفاده کنید. پس درون ساختار if/else خطوط کد مشخص شده را اضافه کنید:
if (pop < 10)
{
map.graphics.add(features[i].
setSymbol(onePopSymbol).setInfoTemplate(resultTemplate));
}
else if (pop >= 10 && pop < 95)
{
map.graphics.add(features[i].
setSymbol(twoPopSymbol).setInfoTemplate(resultTemplate));
}
else if (pop >= 95 && pop < 365)
{
map.graphics.add(features[i].
setSymbol(threePopSymbol).setInfoTemplate(resultTemplate));
}
else if (pop >= 365 && pop < 1100)
{
map.graphics.add(features[i].
setSymbol(fourPopSymbol).setInfoTemplate(resultTemplate));
}
else
{
map.graphics.add(features[i].
setSymbol(fivePopSymbol).setInfoTemplate(resultTemplate));
}
دکمهی run را بزنید خروجی مطابق تصویر زیر نشان داده میشود.
فایل کد این فصل با نام graphicexercise.html درون پوشهی موجود در DVD ضمیمهی کتاب وجود دارد. از این فایل برای صحت کدی که نوشته اید استفاده کنید.
برگرفته از کتاب تولید و طراحی اپلیکیشن های Web GIS و Mobile GIS با استفاده از ArcGIS API for JavaScript
نویسنده: دکتر محمد بافقی زاده
نشر: انتشارات اکادمیک