Monday, August 16, 2010

Image Flare Symbol For Clustered Graphics

This is a long overdue post following the clustering post where I wanted each flare element in a cluster symbol to flare to a different image symbol when the flare expands out. In addition, the default flare symbol expands upon a rollover mouse event, by me giving you the source code, you can customize it to expand on click, double click, shift click, whatever you want - you have the source code. The same applies to the flare elements. The ImageFlareSymbol has the same properties as the basic FlareSymbol but has two additional properties (backgroundWeights, backgroundColors) to color code the clusters based on their weight value. Each cluster is composed of one or more Graphic instance. In this implementation, each graphic must be symbolized with an instance of ImageFlareElementSymbol. The latter has a property ‘href’ that reference a bitmap url that will be displayed as a flare element. Here is a sample application to show the image flare in action. And like usual, here is the source code.

30 comments:

RAMversal said...

This example is what I'm looking for but I need to set a default symbol for clusters with a size of 1 and disable flaring on these 1 item clusters.

In the example, symbols are set on the graphics directly. Is it possible to set a symbol or renderer (UniqueValueRenderer) on the FeatureLayer instead of setting the symbol on each graphic?

thunderhead said...

There is an "issue" with symbols being displayed on the flare elements :-( however - u can assign a default symbol on the graphics layer in such a way that when a cluster is of size of 1 - then the default symbol will be used - I did not implement renderer - but can be adjusted - ping me if u need assistance implementing it

Unknown said...

Mansour,

I love this code and am using it in an AIR project. I am running into one very strange issue though. If I set the ClusterGraphics attributes then I will sometimes get an error in the ImageFlareContainer that the clusterer is null. Do you have any suggestions?

Robert Scheitlin

thunderhead said...

Sorry for the delay - pls download the latest src for the fix

Unknown said...

Mansour,

Thanks. If you don't mind I have one more issue/question. I am dynamically adding and removing graphics from the cluster and need to update the cluster weight and have it reflected in the text on the cluster graphic. I tried to add a changeWatcher to the weight property but it must not be bindable. I also gave a stab at extending the cluster so I could fire some event when the clusters weight was changed but the cluster does not inherit form an item that has eventDispatcher. Do you have any suggestions?

Robert Scheitlin

thunderhead said...

Adjust the updateDisplayListCluster in ImageFlareContainer as follows:

m_textField.text = cluster.weight.toString();
m_textField.x = m_textField.textWidth * -0.5 - 2;
m_textField.y = m_textField.textHeight * -0.5 - 1;

Hope this helps

thunderhead said...

In addition - add graphics to the cluster and call refresh

Unknown said...

Mansour,
OK I had the "m_textField.text = cluster.weight.toString();" already, so your second comment says call refresh... On what? I tried just calling refresh on the graphics layer. Do I need to call it on the clusterGraphic? If so how do I get a reference to the graphic that the cluster is assigned to?

Robert Scheitlin

thunderhead said...

Ah - sorry - so - are you adding the graphic to the layer or to the CLusterGraphic ? if on ClusterGraphic, then adjust the weight property and call refresh on it

Unknown said...

Mansour,

I am actually adding more graphics to the graphics property of the com.esri.ags.clusterers.supportClasses.Cluster that I get a reference to from a FlareMouseEvent.

thunderhead said...

The just update the weight property and call refresh - the above changes _should_ update the weight in the textfield when displayed on the map.

Unknown said...

Mansour,

I did add the code as you said and then looked though all the graphics and refreshed them (as I can't seem to find how to get a reference to just the clusterGraphic that the cluster is attached to) and it DOES NOT refresh the text as you mentioned that it _should_. Any other ideas?

Thanks for helping with this as it stands right now I remove each cluster graphics and re-add it so that I can get it updated.

Robert Scheitlin

Unknown said...

Mansour,

UPDATE. The text changes to the new weight value, but only after you mouse over and then back out.

Robert Scheitlin

CheckMate808 said...

I just recently saw this in action with the military and was taken aback.. now I see where it came from good job..

Can I request a blog on clustering and the use of mini charts to display parameters on point locations?

I have always loved the birdeye mini charts..

you can find them here: http://birdeye.googlecode.com/svn/branches/ng/examples/demo/BirdEyeExplorer.html

Drew said...

I was not able to get the FlareMouseEvent.FLARE_OUT / FlareMouseEvent.FLARE_OVER events to fire. I had to add my own code into the ImageFlareElement.as file to dispatch on mouse over and mouse out.

Thought you should know in case it’s a bug.

thunderhead said...

Nope - a feature - that is why I give out the source code :-)

Unknown said...

I'm looking to use this for a Feature Layer. Can this be done or can it only be done with a Graphics Layer?

thunderhead said...

A FeatureLayer is a subclass of GraphicLayer :-)

Unknown said...

Good to know that I can be done, now I just have to get it to work. When it flares out, the sub-images do not show. You have the cluster coded into the addGraphics function. I have a weighted cluster as an element. What is the process to convert this to what I need?

flare:ImageFlareSymbol id="imageFlareSymbol" backgroundColors="[0xFF6900,0xFF9F00]"
backgroundWeights="[100,1000]" borderColor="0xFFFFFF"
borderThickness="2" ringDistanceStart="40"/>
flare:ImageFlareElementSymbol id="biomass" href="assets/i_biomass.png"/>
flare:ImageFlareElementSymbol id="solar" href="assets/i_solar.png"/>
flare:ImageFlareElementSymbol id="wind" href="assets/i_wind.png"/>
esri:WeightedClusterer id="clusterer" symbol="{imageFlareSymbol}" sizeInPixels="5"/>

thunderhead said...

have to admit that I did not test it with WeightedClusterer :-( I guess will have to do that !

Unknown said...

Will you get a chance to do that? If you do, can you post what you find? This is a feature that will be very useful to my client's application and I know of one other person in the ESRI forums that is looking for this feature.

thunderhead said...

will do it ASAP - and will post finds

Riddlerr said...
This comment has been removed by the author.
Riddlerr said...
This comment has been removed by the author.
Harold said...

Hello Mansour,

Have you gotten a chance to get this working with a weighted cluster? If not, what would be the starting point for implementation?

Thanks for your time

Harold said...

Here's my solution for making this work with a feature layer and weighted clusterer

Mansour, feel free to rip it apart

http://forums.arcgis.com/threads/25133-Multiple-Symbols-on-Feature-Layer-Cluster-Flare?p=100802#post100802

Shafi said...

I'm able to use this application but I have to create PDF out of the map so can you help if user clicks on some button all clusters should Rollover like when mouse is on any cluster

franfr said...

Hello,

I would do the same but not with ImageFlareElementSymbol but SimpleMarkerSymbol.

So he returned in the following code function updateDisplayList:
const layerSymbol:Symbol = getLayerSymbol(flareContainer);
if (layerSymbol)
{
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);
}

This plant has this line:
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);

I get this error:
TypeError: Error #1009: Il est impossible d'accéder à la propriété ou à la méthode d'une référence d'objet nul.
at com.esri.ags.symbols::SimpleMarkerSymbol/draw()[C:\checkout\flex_api2\api\src\com\esri\ags\symbols\SimpleMarkerSymbol.as:346]
at ImageFlareElement/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareElement.as:150]
at ImageFlareContainer/updateDisplayListFlare()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:239]
at ImageFlareContainer/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:246]
at mx.core::UIComponent/validateDisplayList()
at mx.managers::LayoutManager/validateDisplayList()
at mx.managers::LayoutManager/doPhasedInstantiation()
at mx.managers::LayoutManager/doPhasedInstantiationCallback()


Can you help me?

Thank you.

franfr said...

Hello,

I would do the same but not with ImageFlareElementSymbol but SimpleMarkerSymbol.

So he returned in the following code function updateDisplayList:
const layerSymbol:Symbol = getLayerSymbol(flareContainer);
if (layerSymbol)
{
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);
}

This plant has this line:
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);

I get this error:
TypeError: Error #1009: Il est impossible d'accéder à la propriété ou à la méthode d'une référence d'objet nul.
at com.esri.ags.symbols::SimpleMarkerSymbol/draw()[C:\checkout\flex_api2\api\src\com\esri\ags\symbols\SimpleMarkerSymbol.as:346]
at ImageFlareElement/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareElement.as:150]
at ImageFlareContainer/updateDisplayListFlare()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:239]
at ImageFlareContainer/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:246]
at mx.core::UIComponent/validateDisplayList()
at mx.managers::LayoutManager/validateDisplayList()
at mx.managers::LayoutManager/doPhasedInstantiation()
at mx.managers::LayoutManager/doPhasedInstantiationCallback()


Can you help me?

Thank you.
Hello,

I would do the same but not with ImageFlareElementSymbol but SimpleMarkerSymbol.

So he returned in the following code function updateDisplayList:
const layerSymbol:Symbol = getLayerSymbol(flareContainer);
if (layerSymbol)
{
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);
}

This plant has this line:
layerSymbol.draw(m_sprite, graphic.geometry, graphic.attributes, null);

I get this error:
TypeError: Error #1009: Il est impossible d'accéder à la propriété ou à la méthode d'une référence d'objet nul.
at com.esri.ags.symbols::SimpleMarkerSymbol/draw()[C:\checkout\flex_api2\api\src\com\esri\ags\symbols\SimpleMarkerSymbol.as:346]
at ImageFlareElement/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareElement.as:150]
at ImageFlareContainer/updateDisplayListFlare()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:239]
at ImageFlareContainer/updateDisplayList()[C:\Documents and Settings\francois\Adobe Flash Builder 4.5\SIGColbert\src\com\esri\flare\ImageFlareContainer.as:246]
at mx.core::UIComponent/validateDisplayList()
at mx.managers::LayoutManager/validateDisplayList()
at mx.managers::LayoutManager/doPhasedInstantiation()
at mx.managers::LayoutManager/doPhasedInstantiationCallback()


Can you help me?

Thank you.

Guiles78 said...
This comment has been removed by the author.