Arcgis for JS扩展GraphicLayer实现区域对象的聚类统计与展示

功能需求:

分省市统计并展示全国雨量站的数目与位置。

常规做法:

分省市雨量站的数目通过统计表的形式在页面端展示,位置根据XY坐标信息将雨量站标绘在图上。

优化做法:

去掉统计图的展示方式,直接将各省市雨量站的数量信息与位置信息展示在图上,如下图所示:

雨量站的分省市统计与展示

处理思路:

首先,提取各省/市的中心点或者省会城市X与Y坐标信息,在本实例中使用的是省会城市的XY坐标信息,用来显示各省市雨量站的分布。

接着,分省/市统计各省市雨量站的个数,并将其根据个数分颜色、大小将其展示在图上。

最后,点击单个圆圈在地图上标绘详细的雨量站的位置信息,并将其缩放至该省/市。

解决问题:

统计信息的清晰展示与数据的请求速度。

比较:

优化做法直接将统计信息与位置信息展示在地图上,在视觉效果上,提高了地图的交互性与美观程度,简单明了;在数据请求上,优化做法只需统计个数,不需要详细的信息,更不需要将所有的站点在地图上展示,每点击一次,再去请求数据,大大提高了程序的效率与速度。

实现代码:

1、数据

首先,在数据库中查询分省市雨量站的统计情况,返回JSON格式的到前台,数据格式如下:

[
	{id:1,name:"1",x:1,y:1,count:10},
	{id:2,name:"2",x:2,y:2,count:20},
	{id:3,name:"3",x:3,y:3,count:30},
	{……}
	{id:n,name:"n",x:n,y:n,count:n}
]

接着,点击每一个点的时候去请求该省/市的详细雨量站的信息,返回的依然是JSOn格式的,格式如上。

2、扩展GraphicLayer

为了操作方便,将GraphicLayer进行了扩展,扩展的时候主要有以下几个主要点:a、将统计数按照XY坐标展示在图上;b、点击单个点的时候标绘详细的雨量站的位置分布信息。

源代码如下:

define([
    "dojo/_base/declare",
    "dojo/_base/array",
    "esri/Color",
    "dojo/_base/connect",

    "esri/SpatialReference",
    "esri/geometry/Point",
    "esri/graphic",
    "esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/TextSymbol",

    "esri/dijit/PopupTemplate",
    "esri/layers/GraphicsLayer"
], function (
    declare, arrayUtils, Color, connect,
    SpatialReference, Point, Graphic, SimpleMarkerSymbol, TextSymbol,
    PopupTemplate, GraphicsLayer
    ) {
    return declare([GraphicsLayer], {
        constructor: function(options) {
            // 参数:
            //   data:  Object[]
            //     Array of objects. Required. Object are required to have properties named x, y and attributes. The x and y coordinates have to be numbers that represent a points coordinates.
            //   field:  string?
            //     The field of cluster.
            //   showSingles:  Boolean?
            //     Optional. Whether or graphics should be displayed when a cluster graphic is clicked. Default is true.
            //   labelColor:  String?
            //     Optional. Hex string or array of rgba values used as the color for cluster labels. Default value is #fff (white).
            //   labelOffset:  String?
            //     Optional. Number of pixels to shift a cluster label vertically. Defaults to -5 to align labels with circle symbols. Does not work in IE.
            //   singleSymbol:  MarkerSymbol?
            //     Marker Symbol (picture or simple). Optional. Symbol to use for graphics that represent single points. Default is a small gray SimpleMarkerSymbol.
            //   spatialReference:  SpatialReference?
            //     Optional. Spatial reference for all graphics in the layer. This has to match the spatial reference of the map. Default is 102100. Omit this if the map uses basemaps in web mercator.
            //   singleTemplate:  PopupTemplate?
            //     PopupTemplate</a>. Optional. Popup template used to format attributes for graphics that represent single points. Default shows all attributes as "attribute = value" (not recommended).

            //聚类数据
            this._clusterData = options.data || [];
            this._clusters = [];
            //标注颜色,默认为白色
            this._clusterLabelColor = options.labelColor || "#000";
            //标注偏移,默认为-5
            this._clusterLabelOffset = (options.hasOwnProperty("labelOffset")) ? options.labelOffset : -5;

            this._showSingles = options.hasOwnProperty("showSingles") ? options.showSingles : true;
            //单个对象
            this._singles = []; //点击时出现
            // 单个的样式
            var SMS = SimpleMarkerSymbol;
            this._singleSym = options.singleSymbol || new SMS("circle", 6, null, new Color(options.singleColor,0.6));
            //空间参考
            this._sr = options.spatialReference || new SpatialReference({ "wkid": 4326 });

            this._singleTemplate = options.singleTemplate || new PopupTemplate({ "title": "", "description": "{*}" });
        },
        // 重构esri/layers/GraphicsLayer方法
        _setMap: function(map, surface) {
            this._clusterGraphics();
            // GraphicsLayer will add its own listener here
            var div = this.inherited(arguments);
            return div;
        },
        _unsetMap: function() {
            this.inherited(arguments);
        },
        clearSingles: function(singles) {
            // Summary:  Remove graphics that represent individual data points.
            var s = singles || this._singles;
            console.log(s);
            arrayUtils.forEach(s, function(g) {
                console.log(g);
                this.remove(g);
            }, this);
            this._singles.length = 0;
        },
        onClick: function(e) {
            // stop the click from bubbling to the map
            e.stopPropagation();
            this.clearSingles(this._singles);
            var g = e.graphic;
            console.log(g);
            var sonData = city;
            for(var i= 0,  sl=sonData.length;i<sl;i++){
                if(sonData[i].propy===g.attributes.propy){
                    var pt = new Point(sonData[i].x,sonData[i].y, this._sr);
                    var sg = new Graphic(pt, this._singleSym, sonData[i], this._singleTemplate);
                    clusterLayer.add(sg);
                    this._singles.push(sg);
                }
            }
            map.infoWindow.setFeatures(this._singles);
            map.infoWindow.show(g.geometry);
        },
        //添加聚类图形
        _clusterGraphics: function(){
            for(var i= 0, jl=this._clusterData.length;i<jl;i++){
                var point = this._clusterData[i];
                this._addPoint(point);
            }
        },
        //添加点
        _addPoint: function(p){
            var pt = new Point(p.x, p.y,this._sr);
            this.add(
                new Graphic(
                    pt,
                    null,
                    p
                )
            );
            if(p.pcitycount>1){
                // show number of points in the cluster
                var font  = new esri.symbol.Font()
                    .setSize("10pt")
                    .setWeight(esri.symbol.Font.WEIGHT_BOLD);
                var label = new TextSymbol(p.pcitycount)
                    .setColor(new Color(this._clusterLabelColor))
                    .setOffset(0, this._clusterLabelOffset)
                    .setFont(font);
                this.add(
                    new Graphic(
                        pt,
                        label,
                        p
                    )
                );
            }
        }
    });
});

3、在程序中导入包,并引用

        var dojoConfig = {
            paths: {
                extras: location.pathname.replace(/\/[^/]+$/, "") + "/extras"
            }
        };

引用的方式为:

        require([
            ......,
            "extras/ZonalClusterLayer",
            "dojo/domReady!"
        ], function(
            ......,
            ZonalClusterLayer
        ){

4、新建ZonalClusterLayer,分类进行渲染,并将之添加到地图上。

                clusterLayer = new ZonalClusterLayer({
                    "data": capital,
                    "id": "clusters",
                    "labelColor": "#fff",
                    "labelOffset": -4,
                    "singleColor": "#0ff"
                });
                var defaultSym = new SimpleMarkerSymbol().setSize(4);
                var renderer = new ClassBreaksRenderer(defaultSym, "pcitycount");

                /*var picBaseUrl = "images/";
                 var blue = new PictureMarkerSymbol(picBaseUrl + "BluePin1LargeB.png", 32, 32).setOffset(0, 15);
                 var green = new PictureMarkerSymbol(picBaseUrl + "GreenPin1LargeB.png", 64, 64).setOffset(0, 15);
                 var red = new PictureMarkerSymbol(picBaseUrl + "RedPin1LargeB.png", 80, 80).setOffset(0, 15);*/
                var style1 = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                                new Color([255,200,0]), 1),
                        new Color([255,200,0,0.8]));
                var style2 = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 16,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                                new Color([255,125,3]), 1),
                        new Color([255,125,3,0.8]));
                var style3 = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 18,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                                new Color([255,23,58]), 1),
                        new Color([255,23,58,0.8]));
                var style4 = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 20,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                                new Color([204,0,184]), 1),
                        new Color([204,0,184,0.8]));
                var style5 = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 22,
                        new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                                new Color([0,0,255]), 1),
                        new Color([0,0,255,0.8]));
                renderer.addBreak(0, 2, style1);
                renderer.addBreak(2, 5, style2);
                renderer.addBreak(5, 10, style3);
                renderer.addBreak(10, 15, style4);
                renderer.addBreak(15, 20, style5);

                clusterLayer.setRenderer(renderer);
                map.addLayer(clusterLayer);

5、一些无关紧要的东西

在地图上点击,清楚详细结果:

                // close the info window when the map is clicked
                map.on("click", cleanUp);
                // close the info window when esc is pressed
                map.on("key-down", function(e) {
                    if (e.keyCode === 27) {
                        cleanUp();
                    }
                });
            function cleanUp() {
                map.infoWindow.hide();
                clusterLayer.clearSingles();
            }

源码下载

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员互动联盟

【专业文章】六种常见的HTML5写法误用(二)

四、figure元素的常见错误 figure以及figcaption的正确使用,确实是难以驾驭。让我们来看看一些常见的错误, 不是所有的图片都是figure 上...

29650
来自专栏24K纯开源

ChartDirector应用笔记(一)

ChartDirector介绍 ChartDirector是一款小巧精细的商业图表库。其适用的语言范围非常广泛,包括.Net, Java, Asp, VB, ...

27570
来自专栏林德熙的博客

WPF 使用 SharpDX

先介绍一下 SharpDx ,一个底层封装的 DirectX 库,支持 AnyCpu ,支持 Direct3D9, Direct3D11, Direct3D12...

24310
来自专栏葡萄城控件技术团队

前端代码标准最佳实践:CSS篇

上一篇《前端代码标准最佳实践:javascript》发表后,大家讨论还是很热烈,从侧面体现了前端工程师对写标准的前端代码的重视程度很高。这些最佳标准实践并不是那...

230100
来自专栏猿说1024

Markdown 语法

16740
来自专栏阿凯的Excel

动态显示下拉框内容

过了冬至,你在北方瑟瑟发抖,我在广东秋风瑟瑟~ 最近小编经常梦回母校~放一张母校的美图! 年底了,又到了预订报刊的时候! 肯定有人会问,这年头还有谁看报刊...

31230
来自专栏葡萄城控件技术团队

WPF/Silverlight Layout 系统概述——Arrange

上一篇我们介绍了WPF/Silverlight Layout系统的Measure过程,本文将继续介绍Arrange过程。 Arrange过程概述 普通基类属性对...

21190
来自专栏Coding迪斯尼

VUE+WebPack前端游戏设计:实现外星人的动态下滑特效

12320
来自专栏偏前端工程师的驿站

动手写个数字输入框1:input[type=number]的遗憾

前言  最近在用Polymer封装纯数字的输入框,开发过程中发现不少坑,也有很多值得研究的地方。本系列打算分4篇来叙述这段可歌可泣的踩坑经历: 《动手写个数字输...

29050
来自专栏JackieZheng

可视化工具solo show-----Prefuse自带例子GraphView讲解

  2014.10.15日以来的一个月,挤破了头、跑断了腿、伤透了心、吃够了全国最大餐饮连锁店——沙县小吃。其中酸甜苦辣,绝不是三言两语能够说得清道的明的。校招...

51660

扫码关注云+社区

领取腾讯云代金券