arcgis 3x 聚類實現(xiàn) 點擊彈出infowindow 附帶信息 散開點

  • 首先官方也給出了例子 但是這不能滿足我們的需求
    image.png

    改造后 當(dāng)然設(shè)置了他的 renderer 達(dá)到效果


    ss.png
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;
            // 頁面初始數(shù)據(jù)
            this._clusterData = options.data || [];
            // 
            this._clusters = [];
            this._clusterLabelColor = options.labelColor || "#000";
            // 標(biāo)簽偏移可以是零,所以處理方式不同
            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) {
            // 計算并設(shè)置初始分辨率
            this._clusterResolution = map.extent.getWidth() / map.width; // probably a bad default...
            if(this._zoomEnd==null){this._clusterGraphics();}
            //       連接到onZoomEnd,以便在縮放級別更改時重新聚集數(shù)據(jù)
            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) {
            //參數(shù)是要添加到現(xiàn)有集群中的數(shù)據(jù)點。如果數(shù)據(jù)點落在現(xiàn)有集群內(nèi),
            // 則將其添加到該集群,并更新集群的標(biāo)簽。如果新點不在現(xiàn)有集群中,則創(chuàng)建一個新集群
            // 如果傳遞了一個圖形,使用GraphicsLayer的add方法
            if (p.declaredClass) {
                this.inherited(arguments);
                return;
            }
            // 將新數(shù)據(jù)添加到_clusterData中,以便將其包含在集群中

            this._clusterData.push(p);

            var clustered = false;
            //  當(dāng)?shù)貓D級別改變時
            // 在現(xiàn)有集群中查找新點
            for (var i = 0; i < this._clusters.length; i++) {
                var c = this._clusters[i];
                // 將該點添加到現(xiàn)有集群
                this._clusterAddPoint(p, c);
                // 更新集群的幾何形狀
                this._updateClusterGeometry(c);
                // 更新標(biāo)簽
                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() {
            // 摘要:刪除所有集群和數(shù)據(jù)點
            this.inherited(arguments);
            this._clusters.length = 0;
        },
        clearSingles: function(singles) {
            // 摘要:刪除表示單個數(shù)據(jù)點的圖形。
            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 然后設(shè)置為當(dāng)前可見范圍 放大地圖 達(dá)到放大地圖等級 觸發(fā)重新渲染點 從而分開點
                    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);
                }
            }
        },
//如果點前是一個點 則觸發(fā)此事件
        _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>本戶人數(shù)</th><th>聯(lián)系電話</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("農(nóng)戶信息", node);
                // 排口信息
                res.id = id;
                // e.graphic.setAttributes(res);
                // e.graphic.setInfoTemplate(infoTemplate);
                _this._map.infoWindow.setTitle("農(nóng)戶信息");
                _this._map.infoWindow.setContent(node);
                _this._map.infoWindow.show(e.graphic.geometry);
            });
        },
        // 查找數(shù)組中最大值 或者 最小值 
        _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)
            });
        },
        // 內(nèi)部方法 ***************************起點*********************************
        _clusterGraphics: function() {
            // ,遍歷這些點
            for (var j = 0, jl = this._clusterData.length; j < jl; j++) {
                // 查看當(dāng)前特性是否應(yīng)該添加到集群中
                var point = this._clusterData[j];
                var clustered = false;
                var numClusters = this._clusters.length;
                for (var i = 0; i < this._clusters.length; i++) {

                    // 當(dāng)前集群
                    var c = this._clusters[i];
                    // 查看是否滿足距離公式
                    if (this._clusterTest(point, c)) {
                        // 如果滿足 就將當(dāng)前點添加到
                        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);
        },

        // 應(yīng)該包括傳遞給clusterAddPoint的點
        //在現(xiàn)有集群中
        //還為該點提供一個名為clusterId的屬性
        //這與它的星系團(tuán)相對應(yīng)
        _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;

            //構(gòu)建一個包括集群中所有點的范圍
            //擴(kuò)展只用于調(diào)試/測試…該層不使用
            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;
            }

            // 增加數(shù)
            cluster.attributes.clusterCount++;
            // 屬性可能不存在
            if (!p.hasOwnProperty("attributes")) {
                p.attributes = {};
            }
            // 給圖形一個集群id
            p.attributes.clusterId = cluster.attributes.clusterId;
        },

        //傳遞給clusterCreate的點不在
        //為層指定的聚類距離
        //為它創(chuàng)建一個新的集群
        _clusterCreate: function(p) {
            var clusterId = this._clusters.length + 1;
            // console.log("cluster create, id is: ", clusterId);
            // p.attributes might be undefined
            //控制臺。日志(“集群創(chuàng)建,id是:”,clusterId);
            // p。屬性可能未定義
            if (!p.attributes) {
                p.attributes = {};
            }
            p.attributes.clusterId = clusterId;
            // 創(chuàng)建集群
            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
                )
            );
            // 下面的代碼用于不使用單點標(biāo)記集群
            if (c.attributes.clusterCount == 1) {
                return;
            }

            // show number of points in the cluster
            // 顯示集群中的點的數(shù)量
            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) {
            // 查找現(xiàn)有的標(biāo)簽
            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 調(diào)試只有……從未被層調(diào)用
        _clusterMeta: function() {
            // 打印總功能數(shù)
            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);
                    // 轉(zhuǎn)成webMercator坐標(biāo)系
                    // 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
            }

添加到地圖

//調(diào)取api 獲取要渲染的點
    this._loadData("460000", 1, 100000, function(data) {
            // 采集信息
            layer = this.loadClusterLayer(data,map);
            layer.setVisibility(layerConfig.visible);
            map.addLayer(layer);
    })
  • 要點
    通過設(shè)置distance大小改變兩個點的聚合和距離
    在引入這個寫好的圖層類的時候?qū)⑵浞湃肱c根目錄同級 代碼引入
"extras/ClusterLayer",

若你是gis 完整的項目 需要在init.js 設(shè)置dojoConfig

   dojoConfig = {
            parseOnLoad: false,
            async: true,
            tlmSiblingOfDojo: false,
            has: {
                'extend-esri': 1
            },
            paths: {
            //我放到了我的項目的根目錄下了 若放在服務(wù)器根目錄下就改為/extras
              extras:"../extras"
            }
        };
sss (2).png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容