依舊是使用Geoprocessor來分析熱點(密度),不過使用了submitJob()這個異步操作方法,有别于execute()這個同步操作方法。
這個就頗有插值分析的樣子了。也可以說是密度分析。做出來就是一個熱力地圖的樣子。
比如,人口密度,降雨分布等。這都可以由這個例子做出來類似的。
由于上一篇已經介紹過Geoprocessor類和ParameterValue類了,是以這節就略去這些内容。想知道的同學可以點選這裡,看上一篇相關内容。
與上一節不同的是,使用的不是execute()方法了,而是submitJob()方法,這是一個異步操作方法。盡管他們傳回的類型是類似的。
官方給的解釋很簡潔明了,有了前幾個的基礎幾乎可以瞬間抓住重點,如submitJob的參數的擷取,對熱力圖結果如何擷取和處理等,自行查詢API即可。
我這篇部落格則是對這個例子進行重點全解析。如果是老鳥,請直接看:How it works
看看結果
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLzEzN5IzNygDMy0CM1UjNwcTMxIDOwQDM3EDMy0CN3AzN5ATMvwFNwcTMwIzLcRzNwcTOwEzLcd2bsJ2Lc12bj5ycn9Gbi52YuUTMwIzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
給定一個時間範圍,就能查詢該地區報警的頻率。這裡使用了圖例這個widget,對其有讀寫操作。圖中預設的時間按下紅色按鈕後,就可以看到如圖的結果(3-5s)。
最中央紅色區域是報警最頻繁的區域,點狀符号代表報警的時間(星期幾)。
據說這個例子有點長,加油。
給出引用
require([
"esri/Map",
"esri/views/MapView",
"esri/tasks/Geoprocessor",
"esri/widgets/Legend",
"esri/widgets/Spinner",
"esri/layers/support/ImageParameters",
"dijit/form/DateTextBox",
"dojo/dom",
"dojo/dom-construct",
"dojo/on",
"dojo/date/locale",
"dojo/parser",
"dijit/registry",
"dojo/domReady!"
],
function(Map, MapView, Geoprocessor, Legend, Spinner, ImageParameters,
DateTextBox, dom, domConstruct, on, locale, parser, registry) {
...
}
);
dijit這個東西是第三方控件(貌似),看DateTextBox就知道了。AJS4.x除了dojo也有用dijit(不明白為啥名字那麼奇怪)
三個新鮮的玩意兒:Legend、Spinner和ImageParameters。
函數骨架
function(...){
parser.parse();//不知道幹啥用的
on(dom.byId("hotspotButton"), "click", findHotspot);
var map = new Map({...});
var view = new MapView({...});
//執行個體化GP
var gpUrl = ".../GPServer/XXX";//省略,但是還是GPServer
var gp = new Geoprocessor(gpUrl);
gp.outSpatialReference = {...}
//圖例
var legend = new Legend({...});
spinner = new Spinner({...});
domConstruct.place(spinner.domNode, view.root);
//資料處理的重點部分,也是官方How it works主要涉及的部分
function findHotspot(){...}
function buildDefinitionQuery(){...}
function cleanup(){...}
function drawResultData(result){...}
//非重點
function progTest(value){...}
function errBack(err){...}
}
按照官方的套路來,會更容易懂。那麼久直接從findHotspot()、buildDefinitionQuery()、cleanup()、drawResultData(result)這四個方法說起吧。
How it works
允許我模仿一回官方的标題~
findHotspot():分析按鈕的click事件,設定gp.submitJob()的參數對象params,并執行分析;在這裡,使用了異步操作分析,終于看到了完整的then寫法。
buildDefinitionQuery():gp.submitJob()的參數對象的生成方法,該方法傳回了一個Object對象,供submitJob()使用。
cleanup():周遊map中的layer,如果發現名字全等于"HotspotLayer",移除。
drawResultData(result):繪制分析結果。
findHotspot()
function findHotspot() {
var params = {
Query: buildDefinitionQuery()
};
cleanup();
spinner.viewModel.point = view.center;
//經典的完整then()寫法
gp.submitJob(params).then(drawResultData, errBack, progTest);
}
通過buildDefinitionQuery()擷取需要的參數。
then寫法,第一個drawResultData()是分析成功時要做的事情:繪制結果;
errBack()是分析失敗要做的事情;
progTest()則是測試分析進展。
後兩個比較簡單,這樣的寫法類似try catch異常處理。
buildDefinitionQuery()
function buildDefinitionQuery() {
var defQuery;
var startDate = locale.format(registry.byId('fromDate').value, {
datePattern: 'yyyy-MM-dd hh:mm:ss',
selector: 'date'
});
var endDate = locale.format(registry.byId('toDate').value, {
datePattern: 'yyyy-MM-dd hh:mm:ss',
selector: 'date'
});
var def = [];
def.push("(Date >= date '" + startDate + "' and Date <= date '" +
endDate + "')");
def.push(
"(Day = 'SUN' OR Day= 'SAT' OR Day = 'FRI' OR Day ='MON' OR Day='TUE' OR Day='WED' OR Day ='THU')"
);
if (def.length > 1) {
defQuery = def.join(" AND ");
}
return defQuery;
}
buildDefinitionQuery()方法
使用locale.format方法擷取時間控件上的時間,分别為startDate和endData兩個Object變量;
然後根據日期範圍,設定一組SQL語句(應該是,文法比較怪異),名為def(裝箱為String[])
最後把數組通過AND來連結成一個長字元串,指派給defQuery這個變量,并傳回defQuery變量作為傳回值,也即為submitJob()的參數。
drawResultData(result)
function drawResultData(result) {
var imageParams = new ImageParameters({
format: "png32",
dpi: 300
});
var resultLayer = gp.getResultMapImageLayer(result.jobId);
resultLayer.opacity = 0.7;
resultLayer.title = "HotspotLayer";
map.layers.add(resultLayer);
spinner.viewModel.point = null;
}
ImageParameters這個類是什麼東西完全不知道...new出來完全沒看懂哪裡有用,各位可以試試删除這個執行個體再運作。//懷疑是SDK開發人員忘記删了。
從gp中擷取MapImageLayer,這個getResultMapImageLayer()是個新方法,傳回指定id的MapImageLayer執行個體。這裡傳回的MapImageLayer執行個體名為resultLayer。
設定好透明度和名字後,加入到map的layers中。這就算完成了。
最後再上一張邏輯圖:
至于圖例widget和那個啥spinner就不作為重點啦~有興趣的同學可以深究一下,應該在widget章節有詳細的說明的。
再次感歎then這個東西的強大之處,Promise對異步操作真的太友善了。
總結一下
...???上面那張邏輯圖不就說明了一切嗎???
黑人問号.jpg