Closed Virgil-N closed 4 years ago
Hi @Virgil-N, have a look at the index_v4.html file for how to create the class breaks renderers. Here's a snippet of creating one of them. If it still doesn't work for you, create a plunkr or some sort of live demo and I can take a look.
// set up a class breaks renderer to render different symbols based on the cluster count. Use the required clusterCount property to break on.
var defaultSym = new SimpleMarkerSymbol({
size: 6,
color: "#FF0000",
outline: null
});
var renderer = new ClassBreaksRenderer({
defaultSymbol: defaultSym
});
renderer.field = "clusterCount";
var smSymbol = new SimpleMarkerSymbol({ size: 22, outline: new SimpleLineSymbol({ color: [221, 159, 34, 0.8] }), color: [255, 204, 102, 0.8] });
var mdSymbol = new SimpleMarkerSymbol({ size: 24, outline: new SimpleLineSymbol({ color: [82, 163, 204, 0.8] }), color: [102, 204, 255, 0.8] });
var lgSymbol = new SimpleMarkerSymbol({ size: 28, outline: new SimpleLineSymbol({ color: [41, 163, 41, 0.8] }), color: [51, 204, 51, 0.8] });
var xlSymbol = new SimpleMarkerSymbol({ size: 32, outline: new SimpleLineSymbol({ color: [200, 52, 59, 0.8] }), color: [250, 65, 74, 0.8] });
renderer.addClassBreakInfo(0, 19, smSymbol);
renderer.addClassBreakInfo(20, 150, mdSymbol);
renderer.addClassBreakInfo(151, 1000, lgSymbol);
renderer.addClassBreakInfo(1001, Infinity, xlSymbol);
Hi @Virgil-N, have a look at the index_v4.html file for how to create the class breaks renderers. Here's a snippet of creating one of them. If it still doesn't work for you, create a plunkr or some sort of live demo and I can take a look.
// set up a class breaks renderer to render different symbols based on the cluster count. Use the required clusterCount property to break on. var defaultSym = new SimpleMarkerSymbol({ size: 6, color: "#FF0000", outline: null }); var renderer = new ClassBreaksRenderer({ defaultSymbol: defaultSym }); renderer.field = "clusterCount"; var smSymbol = new SimpleMarkerSymbol({ size: 22, outline: new SimpleLineSymbol({ color: [221, 159, 34, 0.8] }), color: [255, 204, 102, 0.8] }); var mdSymbol = new SimpleMarkerSymbol({ size: 24, outline: new SimpleLineSymbol({ color: [82, 163, 204, 0.8] }), color: [102, 204, 255, 0.8] }); var lgSymbol = new SimpleMarkerSymbol({ size: 28, outline: new SimpleLineSymbol({ color: [41, 163, 41, 0.8] }), color: [51, 204, 51, 0.8] }); var xlSymbol = new SimpleMarkerSymbol({ size: 32, outline: new SimpleLineSymbol({ color: [200, 52, 59, 0.8] }), color: [250, 65, 74, 0.8] }); renderer.addClassBreakInfo(0, 19, smSymbol); renderer.addClassBreakInfo(20, 150, mdSymbol); renderer.addClassBreakInfo(151, 1000, lgSymbol); renderer.addClassBreakInfo(1001, Infinity, xlSymbol);
Hi, i made a project on codepen.io. Because i can't open plunker, unless i use an vpn. Here is the url: https://codepen.io/virgil-n/project/editor/AevazO#0 There is no dots rendered on the map.(ps: It works when i use vue. But still prints errors.) U can see the information in console. Thanks!
Ok cool, codepen is great. I just forked yours and fixed it up a bit. The markers are displaying now. See it here - https://codepen.io/nickcam/project/editor/XRpmOj
There were a few things wrong
The data setup was wrong. You had it as a multidimensional array, with the outer array containing one entry that was your actual data array. I just added this fix that - data = data[0];
Would be better to fix it when generating it though.
In the data your location properties are called latitude and longitude. The layer is expecting to see properties called x and y. You can set this in the oprions though. I just set the options to make it look for the latitude and longitude properties.
xPropertyName: "longitude",
yPropertyName: "latitude"
Also the latitude and longitude properties in your data were strings. They need to be numbers.
Thanks for your replay. I still have one question. It's can i return a graphic in the getSymbol function? I have tried, but the console ptints the error i had committed.
No you can't return a graphic from getSymbol. I don't see why you'd want to as well. getSymbol takes the graphic it's getting a symbol for as the first parameter, why would you want to return that graphic?
Unless you want to change the single symbol based on whether the current view is 2d or 3d, or use some other renderer for unclustered symbols then you shouldn't use singleRenderer. You can just set singleSymbol in constructor options, if neither is set it will just fall back to use the defaultSymbol set in the clusterRenderer.
Do you have some conditional logic required for setting the symbols of the unclustered graphics?
Yes, i have to show a custom polygon when the count equals 1 and show other symbols defined in the classBreaksRenderer when count larger than 1. Can u give me some suggestions?
Ok no worries. You won't be able to draw a polygon based on the unclustered points though. They're just points, you'll need a number of points to form a polygon and then create a symbol for it and add to the map somehow.
This is best done outside of the layer code. You can use the event "draw-complete" to do this. It will fire after every draw, so you can get the latest list of unclustered graphics at that point. I've updated my forked codepen to demonstrate it. This is what I added -
clusterLayer.on("draw-complete", () => {
var singleGraphics = [];
clusterLayer.graphics.forEach((item, i) => {
if(!item.attributes.clusterId) singleGraphics.push(item);
});
// Do something with the single graphics. Use their data to generate a polygon from somewhere else and add the polygon
// to a different layer or to the mapViews graphics collection.
console.log('single graphics', singleGraphics);
});
So u mean i have to create a new graphic layer, and add graphics to it? I have tried, so i must change the opacity of layer to show or hide the graphics? I use scale to decide when to show or hide custom graphic. But my graphics amount is very large, and when i scale to the boundary value, my browser blocked. In this case, do i have any choices? Thank you for your patient!
I'm not sure I'm understanding what you're trying to do unfortunately. I'll try and explain what I think though.
If your data set is really large then clustering can be a good idea. For this cluster layer to work your data has to be an array of points though, it can't be polygons.
How many points are you talking about? In the latest releases arcgis-js-api uses webgl to render, which performance wise is great, so you should be able to render many thousands of points in a feature layer without clustering and not have any problems drawing them.
You may have an issue getting the data to the browser if it's a lot of points as the download of data may take quite a bit. In that case you'll have to rethink how your data get's to the browser. Few options off the top of my head:
The example I sent in my previous comment was to show you how you could display a polygon for each of the unclustered graphics. You'd have to fill in the gaps to create the polygon and symbol and then add it to the map however you want though.
OK, I will take a look at the arcgis documents. It's wonderful if arcgis only render the graphics which is in my viewport, that's my imagination. ^-^.. Thanks again!
No sorry I think there's some misunderstanding. It won't render only the graphics in your viewport automatically, but it can render a LOT of graphics at once without performance problems so you'll probably be ok even if you have a lot of geometries to draw.
I was trying to say getting your data to the browser may be a performance issue if you have a lot. So you may need to do some server side work to help with that.
I see. But it's not a major problem, because it's used in a LAN network.
let renderer = new classBreaksRenderer({ // type: "class-breaks", defaultSymbol: { type: "simple-marker", size: 14, color: "#FF0000", outline: null } }); renderer.field = "clusterCount";
Some codes here:
let options = { id: "cluster-layer", title: "cluster-layer", clusterRenderer: renderer, // areaRenderer: areaRenderer, // flareRenderer: flareRenderer, // singlePopupTemplate: popupTemplate, spatialReference: new spatialReference({ "wkid": 4326 }), // subTypeFlareProperty: "facilityType", // singleFlareTooltipProperty: "name", displaySubTypeFlares: false, displayFlares: false, maxSingleFlareCount: 8, clusterRatio: 100, // clusterAreaDisplay: 'activated', data: data, clusterToScale: 10000, singleRenderer: { getSymbol: function(g, activeView) { console.log('gggggg', g) return g.attributes.graphicObj; } } }; let clusterLayer = new fcl.FlareClusterLayer(options); // clusterLayer.opacity = clusterLayersOpacity this.map.add(clusterLayer);
getSymbol function prints: { attributes: Object geometry: Object layer: null popupTemplate: undefined sourceLayer: null symbol: null visible: true initialized: true constructed: true destroyed: false accessor: a {host: {…}, _origin: 6, cursors: null, ctorArgs: null, destroyed: false, …} uid: 10194 proto: Object }
Can anybody help me?