九、统计图表专题图
1、引言
统计图表是专题地图中常用的一类符号,用于表示制图要素属性。常用的统计图表类型有直方图、饼图、柱状图、堆叠图等。与之前提到的渲染器不同,在ArcGIS API for Javascript没有直接提供统计图表对应的渲染器,需要我们基于API进行扩展。
扩展思路:借鉴了刘光老师《WebGIS从基础到开发实践》一书提供思路以及编写的CustomModules类包,即: ArcGIS API for Javascript是基于Dojo框架编写,故我们可以使用DojoX Charting的Chart2D、Chart3D图表创建统计图。然后在每个要素中心自定义一个信息窗口,最后在信息窗口添加对应的统计图。
2、CustomModules类包说明
CustomModules类包包括:ChartInfoWindow.js (图表响应地图的放大、缩小、平移等操作)、CustomThme.js(基本的图表样式)、GeometryUtils.js(计算多边形中心的算法,确定信息窗口位置,避免与服务器交互,提高响应速度)。这里我们引用ChartInfoWindow.js和GeometryUtils.js两个类包。
如下图所示,为华东地区各个省份年均收入的直方图专题图,选取了1995、2000、2005年三年的年均收入信息做对比。
3、代码部分
话不多说,直接上完整代码(直方图专题图):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>直方图专题图</title>
<link rel="stylesheet" type="text/css" href="http://localhost/arcgis_js_api/library/3.17/3.17/dijit/themes/claro/claro.css" />
<link rel="stylesheet" type="text/css" href="http://localhost/arcgis_js_api/library/3.17/3.17/esri/css/esri.css" />
<link href="ChartInfoWindow.css" rel="stylesheet" />
<style>
html,body,#map{
padding: 0;
margin: 0;
height: 100%;
width: 100%;
border:0px solid #000;
}
</style>
<script type="text/javascript" src="http://localhost/arcgis_js_api/library/3.17/3.17/init.js"></script>
<script>
require([
"esri/map",
"esri/layers/FeatureLayer",
"esri/layers/ArcGISDynamicMapServiceLayer",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/renderers/SimpleRenderer",
"esri/Color",
"dojo/_base/array",
"dojo/dom-construct",
"dojo/_base/window",
"dojox/charting/Chart2D",
"dojox/charting/plot2d/ClusteredColumns",
"CustomModules/ChartInfoWindow",
"CustomModules/geometryUtils",
"dojo/domReady!"
], function (
Map, FeatureLayer, ArcGISDynamicMapServiceLayer, SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer, Color,
array, domConstruct, win, Chart2D,ClusteredColumns, ChartInfoWindow, geometryUtils
) {
var map = new Map("map", {
basemap:"topo",
center: [118.2, 31.1],
zoom: 6
});
var baseLayer = new ArcGISDynamicMapServiceLayer("http://localhost:6080/arcgis/rest/services/test/huadong/MapServer");
map.addLayer(baseLayer);
//新建feature图层
var featureLayer = new FeatureLayer("http://localhost:6080/arcgis/rest/services/test/huadong/MapServer/0", {
mode: FeatureLayer.MODE_SNAPSHOT,//快照模式
outFields: ["*"]
});
//为featureLayer设置渲染器
var defaultSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_NULL).
setOutline(new SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new Color("#FF8C00"), 1.5));
var renderer = new SimpleRenderer(defaultSymbol);
featureLayer.setRenderer(renderer);
//要素属性值组,多边形中心点point数组
var featureAttrs = [];
var PolygonCenter = [];
//featureLayer图层加载完毕后触发 createChartInfoWindow函数
featureLayer.on("update-end", function (evt) {
var showFields = ["Y1995","Y2000","Y2005"];
//遍历要素获取属性值
array.forEach(featureLayer.graphics, function (graphic) {
var attr = [];
for (var i = 0, j = showFields.length; i < j; i++) {
attr.push(graphic.attributes[showFields[i]]);
}
PolygonCenter.push(geometryUtils.getPolygonCenterPoint(graphic.geometry));
featureAttrs.push(attr);
});
createChartInfoWindow(showFields);
});
map.addLayer(featureLayer);
//创建放置直方图的信息窗口
function createChartInfoWindow(showFields) {
var max = 10000;
var optinalChart = null;
for(var i=0;i<featureAttrs.length;i++){
var infoWindow = new ChartInfoWindow({
domNode: domConstruct.create('div', null, document.getElementById('map'))
});
infoWindow.setMap(map);
//定义图表节点
var nodeChart = null;
nodeChart = domConstruct.create("div", { id: 'nodeColumnChart' + i, style: "width:120px;height:80px;background-color:transparent" }, win.body());
var chart = makeChart(nodeChart,showFields,max,i); //绘制直方图
infoWindow.resize(122, 82);
//读取几何的中心位置,放置图表信息框
var Cpoint = PolygonCenter[i];
infoWindow.setContent(nodeChart);
infoWindow.__mcoords = Cpoint;
infoWindow.show(map.toScreen(Cpoint));
}
}
//在信息窗口框绘制直方图
function makeChart(nodeChart,showFields, max, index) {
//初始化一个chart2D变量
var chart = new Chart2D(nodeChart,{margins: { l: 6, r: 0, t: 2, b: 0 }});
chart.addPlot("default", {type: "Columns",gap:0});
chart.addAxis("x", { fixLower: "major", fixUpper: "major",
labels: [{ value: 0, text: " " },{ value: 1, text: " " },{ value: 2, text: " " },{ value: 3, text: " " }, { value: 4, text: " " }],
fontColor: "black",
majorTick: { color: "black", length: 0},
minorTick: { stroke: "black", length: 0}
});
chart.addAxis("y", { vertical: true, fixLower: "major", fixUpper: "major",
min: 0,to: max, //刻度最小最大允许值
fontColor: "black",
font: "normal normal bold 6pt Tahoma",
majorTick: { color: "black", length: 0}, //刻度线设置
minorTick: { stroke: "black", length: 0}
});
//定义矩形颜色
var ColorArr=[new Color([48,169,208,1]),new Color([255,180,0,1]),new Color([62,193,121,1])];
//循环featureAttrs添加直方图属性数据
var length = showFields.length;
for (var i = 0; i < length; i++) {
serieValues = [];
for (var m = 0; m < i; m++) {
serieValues.push(0);
}
serieValues.push(featureAttrs[index][i]);
console.log(serieValues);
chart.addSeries(showFields[i], serieValues, { stroke: { color: "#666", width:0},fill: ColorArr[i]});
}
chart.render();
return chart;
}
});
</script>
</head>
<body class="claro">
<div id="map" ></div>
</body>
</html>
其他几种专题图的实现与直方图类似,不同的是绘制统计图表的函数不同。下面分别贴上各种图表的绘制函数:
饼图 (需添加引用 dojox/charting/plot2d/Pie 类)
function makeChart(nodeChart,showFields, index) {
//初始化Pie图表变量
var chart = new Chart2D(nodeChart,{margins: { l: 0, r: 0, t: 0, b: 0 }});
chart.addPlot("default", {type: "Pie",font: "normal normal 6pt Tahoma",fontColor: "#fff",labelOffset: 0,radius: 25});
//添加attributes属性
chart.addSeries("all",[
{ y:featureAttrs[index][0], text: "", stroke: "#555",fill:new Color([255,180,0,1]) },
{ y:featureAttrs[index][1], text: "", stroke: "#555",fill:new Color([48,169,208,1]) },
{ y:featureAttrs[index][2], text: "", stroke: "#555",fill:new Color([62,193,121,1]) }
]);
chart.render();
return chart;
}
堆叠图 (需添加引用 dojox/charting/plot2d/StackedColumns 类)
function makeChart(nodeChart,showFields, max, index) {
//初始化StackedColumnsChart
var chart = new Chart2D(nodeChart,{margins: { l: 0, r: 0, t: 2, b: 0 }});
chart.addPlot("default", {type: "StackedColumns",gap:0});
chart.addAxis("y", { vertical: true, fixLower: "major", fixUpper: "major",
min: 0,to: max, //刻度最大允许值
fontColor: "black",
font: "normal normal 0pt Tahoma"
});
//定义矩形颜色
var ColorArr=[new Color([255,50,0,1]),new Color([255,150,0,1]),new Color([255,255,0,1]),new Color([0,240,50,1]),new Color([0,205,150,1]),new Color([0,150,255,1])];
var length = showFields.length;
for (var i = 0; i < length; i++) {
serieValues = [];
serieValues.push(featureAttrs[index][i]);
chart.addSeries(showFields[i], serieValues, { stroke: { color: "#fff", width:0},fill: ColorArr[i]});
}
chart.render();
return chart;
}
柱状图 (需添加引用 dojox/charting/Chart3D、dojox/charting/plot3d/Bars、dojox/gfx3d/matrix 类)
function makeChart(nodeChart,showFields, max, index) {
//初始化 一个chart变量
var chart3d = new Chart3D('chart3d'+index,{
lights: [{direction: {x: 5, y: 5, z: -5}, color: "white"}],
ambient: {color:"white", intensity: 2},
specular: "white"
},
[Matrix.cameraRotateXg(15), Matrix.cameraRotateYg(-10), Matrix.scale(0.5), Matrix.cameraTranslate(-50, 50, 0)]
);
//定义矩形颜色
var ColorArr=[new Color([0,169,208,1]),new Color([255,160,0,1]),new Color([220,55,121,1])];
//featureAttrs 设置为直方图的"柱"
var length = showFields.length;
var plot1 = new dojox.charting.plot3d.Bars(120, 120,
{gap: 6, material: ColorArr[0]});
plot1.setData([featureAttrs[index][0],0,0]);
chart3d.addPlot(plot1);
var plot2 = new dojox.charting.plot3d.Bars(120, 120,
{gap: 6, material: ColorArr[1]});
plot2.setData([0,featureAttrs[index][1],0]);
chart3d.addPlot(plot2);
var plot3 = new dojox.charting.plot3d.Bars(120, 120,
{gap: 6, material: ColorArr[2]});
plot3.setData([0,0,featureAttrs[index][2]]);
chart3d.addPlot(plot3);
chart3d.generate().render();
return chart3d;
}
更多关于Dojo图表的相关内容,请戳官方文档说明