统计专题图


统计专题图是通过为每个要素绘制统计图来反映其对应的专题值大小的一种专题图。统计专题图是统计图表应用在地图上的结果。

统计专题图可以基于多个变量,反映多种属性,即可以将多个专题值绘制在一个统计图上。通过统计专题图可以在区域本身与各区域之间形成横向和纵向的对比。常见的统计专题图有面积图、柱状图、折线图、饼图、点状图、环状图、玫瑰图、三维饼图、三维柱状图、三维玫瑰图等。

服务器端和客户端均可以制作统计专题图。服务器端制作的专题图以图片的形式加载到地图上,是静态的;而客户端专题图则是“动态”的,具有鼠标交互效果,如hover时高亮,点击时弹出信息框等,因此相对更灵活。 本节将分别以服务器端和客户端两种方式制作统计专题图中的三维柱状图(Bar3D)。

服务器端制作3D柱状图

使用服务器端的REST地图服务制作专题图,则可以通过iClient的SuperMap.REST.ThemeGraph来调用服务,通过ThemeGraphType指定统计图的类型,如SuperMap.REST.ThemeGraphType.BAR3D。

Step1 初始化地图

var map, local, baseLayer, layersID, themeLayer,
        url = "http://www.supermapol.com/iserver/services/map_City5/rest/maps/京津地区地图";
var value="IbooSg6gIBmhIRaesVgjSED0",
        name = "ak";
SuperMap.Credential.CREDENTIAL = new SuperMap.Credential(value, "ak");
function init(){
    map = new SuperMap.Map("map",{controls: [
        new SuperMap.Control.LayerSwitcher(),
        new SuperMap.Control.ScaleLine(),
        new SuperMap.Control.Zoom(),
        new SuperMap.Control.Navigation({
            dragPanOptions: {
                enableKinetic: true
            }
        })]
                                                             });
    baseLayer = new SuperMap.Layer.TiledDynamicRESTLayer("京津地区地图", url, {transparent: true, cacheEnabled: true}, {maxResolution:"auto"});
    baseLayer.events.on({"layerInitialized":addLayer});
}
function addLayer() {
    map.addLayer(baseLayer);
    map.setCenter(new SuperMap.LonLat(117, 40), 0);
    map.allOverlays = true;
}

Step2 定义样式制作统计专题图BAR3D

//对 Jingjin 数据源的 BaseMap_R 数据集两个字段 Pop_Rate95 和 Pop_Rate99 制作统计专题图
function addThemeGraph() {
    removeTheme();
    //创建统计专题图对象,ThemeGraph 必设 items。
    //专题图参数 ThemeParameters 必设 theme(即以设置好的分段专题图对象)、dataSourceName 和 datasetName
    var style1 = new SuperMap.REST.ServerStyle({
        fillForeColor: new SuperMap.REST.ServerColor(92,73,234),
        lineWidth: 0.1
    }),
            style2 = new SuperMap.REST.ServerStyle({
                fillForeColor: new SuperMap.REST.ServerColor(211,111,240),
                lineWidth: 0.1
            }),
            item1 = new SuperMap.REST.ThemeGraphItem({
                caption: "1992-1995人口增长率",
                graphExpression: "Pop_Rate95",
                uniformStyle: style1
            }),
            item2 = new SuperMap.REST.ThemeGraphItem({
                caption: "1995-1999人口增长率",
                graphExpression: "Pop_Rate99",
                uniformStyle: style2
            }),
            themeGraph  = new SuperMap.REST.ThemeGraph({
                items: new Array(item1,item2),
                barWidth: 0.03,
                graduatedMode: SuperMap.REST.GraduatedMode.SQUAREROOT,
                graphAxes: new SuperMap.REST.ThemeGraphAxes({
                    axesDisplayed: true
                }),
                graphSize: new SuperMap.REST.ThemeGraphSize({
                    maxGraphSize: 1,
                    minGraphSize: 0.35
                }),
                graphText: new SuperMap.REST.ThemeGraphText({
                    graphTextDisplayed: true,
                    graphTextFormat: SuperMap.REST.ThemeGraphTextFormat.VALUE,
                    graphTextStyle: new SuperMap.REST.ServerTextStyle({
                        sizeFixed: true,
                        fontHeight: 9,
                        fontWidth: 5
                    })
                }),
                graphType: SuperMap.REST.ThemeGraphType.BAR3D
            }),

            //专题图参数对象
            themeParameters = new SuperMap.REST.ThemeParameters({
                themes: [themeGraph],
                dataSourceNames: ["Jingjin"],
                datasetNames: ["BaseMap_R"]
            }),

            //与服务端交互
            themeService=new SuperMap.REST.ThemeService(url, {
                eventListeners: {
                    "processCompleted": ThemeCompleted,
                    "processFailed": themeFailed
                }
            });
    themeService.processAsync(themeParameters);
}

Step3 把制作的专题图添加到地图上


//显示专题图。专题图在服务端为一个资源,每个资源都有一个 ID 号和一个 url
//要显示专题图即将资源结果的 ID 号赋值给图层的 layersID 属性即可
function ThemeCompleted(themeEventArgs){
    if (themeEventArgs.result.resourceInfo.id){
        themeLayer = new SuperMap.Layer.TiledDynamicRESTLayer("京津地区人口分布专题图",
                                                                                                                    url, {cacheEnabled:false,transparent: true,
                                                                                                                                layersID: themeEventArgs.result.resourceInfo.id}, {maxResolution:"auto"});
        themeLayer.events.on({"layerInitialized":addThemelayer});

    }
}
function addThemelayer() {
    map.addLayer(themeLayer);
}

在线演示与源码编辑

您可以在线访问完整代码、体验演示效果,也可以直接在线编辑源码并实时查看效果。

客户端制作3D柱状图

客户端统计专题图采用了数据驱动的可视化策略,对使用者来说,只需要关注自己需要展示的数据和图表的样式两部分内容。 使用者将自己的 feature 数据添加到统计专题图图层,图层按照图表配置对象 chartSetting 将用户feature数据制作为统计图表,然后在图层中把图表绘制出来。

使用客户端直接制作统计专题图,需要通过统计专题图图层(SuperMap.Layer.Graph)和统计图表抽象模型(SuperMap.Feature.Theme.Graph)来实现。 统计专题图图层使用feature数据制作统计图表的过程中必须要依赖于统计专题要素模型(SuperMap.Feature.Theme.Graph)的可实例化子类, 统计专题要素模型又称为图表模型或图表类)。

SuperMap.Feature.Theme.Graph 是统计专题要素模型的基础抽象模型,它不可被实例化,它的可实例化子类(图表模型/图表类)必须实现 assembleShapes() 接口。

图表类没有加入到iClient产品的库文件中,所以使用客户端统计专题图需要单独引用相应的图表类文件,具体包括:

图表名称 图表类型 类名 文件名
柱状图 Bar uperMap.Feature.Theme.Bar Bar.js
折线图 Line SuperMap.Feature.Theme.Line Line.js
饼图 Pie SuperMap.Feature.Theme.Pie Pie.js
三维柱状图 Bar3D SuperMap.Feature.Theme.Bar3D Bar3D.js
点状图 Point SuperMap.Feature.Theme.Point Point.js
环状图 Ring SuperMap.Feature.Theme.Ring Ring.js

Step1 初始化地图

var map, local, layer, themeLayer,
        url = "http://www.supermapol.com/iserver/services/map_China4003/rest/maps/China_4326";
var value="IbooSg6gIBmhIRaesVgjSED0",
        name = "ak";
SuperMap.Credential.CREDENTIAL = new SuperMap.Credential(value, "ak");

// 初始化信息框 div
var infoDom = document.createElement("div");
infoDom.style.position = "absolute";
infoDom.id = "infowin";

//初始化地图,检查浏览器是否支持Canvas。
function init(){
    // 统计图模块要求浏览器支持 Canvas 渲染
    if(!document.createElement('canvas').getContext){
        alert("您的浏览器不支持 Canvas,请升级!");
        return;
    }

    map = new SuperMap.Map("map",{controls: [
        new SuperMap.Control.LayerSwitcher(),
        new SuperMap.Control.ScaleLine(),
        new SuperMap.Control.Zoom(),
        new SuperMap.Control.Navigation({
            dragPanOptions: {
                enableKinetic: true
            }
        })]
                                                             });
    layer = new SuperMap.Layer.TiledDynamicRESTLayer("China", url, {transparent: true, cacheEnabled: true}, {maxResolution:"auto"});
    layer.events.on({"layerInitialized":addLayer});
    ...
}

Step2 创建统计专题图图层,定义样式Bar3D


    // 创建一个三维柱状图(Bar3D)统计专题图图层
    themeLayer = new SuperMap.Layer.Graph("ThemeLayer", "Bar3D");

    // 指定用于专题图制作的属性字段
    themeLayer.themeFields = ["CON2009", "CON2010", "CON2011", "CON2012", "CON2013"];

    // 配置图表参数
    themeLayer.chartsSetting = {
        // width,height,codomain 分别表示图表宽、高、数据值域;此三项参数为必设参数
        width: 260,
        height: 120,
        codomain: [0, 40000], // 允许图表展示的值域范围,此范围外的数据将不制作图表
        // 3d 柱条正面样式(3d 柱条的侧面和顶面会以 3d 柱条正面样式为默认样式)
        barFaceStyle: {
            stroke: true
        },
        // 按字段设置 3d 柱条正面样式
        barFaceStyleByFields: [{ fillColor: "#FFB980" }, { fillColor: "#5AB1EF" }, { fillColor: "#B6A2DE" }, { fillColor: "#2EC7C9" }, { fillColor: "#D87A80" }],
        // 3d 柱条正面 hover 样式(3d 柱条的侧面和顶面 hover 会以 3d 柱条正面 hover 样式为默认 hover 样式)
        barFaceHoverStyle: {
            stroke: true,
            strokeWidth: 1,
            strokeColor: "#ffff00"
        },
        xShapeBlank: [15, 15, 15],   // 水平方向上的空白间距参数
        axisYTick: 4,       // y 轴刻度数量
        useXReferenceLine: true,         // 使用参考线
        xReferenceLineStyle: {strokeColor: "#008acd", strokeOpacity: 0.4},         // 参考线样式
        axisYLabels: ["4万", "3万", "2万", "1万", "0"],         // y 轴标签
        axisXLabels: ["09年", "10年", "11年", "12年", "13年"],       // x 轴标签
        backgroundStyle: {         // 背景样式
            fillColor: "#d1eeee",
            shadowBlur: 12,
            shadowColor: "#d1eeee"
        },
        backgroundRadius: [5, 5, 5, 5]       // 背景框圆角参数
    };

    // 注册专题图 mousemove, mouseout事件(注意:专题图图层对象自带 on 函数,没有 events 对象)
    themeLayer.on("mousemove", showInfoWin);
    themeLayer.on("mouseout", closeInfoWin);

    themeLayer.setOpacity(0.9);
}

Step2 创建统计专题图图层,定义样式Bar3D


//构建 feature 数据, 专题图的数据必须是 SuperMap.Feature.Vector
function addThemeLayer() {
    clearThemeLayer();

    var features = [];
    for(var i = 0, len = chinaConsumptionLevel.length; i < len; i++){
        // 省居民消费水平(单位:元)信息
        var provinceInfo = chinaConsumptionLevel[i];
        var geo = new SuperMap.Geometry.Point(provinceInfo[1], provinceInfo[2]);
        var attrs = {};
        attrs.NAME = provinceInfo[0];
        attrs.CON2009 = provinceInfo[3];
        attrs.CON2010 = provinceInfo[4];
        attrs.CON2011 = provinceInfo[5];
        attrs.CON2012 = provinceInfo[6];
        attrs.CON2013 = provinceInfo[7];

        var fea = new SuperMap.Feature.Vector(geo, attrs);
        features.push(fea);
    }

    themeLayer.addFeatures(features);
}

Step2 把底图和专题图层添加到地图上

function addLayer() {
    map.addLayers([layer, themeLayer]);
    map.setCenter(new SuperMap.LonLat(104.067923,34.679943), 1);

Step3 实现点击交互的弹窗效果

// 显示地图弹窗
function showInfoWin(e){
    // e.target 是图形对象,即数据的可视化对象,三维柱状图中是指三维柱条;
    // 图形对象的 refDataID 属性是数据(feature)的 id 属性,它指明图形对象是由那个数据制作而来;
    // 图形对象的 dataInfo 属性是图形对象表示的具体数据,他有两个属性,field 和 value;
    if(e.target && e.target.refDataID && e.target.dataInfo){
        closeInfoWin();
        // 获取图形对应的数据 (feature)
        var fea = themeLayer.getFeatureById(e.target.refDataID);

        var info = e.target.dataInfo;

        // 弹窗内容
        var contentHTML = "<div style='padding: 2px; color: #000; background-color: #d1eeee';'>";
        contentHTML += "<strong>" + fea.attributes.NAME + "</strong>";

        contentHTML += "<hr style='margin: 3px'>";
        switch(info.field){
            case "CON2009":
                contentHTML += "09年居民消费水平 <br/><strong>" + info.value + "</strong>(元)";
                break;
            case "CON2010":
                contentHTML += "10年居民消费水平 <br/><strong>" + info.value + "</strong>(元)";
                break;
            case "CON2011":
                contentHTML += "11年居民消费水平 <br/><strong>" + info.value + "</strong>(元)";
                break;
            case "CON2012":
                contentHTML += "12年居民消费水平 <br/><strong>" + info.value + "</strong>(元)";
                break;
            case "CON2013":
                contentHTML += "13年居民消费水平 <br/><strong>" + info.value + "</strong>(元)";
                break;
            default:
                contentHTML += "No Data";
        }
        contentHTML += "</div>";

        infoDom.style.left = e.event.clientX + 40 + "px";
        infoDom.style.top = e.event.clientY - 25 + "px";
        infoDom.innerHTML = contentHTML;
        document.body.appendChild(infoDom);
    }
}

在线演示与源码编辑

您可以在线访问完整代码、体验演示效果,也可以直接在线编辑源码并实时查看效果。