web前端

arcgis 3x 聚类实现 点击弹出infowindow 附带

2019-12-11  本文已影响0人  channel_puls
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",
    "esri/InfoTemplate",
    "esri/geometry/Extent",
    "dojo/dom-construct",
    "esri/symbols/PictureMarkerSymbol",
    "esri/dijit/InfoWindow"
], function(
    declare, arrayUtils, Color, connect,
    SpatialReference, Point, Graphic, SimpleMarkerSymbol, TextSymbol,
    PopupTemplate, GraphicsLayer,
    InfoTemplate,
    Extent,
    domConstruct,PictureMarkerSymbol,
    InfoWindow
) {
    return declare([GraphicsLayer], {
        constructor: function(options) {
            this._clusterTolerance = options.distance || 50;
            // 页面初始数据
            this._clusterData = options.data || [];
            // 
            this._clusters = [];
            this._clusterLabelColor = options.labelColor || "#000";
            // 标签偏移可以是零,所以处理方式不同
            this._clusterLabelOffset = (options.hasOwnProperty("labelOffset")) ? options.labelOffset : -5;
            this._singles = []; // 在单击图形时填充
            this._showSingles = options.hasOwnProperty("showSingles") ? options.showSingles : true;
            // 表示单个点的图形
            var SMS = SimpleMarkerSymbol;
            this._singleSym = options.singleSymbol || new SMS("circle", 3, null, new Color("#097"));
            this._singleTemplate = options.singleTemplate || new InfoTemplate("Attributes", "{*}");
            this._maxSingles = options.maxSingles || 1000;
            this._webmap = options.hasOwnProperty("webmap") ? options.webmap : false;
            this._sr = options.spatialReference || new SpatialReference({
                "wkid": 4326
            });
            this._zoomEnd = null;
            this._mapclick = null;
        },

        // override esri/layers/GraphicsLayer methods 
        _setMap: function(map, surface) {
            // 计算并设置初始分辨率
            this._clusterResolution = map.extent.getWidth() / map.width; // probably a bad default...
            if(this._zoomEnd==null){this._clusterGraphics();}
            //       连接到onZoomEnd,以便在缩放级别更改时重新聚集数据
            this._zoomEnd = connect.connect(map, "onZoomEnd", this, function() {
                // 更新分辨率
                this._clusterResolution = this._map.extent.getWidth() / this._map.width;
                this.clear();
                this._clusterGraphics();
            });
            // GraphicsLayer将在这里添加自己的侦听器
            var div = this.inherited(arguments);
            return div;
        },

        _unsetMap: function() {
            this.inherited(arguments);
            connect.disconnect(this._zoomEnd);
        },
        // 公共ClusterLayer方法
        add: function(p) {
            //参数是要添加到现有集群中的数据点。如果数据点落在现有集群内,
            // 则将其添加到该集群,并更新集群的标签。如果新点不在现有集群中,则创建一个新集群
            // 如果传递了一个图形,使用GraphicsLayer的add方法
            if (p.declaredClass) {
                this.inherited(arguments);
                return;
            }
            // 将新数据添加到_clusterData中,以便将其包含在集群中

            this._clusterData.push(p);

            var clustered = false;
            //  当地图级别改变时
            // 在现有集群中查找新点
            for (var i = 0; i < this._clusters.length; i++) {
                var c = this._clusters[i];
                // 将该点添加到现有集群
                this._clusterAddPoint(p, c);
                // 更新集群的几何形状
                this._updateClusterGeometry(c);
                // 更新标签
                this._updateLabel(c);
                clustered = true;
            }

            if (!clustered) {
                p.attributes.clusterCount = 1;
                this._clusterCreate(p);
                this._showCluster(p);
            }
        },
        showSingles: function() {
            var singles = [];
            for (var i = 0, il = this._clusterData.length; i < il; i++) {
                singles.push(this._clusterData[i]);
            }
            this._addSingles(singles);
        },
        clear: function() {
            // 摘要:删除所有集群和数据点
            this.inherited(arguments);
            this._clusters.length = 0;
        },
        clearSingles: function(singles) {
            // 摘要:删除表示单个数据点的图形。
            var s = singles || this._singles;
            arrayUtils.forEach(s, function(g) {
                this.remove(g);
            }, this);
            this._singles.length = 0;
        },

        onClick: function(e) {
            // 删除任何以前显示的单一功能
            this._map.infoWindow.resize(440, 350)
            this.clearSingles(this._singles);
            // 查找组成被单击的集群的单个图形
            // would be nice to use filter but performance tanks with large arrays in IE
            var singles = [];
            for (var i = 0, il = this._clusterData.length; i < il; i++) {
                if (e.graphic.attributes.clusterId == this._clusterData[i].attributes.clusterId) {
                    singles.push(this._clusterData[i]);
                }
            }
            if (singles.length > this._maxSingles) {
                alert("Sorry, that cluster contains more than " + this._maxSingles + " points. Zoom in for more detail.");
                return;
            } else {
                e.stopPropagation();
                // 停止从弹出到地图的单击
                if (singles.length == 1) {
                    // 单一的时候
                    // this._map.infoWindow.show(e.graphic.geometry);
                    // this._graphicOnClick(e.graphic.attributes);
                    this._graphicOnClick(e);
                } else if(this._map.getMaxZoom()-this._map.getZoom()>2 && singles.length > 1){
//点击singles时得到符号的extent 然后设置为当前可见范围 放大地图 达到放大地图等级 触发重新渲染点 从而分开点
                    var xmax, ymax, xmin, ymin;
                    xmax = this._find(singles, "x", "max");
                    ymax = this._find(singles, "y", "max");
                    xmin = this._find(singles, "x", "min");
                    ymin = this._find(singles, "y", "min");
                    var extent = new Extent(xmin, ymin, xmax, ymax, this._sr)
                    this._map.setExtent(extent);
                    this._clusterResolution = this._map.extent.getWidth() / this._map.width;
                    this.clear();
                    this._clusterGraphics();
                    this._addSingles(singles);
                }
            }
        },
//如果点前是一个点 则触发此事件
        _graphicOnClick: function(e) {
            var _this = this;
            var id;
            if (e.graphic.attributes.id.id) {
                id = e.graphic.attributes.id.id;
            } else {
                id = e.graphic.attributes.id;
            }
            this.addInfo(id, function(res) {
                // var node = domConstruct.create("div", {
                //  innerHTML: "<div class='content_doms'>" +
                //      "<div class='content_doms_header'>" +
                //      "<table class='table table-bordered table-condensed'><thead><tr class='info'><th>户主姓名</th><th>所在自然村</th><th>本户人数</th><th>联系电话</th></tr></thead>" +
                //      "<tbody><tr><td>" + res.nhFarmerInfo.name + "</td><td>" + res.nhFarmerInfo.naturalvillagename +
                //      "</td><td>" + res.nhFarmerInfo.peoples + "</td><td>" + res.nhFarmerInfo.telephone +
                //      "</td></tr></tbody></table>" +
                //      "</div>" +
                //      "<div class='content_doms_footer'>" + _this.createList(res.nhOutletList) + "<div>" +
                //      "</div>"
                // });
                // 表格生成代码
                var node = domConstruct.create("div", {
                    innerHTML: "<div class='content_doms'>" +
                        "<div class='content_doms_header'>" +
                        // <table class='table table-bordered table-condensed'>" + createTableList(res.nhFarmerInfo) +"</table>
                        generateTable(res.nhFarmerInfo,2)+
                        "</div>" +
                        "<div class='content_doms_footer'>" +createList(res.nhOutletList) + "<div>" +
                        "</div>"
                });
                // var infoTemplate = new InfoTemplate("农户信息", node);
                // 排口信息
                res.id = id;
                // e.graphic.setAttributes(res);
                // e.graphic.setInfoTemplate(infoTemplate);
                _this._map.infoWindow.setTitle("农户信息");
                _this._map.infoWindow.setContent(node);
                _this._map.infoWindow.show(e.graphic.geometry);
            });
        },
        // 查找数组中最大值 或者 最小值 
        _find: function(arr, pro, single) {
            return Math[single].apply(Math, arr.map(function(o) {
                return o[pro]
            }))
        },
        addInfo: function(id, cb) {
            var url ='/hbnhcj/farmer/nhFarmerInfo/getFarmerWithOutlet';
            $ajax(url,"GET",{id:id},function(data){
                cb(data.result)
            });
        },
        // 内部方法 ***************************起点*********************************
        _clusterGraphics: function() {
            // ,遍历这些点
            for (var j = 0, jl = this._clusterData.length; j < jl; j++) {
                // 查看当前特性是否应该添加到集群中
                var point = this._clusterData[j];
                var clustered = false;
                var numClusters = this._clusters.length;
                for (var i = 0; i < this._clusters.length; i++) {

                    // 当前集群
                    var c = this._clusters[i];
                    // 查看是否满足距离公式
                    if (this._clusterTest(point, c)) {
                        // 如果满足 就将当前点添加到
                        this._clusterAddPoint(point, c);
                        clustered = true;
                        break;
                    }
                }

                if (!clustered) {
                    this._clusterCreate(point);
                }
            }
            this._showAllClusters();
        },

        _clusterTest: function(p, cluster) {
            var distance = (
                Math.sqrt(
                    Math.pow((cluster.x - p.x), 2) + Math.pow((cluster.y - p.y), 2)
                ) / this._clusterResolution
            );
            return (distance <= this._clusterTolerance);
        },

        // 应该包括传递给clusterAddPoint的点
        //在现有集群中
        //还为该点提供一个名为clusterId的属性
        //这与它的星系团相对应
        _clusterAddPoint: function(p, cluster) {
            //平均在新的点集群几何
            var count, x, y;
            count = cluster.attributes.clusterCount;
            x = (p.x + (cluster.x * count)) / (count + 1);
            y = (p.y + (cluster.y * count)) / (count + 1);
            cluster.x = x;
            cluster.y = y;

            //构建一个包括集群中所有点的范围
            //扩展只用于调试/测试…该层不使用
            if (p.x < cluster.attributes.extent[0]) {
                cluster.attributes.extent[0] = p.x;
            } else if (p.x > cluster.attributes.extent[2]) {
                cluster.attributes.extent[2] = p.x;
            }
            if (p.y < cluster.attributes.extent[1]) {
                cluster.attributes.extent[1] = p.y;
            } else if (p.y > cluster.attributes.extent[3]) {
                cluster.attributes.extent[3] = p.y;
            }

            // 增加数
            cluster.attributes.clusterCount++;
            // 属性可能不存在
            if (!p.hasOwnProperty("attributes")) {
                p.attributes = {};
            }
            // 给图形一个集群id
            p.attributes.clusterId = cluster.attributes.clusterId;
        },

        //传递给clusterCreate的点不在
        //为层指定的聚类距离
        //为它创建一个新的集群
        _clusterCreate: function(p) {
            var clusterId = this._clusters.length + 1;
            // console.log("cluster create, id is: ", clusterId);
            // p.attributes might be undefined
            //控制台。日志(“集群创建,id是:”,clusterId);
            // p。属性可能未定义
            if (!p.attributes) {
                p.attributes = {};
            }
            p.attributes.clusterId = clusterId;
            // 创建集群
            var cluster = {
                "x": p.x,
                "y": p.y,
                "attributes": {
                    "clusterCount": 1,
                    "clusterId": clusterId,
                    "id": p.attributes,
                    "extent": [p.x, p.y, p.x, p.y]
                }
            };
            this._clusters.push(cluster);
        },
        // 展示所有聚类
        _showAllClusters: function() {
            for (var i = 0, il = this._clusters.length; i < il; i++) {
                var c = this._clusters[i];
                this._showCluster(c);
            }
        },
        // 展示单一聚类
        _showCluster: function(c) {
            // 单一集群  
            console.log(c);

            var point = new Point(c.x, c.y, this._sr);
            this.add(
                new Graphic(
                    point,
                    null,
                    c.attributes
                )
            );
            // 下面的代码用于不使用单点标记集群
            if (c.attributes.clusterCount == 1) {
                return;
            }

            // show number of points in the cluster
            // 显示集群中的点的数量
            var label = new TextSymbol(c.attributes.clusterCount.toString())
                .setColor(new Color(this._clusterLabelColor))
                .setOffset(0, this._clusterLabelOffset);
            this.add(
                new Graphic(
                    point,
                    label,
                    c.attributes
                )
            );
        },

        _addSingles: function(singles) {
            // 向地图添加单个图形
            arrayUtils.forEach(singles, function(p) {
                var g = new Graphic(
                    new Point(p.x, p.y, this._sr),
                    new PictureMarkerSymbol("https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32)
                        .setOffset(0, 15),
                    p.attributes,
                    this._singleTemplate
                );
                this._singles.push(g);
                if (this._showSingles) {
                    this.add(g);
                }
            }, this);
            // this._map.infoWindow.show
            // this._map.infoWindow.setFeatures(this._singles);
        },

        _updateClusterGeometry: function(c) {
            // 查找集群图
            var cg = arrayUtils.filter(this.graphics, function(g) {
                return !g.symbol &&
                    g.attributes.clusterId == c.attributes.clusterId;
            });
            if (cg.length == 1) {
                cg[0].geometry.update(c.x, c.y);
            } else {
                console.log("didn't find exactly one cluster geometry to update: ", cg);
            }
        },

        _updateLabel: function(c) {
            // 查找现有的标签
            var label = arrayUtils.filter(this.graphics, function(g) {
                return g.symbol &&
                    g.symbol.declaredClass == "esri.symbol.TextSymbol" &&
                    g.attributes.clusterId == c.attributes.clusterId;
            });
            if (label.length == 1) {
                // console.log("update label...found: ", label);
                this.remove(label[0]);
                var newLabel = new TextSymbol(c.attributes.clusterCount)
                    .setColor(new Color(this._clusterLabelColor))
                    .setOffset(0, this._clusterLabelOffset);
                this.add(
                    new Graphic(
                        new Point(c.x, c.y, this._sr),
                        newLabel,
                        c.attributes
                    )
                );
                // console.log("updated the label");
            } else {
                console.log("didn't find exactly one label: ", label);
            }
        },

        // debug only...never called by the layer 调试只有……从未被层调用
        _clusterMeta: function() {
            // 打印总功能数
            console.log("Total:  ", this._clusterData.length);

            // 加起来并打印出来
            var count = 0;
            arrayUtils.forEach(this._clusters, function(c) {
                count += c.attributes.clusterCount;
            });
            console.log("In clusters:  ", count);
        }

    });
});

            loadClusterLayer: function(data,map) {
                var photoInfo = {},
                    clusterLayer;
                var wgs = new SpatialReference({
                    "wkid": 4326
                });
                photoInfo.data = array.map(data, function(p) {
                    var latlng = new Point(parseFloat(p.lon), parseFloat(p.lat), wgs);
                    // 转成webMercator坐标系
                    // var webMercator = webMercatorUtils.geographicToWebMercator(latlng);
                    var attributes = {
                        "id": p.id
                    };
                    return {
                        "x": latlng.x,
                        "y": latlng.y,
                        "attributes": attributes
                    };
                });
                var one = new PictureMarkerSymbol("https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32)
                    .setOffset(0, 15);
                // cluster layer that uses OpenLayers style clustering
                clusterLayer = new ClusterLayer({
                    "data": photoInfo.data,
                    "distance": 1,
                    "id": "clusters",
                    "labelColor": "#000",
                    "labelOffset": -5,
                    "resolution":  map.extent.getWidth() / map.width,
                    "singleColor": "#888",
                    "singleTemplate": '',
                    "spatialReference": wgs,
                });
                var defaultSym = new SimpleMarkerSymbol().setSize(4);
                var renderer = new ClassBreaksRenderer(defaultSym, "clusterCount");
                var first = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 50,
                    new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 125, 3, 0.2]), 10),
                    new Color([241, 128, 23, 0.9]));

                var second = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 35,
                    new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([241, 211, 87, 0.6]), 10),
                    new Color([240, 194, 13, 0.9]));

                var third = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 25,
                    new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([181, 226, 140, 0.6]), 10),
                    new Color([110, 204, 57, 0.9]));
                //渲染等级
                renderer.addBreak(0, 1, one);
                renderer.addBreak(2, 3, third);
                renderer.addBreak(4, 20, second);
                renderer.addBreak(21, 100, first);
                clusterLayer.setRenderer(renderer);
                return clusterLayer
            }

添加到地图

//调取api 获取要渲染的点
    this._loadData("460000", 1, 100000, function(data) {
            // 采集信息
            layer = this.loadClusterLayer(data,map);
            layer.setVisibility(layerConfig.visible);
            map.addLayer(layer);
    })
"extras/ClusterLayer",

若你是gis 完整的项目 需要在init.js 设置dojoConfig

   dojoConfig = {
            parseOnLoad: false,
            async: true,
            tlmSiblingOfDojo: false,
            has: {
                'extend-esri': 1
            },
            paths: {
            //我放到了我的项目的根目录下了 若放在服务器根目录下就改为/extras
              extras:"../extras"
            }
        };
sss (2).png
上一篇下一篇

猜你喜欢

热点阅读