FK JavaScript之:ArcGIS JavaScript API之地图动画

时间:2021-07-10 16:41:43

地图要素动画应用场景:动态显示地图上的要素的属性随着时间的改变而改变,并根据其属性的变化设置其渲染.比如:某水域项目中,随着时间的变化,动态展现水域的清淤进度

本文目的:对ArcGIS JavaScript 官网示例中的代码进行分析注解.下述代码对官网示例进行了部分调整

示例网址1:

示例网址2:

示例中csv文件

以下为代码注释:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--The viewport meta tag is used to improve the presentation and
behavior of the samples on iOS devices-->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>LLC动态图测试</title>
<link rel="stylesheet" href="http://**.**.**.**/arcgis_js_api/library/3.15/3.15/esri/css/esri.css">
<style>
html, body, #mainWindow {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
} body {
background-color: white;
overflow: hidden;
font-family: "Trebuchet MS";
} #loading {
background: #fff;
height: 100%;
overflow: hidden;
position: absolute;
width: 100%;
z-index: 100;
} #loadingMessage {
color: #000;
margin: 0 auto;
padding: 150px 0 0 0;
text-align: center;
width: 200px;
} .shadow {
-moz-box-shadow: 0 0 5px #888;
-webkit-box-shadow: 0 0 5px #888;
box-shadow: 0 0 5px #888;
} #map {
background-color: white;
} #feedback {
background: #fff;
color: #000;
font-family: arial;
height: auto;
left: 30px;
margin: 5px;
padding: 10px;
position: absolute;
text-align: center;
top: 30px;
visibility: hidden;
width: 200px;
z-index: 10;
} #currentYear {
display: inline-block;
height: 25px;
text-align: center;
width: 50px;
} #play, #pause {
cursor: pointer;
display: none;
width: 50px;
} #legend {
padding: 10px 0 0 0;
} #legend table table td {
text-align: left;
} /* animate color transition when years change */
/*The LLC Guess:the CSS name seems to be useless,maybe you can edit it arbitrary*/
/*以下为地图的显示样式,相关内容查询svg,path[]中的内容,即为要素分类的类别*/
#counties_layer path {
transition: fill 1.15s, fill-opacity 1.15s, stroke 1.15s, stroke-opacity 1.15s;
-webkit-transition: fill 1.15s, fill-opacity 1.15s, stroke 1.15s, stroke-opacity 1.15s;
} #counties_layer path[data-relgrowth="no-data"] {
stroke: rgb(255, 255, 255);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="zero-or-less"] {
fill: rgb(175, 141, 195); /* purple */
fill-opacity: 1;
stroke: rgb(175, 141, 195);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="lt-US"] {
fill: rgb(225, 236, 231); /* light */
fill-opacity: 1;
stroke: rgb(225, 236, 231);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="gt-US"] {
fill: rgb(127, 191, 123); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="llcStyle"] {
fill: rgb(0, 0, 0); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="1"] {
fill: rgb(0, 0, 0); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="2"] {
fill: rgb(255, 0, 0); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="3"] {
fill: rgb(0, 255, 0); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="4"] {
fill: rgb(0, 0, 255); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="5"] {
fill: rgb(255, 255, 0); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
} #counties_layer path[data-relgrowth="6"] {
fill: rgb(0, 255, 255); /* green */
fill-opacity: 1;
stroke: rgb(127, 191, 123);
stroke-width: 1pt;
stroke-opacity: 1;
}
</style> <script type="text/javascript" src="http://**.**.**.**/arcgis_js_api/library/3.15/3.15/init.js"></script>
<script>
require([
"esri/map",
"esri/layers/FeatureLayer",
"esri/dijit/Legend",
"esri/InfoTemplate", "esri/renderers/ClassBreaksRenderer",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol", "dojo/_base/array",
"esri/Color",
"dojo/_base/fx",
"dojo/_base/lang",
"dojo/Deferred", "dojo/dom",
"dojo/dom-construct",
"dojo/dom-style",
"dojo/number",
"dojo/on",
"dojo/parser",
"dojo/string", "dojox/data/CsvStore",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function (Map, FeatureLayer, Legend, InfoTemplate,
ClassBreaksRenderer, SimpleFillSymbol, SimpleLineSymbol,
arrayUtils, Color, fx, lang, Deferred,
dom, domConstruct, domStyle, number, on, parser, string,
CsvStore) {
parser.parse();
var map, layer, currentYear = 1971, currentUSPgr, timer; map = new Map("map", {
basemap: "gray",
center: [120.2, 30.542],
zoom: 11,
slider: false
});
map.on("load", function () {
//加载csv数据.csv中为美国人口数据表,之后通过fip与矢量数据进行关联
loadCSV().then(function (csvData) {
//神奇的JavaScript this. 绑定setYear的上下文对象为csvData,所以,在函数中,this就是csvData
setYear = lang.hitch(csvData, setYear);
//年份设置为1971年
setYear(1971);
//添加图层(该方法大体上相当于将featureLayer与csv中的表进行了连接处理)
layer = addCounties(csvData);
});
}); // set up play/pause buttons
//播放/暂停按钮事件绑定
on(dom.byId("pause"), "click", function () {
domStyle.set(this, "display", "none");
domStyle.set("play", "display", "inline-block");
pause();
});
on(dom.byId("play"), "click", function () {
domStyle.set(this, "display", "none");
domStyle.set("pause", "display", "inline-block");
play();
}); function addCounties(csvData) {
var content = "<b>河流名称</b>: ${河流名称} \
<br><b>清淤量</b>: ${清淤量} \
<br><b>FKRATE</b>: ${rate} "; // \
// <br><National Average: ${NATLAVG}";
var infoTemplate = new InfoTemplate("${河流名称} FK河段", content);
//FeatureLayer URL
var url = "http://**.**.**.**/arcgis/rest/services/DQ/DQDestilingTemp/MapServer/6";
var counties = new FeatureLayer(url,
{
id: "counties",
infoTemplate: infoTemplate,
outFields: ["河流名称", "FID", "SILTVOLUME"],
styling: false
}); counties.on("load", function () {
on.once(counties, "update-end", function () {
//设置地图渲染器,此渲染器不用于地图渲染,只用于生成图例,所以"FID"字段只是写着玩玩
var renderer = createRenderer(currentYear, "FID", csvData);
counties.setRenderer(renderer);
createLegend(counties);
domStyle.set("pause", "display", "inline-block");
//开始动画
play();
});
fadeOutLoading();
}); if (counties.surfaceType === "svg") {
counties.on("graphic-draw", function (evt) {
//下述代码进行要素与csv表的关联操作
var attrs = evt.graphic.attributes;
var joinKey = attrs && attrs.FID; //关联用的字段,先用FID表示了
var relgrowth = "no-data"; if (joinKey && csvData[joinKey] && csvData[joinKey][currentYear]) {
//根据csv表中的数据,获取相应年份的人口数据,计算人口增长率
var countyPgr = getGrowthRate(csvData[joinKey][currentYear - 1], csvData[joinKey][currentYear], 1);
//console.log(countyPgr);
//根据增长率的不同,进行分类渲染
if (countyPgr <= 0.5 && countyPgr > 0)
relgrowth = "1";
else if (countyPgr > 0.5 && countyPgr <= 1)
relgrowth = "2";
else if (countyPgr > 1 && countyPgr <= 1.25)
relgrowth = "3";
else if (countyPgr > 1.25 && countyPgr <= 1.5)
relgrowth = "4";
else if (countyPgr > -5 && countyPgr <= -0.5)
relgrowth = "5";
else
relgrowth = "6";
}
var qyl;
if (joinKey != undefined && csvData[joinKey] != undefined && csvData[joinKey][currentYear] != undefined)
qyl = csvData[joinKey][currentYear];
//此处可以将某年某月的数据关联到图层的属性中
attrs.清淤量 = qyl;
attrs.rate = countyPgr;
//此处是配色的关键字段!此处内容与上面配置的样式表相对应
evt.graphic.getNode().setAttribute("data-relgrowth", relgrowth);
});
} map.addLayer(counties);
return counties;
} function loadCSV() {
//加载csv中的数据.可以略过,处理结果就是将csv中的表加载到了csvData中,其他函数可以根据FID,时间获取某年月的数据
var dfd = new Deferred(); var csvStore = new CsvStore({
url: "DesiltingTemp.csv"
}); csvStore.fetch({
onComplete: function (items, request) { //process csv data and create in memory object store.
var store = request.store;
var minYearPopulation = 1970;
var maxYearPopulation = 2006;
var counties = {}; counties.minVal = Infinity;
counties.maxVal = -Infinity; arrayUtils.forEach(items, function (item) {
//var countyFips = store.getValue(item, "county_fips");
//var stateFips = store.getValue(item, "state_fips");
//var fips = string.pad(stateFips, 2, "0") + string.pad(countyFips, 3, "0");
var fips = store.getValue(item, "FID");
var population = {}; population.maxVal = -Infinity; for (var year = minYearPopulation; year <= maxYearPopulation; year++) {
var fieldName = "pop" + year;
var popValue = parseInt(store.getValue(item, fieldName), 10);
population[year] = popValue;
population.maxVal = (popValue > population.maxVal) ? popValue : population.maxVal;
counties.minVal = (popValue < counties.minVal) ? popValue : counties.minVal;
counties.maxVal = (popValue > counties.maxVal) ? popValue : counties.maxVal;
} counties[fips] = population;
});
dfd.resolve(counties);
},
onError: function (err) {
console.log("Error loading CSV: ", err.message, err);
}
});
return dfd;
} function getGrowthRate(pt1, pt2, t2_t1) {
return ((Math.log(pt2) - Math.log(pt1)) / (t2_t1)) * 100;
} function setYear(year) {
//设置当前年份
//由于函数调用时有如下代码setYear = lang.hitch(csvData, setYear); so this就是csvData
var csvData = this;
currentYear = year;
currentUSPgr = getGrowthRate(csvData["0"][currentYear - 1], csvData["0"][currentYear], 1);
dom.byId("currentYear").innerHTML = currentYear; if (layer) {
layer.renderer._currentYear = year;
//添加renderer分类对象,对分类渲染来说没有实际意义
addBreaks(layer.renderer);
//重绘.根据官网资料,该方法不通过服务器重绘
layer.redraw();
//恢复之前的地图弹窗
var sel = map.infoWindow.getSelectedFeature();
if (sel && map.infoWindow.isShowing) {
map.infoWindow.setFeatures([sel]);
}
}
} function changeYear(incr) {
//更改地图的当前年份
var year;
if (incr < 1) {
year = (currentYear === 1971) ? 2006 : currentYear + incr;
setYear(year);
}
else if (incr > 0) {
year = (currentYear === 2006) ? 1971 : currentYear + incr;
setYear(year);
}
} function play() {
//动画播放
if (!timer) {
timer = setInterval(function () {
changeYear(1);
}, 1250);
}
} function pause() {
clearInterval(timer);
timer = null;
} function createRenderer(startYear, joinField, data) {
// renderer is used for the legend
//The LLC Says:This Method is only used for the legend,actually,the breaks info of the renderer is not used for the layer to display.
//so the attibuteField of the ClassBreaksRenderer is meaningless
//var tColor=[0,0,0];
//该Renderer只用来生成图例,不用以分类渲染
var renderer = new ClassBreaksRenderer(null, "FID");
renderer._currentYear = startYear;
renderer._data = data;
addBreaks(renderer);
// console.log("renderer with breaks", renderer);
return renderer;
} function createLegend(layer) {
//创建图例
var legendDijit = new Legend({
map: map,
layerInfos: [
{
"layer": layer,
"title": "Population Change"
}
]
}, "legend");
legendDijit.startup();
domStyle.set("feedback", "visibility", "visible");
} function addBreaks(renderer) {
// console.log("addBreaks", renderer);
var currentYear = renderer._currentYear,
data = renderer._data,
totalGrowth = getGrowthRate(data['0'][currentYear], data['0'][currentYear - 1], 1),
roundedTotalGrowth = number.round(totalGrowth, 2); renderer.clearBreaks(); var negative = [175, 141, 195];
var flat = [20, 236, 231];
var positive = [127, 191, 123]; renderer.addBreak({
minValue: -Infinity,
maxValue: 0,
symbol: new SimpleFillSymbol().setColor(new Color(negative))
.setOutline(new SimpleLineSymbol().setColor(new Color(negative))),
label: "Decrease"
}); renderer.addBreak({
minValue: 0,
maxValue: roundedTotalGrowth,
symbol: new SimpleFillSymbol().setColor(new Color(flat))
.setOutline(new SimpleLineSymbol().setColor(new Color(flat))),
label: "Flat"
}); renderer.addBreak({
minValue: roundedTotalGrowth,
maxValue: Infinity,
symbol: new SimpleFillSymbol().setColor(new Color(positive))
.setOutline(new SimpleLineSymbol().setColor(new Color(positive))),
label: "Increase"
});
} function fadeOutLoading() {
var fade = fx.fadeOut({
node: "loading",
onEnd: function () {
domConstruct.destroy(dom.byId("loading"));
}
});
fade.play();
}
});
</script>
</head> <body>
<div id="loading">
<div id="loadingMessage">
正在加载清淤量数据
<br>
<img src="assets/loading_gray_circle.gif">
</div>
</div>
<div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="'design': 'headline', 'gutters': false">
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="'region': 'center'">
<div id="feedback" class="shadow">
Year:
<span id="currentYear">
<img src="assets/loading_gray_circle.gif">
</span>
|
<!--div id="play">></div-->
<span id="play">Play</span>
<!--div id="pause">||</div-->
<span id="pause">Pause</span>
<div id="legend"></div>
</div> </div> <!-- end map div -->
</div> <!-- end border container div -->
</body>
</html>