31.10.2012, 03:16 | #1 |
Участник
|
Microsoft Dynamics CRM Team Blog: Creating Heat Maps with Bing Maps and Dynamics CRM
Источник: http://blogs.msdn.com/b/crm/archive/...amics-crm.aspx
============== Creating Heat Maps with Bing Maps and Dynamics CRM The majority of data in the enterprise today has a location component, including most sales, operational, or service-related data. By visualizing our business data on a map, we can identify trends by geography, and use them to make smarter business decisions. In this blog post, we will show how you can visualize business data within Microsoft Dynamics CRM on Bing Maps in the form of a heat map, to identify hotspots of customers, leads, service requests and more. Dynamics CRM provides a powerful general purpose framework for developing line-of-business applications, and we will use Dynamics CRM Online, the Bing Maps AJAX v7 control, and a HeatMap module to create our visualization. What are heat maps? Wikipedia defines a heat map as “a graphical representation of data where the individual values contained in a matrix are represented as colors”. In a geographic mapping context, heat maps can provide a visualization of the relative density of point data: We will now show how we can bring this method of visualization into Dynamics CRM through the use of Web Resources and Bing Maps, to show a heat map of our CRM Opportunities, weighted by the Estimated Value, to give us a view into our potential revenue opportunity by geography. Note that the code samples below assume that your data in CRM has been geocoded, with latitudes and longitudes populated for the entities you wish to visualize. If your data does not already have coordinates populated, you can leverage the Bing Maps Locations API to geocode individual addresses, or alternately, the Bing Maps Spatial Data Services GeocodeDataflow API to geocode your data in batches. Creating our Heat Map Web Resource: We will present our mapping visualization in the context of Dynamics CRM Online through the use of Web Resources. We will create one HTML Web Resource for our map, and we will also leverage a JavaScript Web Resource to host the Heat Map module that enables the heat spot visualization. Our HTML Web Resource will host our map, and retrieve the entity data from Dynamics CRM Online, using the REST Endpoint for Web Resources. When creating our HTML Web Resource, we must use the appropriate DOCTYPE declaration, add a META element with the charset attribute set to "utf-8", and include the appropriate JavaScript resource files:
Bing Map Heatmap body { margin:0 0 0 0; } … Our HTML will be very basic: just a placeholder DIV for themap, which will occupy the entire page. Note that we will call our getMap() function when the page loads: … <div id="map" style="width: 100%; height: 100%;" /> Instantiating our Map: In our Web Resource file, we will add JavaScript code to instantiate our map. First, we define a number of global variables, to be used as we load the map and retrieve our data. Note that we use the Client Global Context to retrieve the server URL, which we will use as part of our REST request for CRM entity data, to enable portability of our Web Resource The getMap() function gets called when the page loads, and at this time, we will instantiate our map, and then register and load a module which will enable our heat map visualization. When loading the module, we define a callback function in which we construct our query to retrieve Opportunity data from the CRM REST endpoint, and then issue an AJAX request. Note how we are also extending the Microsoft.Maps.Location class by adding a multiplier property, which we will use to weight our heat map: //CRM Server Url: var serverUrl = GetGlobalContext().getServerUrl(); // Configure global variables: var map = null; // Set up arrays to hold opportunity query results and locations for heatmapping: var opportunityResults = new Array; var opportunityLocations = new Array(); // Heat map layer: var heatmapLayer = null; // Called on load, we instantiate the map, and retrieve all of our location data from CRM: function getMap() { // Instantiate map, and show world view: var mapOptions = { credentials: "insert key here", zoom: 2, center: new Microsoft.Maps.Location(36, -40) }; map = new Microsoft.Maps.Map(document.getElementById('map'), mapOptions); // Extend location to allow for revenue-weighted heatmaps: Microsoft.Maps.Location.prototype.multiplier = null; // Register and load the Client Side HeatMap Module Microsoft.Maps.registerModule("HeatMapModule", "./new_heatmap_module"); Microsoft.Maps.loadModule("HeatMapModule", { callback: function () { // Once the module is loaded, retrieve the opportunity data: // Define REST query for Opportunity data: var oppQuery = "OpportunitySet?$select=EstimatedValue," + "opportunity_customer_accounts/Address1_Latitude," + "opportunity_customer_accounts/Address1_Longitude&" + "$expand=opportunity_customer_accounts"; // Load Opportunity Data: var requestUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/" + oppQuery; makeAjaxRequest(requestUrl, opportunityResults, opportunityCallback); } }); } } Our query against the REST endpoint retrieves the EstimatedValue of each opportunity, and also uses the $expand OData option to enable us to also retrieve the Latitude and Longitude of the Account to which this Opportunity relates. Note how we are passing three parameters to the makeAjaxRequest function:
We will retrieve all of our Opportunity data through the use of the jQuery ajax method. Note that there is a maximum of 50 records returned per request to the CRM REST endpoint. If there are more than 50 Opportunity records, there will be a JSON__next property at the end of the result set. The URL value in that node can be used to retrieve the next set of records. Once all records have been obtained, the callback function (opportunityCallback) is called: // issue ajax request, populate specified array with results, then call specified callback function: function makeAjaxRequest(requestUrl, resultArray, callbackFunction) { $.ajax( { type: "GET", url: requestUrl, contentType: "application/json; charset=utf-8", dataType: "json", error: function (request, textStatus, errorThrown) { alert("Error occurred: " + request.responseXML); return; }, success: function (data) { var results = data.d["results"]; for (resultKey in results) { // Add results to appropriate array: resultArray.push(results[resultKey]); } //Check to see if we have all of the data: if (null != data.d.__next) { // If not, issue an additional request: makeAjaxRequest(data.d.__next, resultArray, callbackFunction); } else { // Call callback function: callbackFunction(); } } }); } Adding our Heat Map Layer: Now that we have all of our Opportunity data, our callback function will create Microsoft.Maps.Location objects with each Opportunity, and add a multiplier property, calculated based on the Estimated Value of the Opportunity. All Locations are added to an array, which is then used to create our Heat Map Layer with the Heatmap Module. This module was created by Alastair Aitchison, Microsoft MVP, and is shared on CodePlex as part of the Bing Maps V7 Modules project. Note that this module is dependent on the HTML5 canvas element. For Internet Explorer, this means IE9+ will be needed to view the heat map. The module accepts several options when creating the heat map layer, in addition to the map and locations parameters:
var opportunityCallback = function addOpportunityHeatmap() { for (var j = 0; j < opportunityResults.length; j++) { var item = opportunityResults[j]; // Retrieve item values: var lat = item["opportunity_customer_accounts"].Address1_Latitude; var lon = item["opportunity_customer_accounts"].Address1_Longitude; var estimatedValue = item["EstimatedValue"].Value; // If lat and long available, construct pushpin and add to map: if (lat && lon && lat != 0 && lon != 0) { // Create location: var location = new Microsoft.Maps.Location(lat, lon); // Add a nominal multiplier value to the location, for revenue-based heatmapping: if (estimatedValue >= 0) { var locMultiplier = estimatedValue / 2000000; location.multiplier = locMultiplier; } // Add location to appropriate array for heatmapping: opportunityLocations.push(location); } } // Construct heatmap layer, using heatmapping module: heatmapLayer = new HeatMapLayer( map, [], { intensity: 0.7, radius: 500000, unit: 'meters', colourgradient: { 0.0: 'green', 0.5: 'yellow', 1.0: 'red' } }); heatmapLayer.SetPoints(opportunityLocations); } Minor Update to Heat Map Module: In this example, I have made a minor modification to the heat map module, to allow the multiplier we set for each Location to weight the radius used for each heat spot. // Main method to draw the heatmap function _createHeatMap() { // Ensure the canvas matches the current dimensions of the map // This also has the effect of resetting the canvas _canvas.height = _map.getHeight(); _canvas.width = _map.getWidth(); _canvas.style.top = -_canvas.height / 2 + 'px'; _canvas.style.left = -_canvas.width / 2 +'px'; // Calculate the pixel radius of each heatpoint at the current map zoom if (_options.unit == "pixels") { radiusInPixel = _options.radius; } else { radiusInPixel = _options.radius / _map.getMetersPerPixel(); } var ctx =_canvas.getContext("2d"); var shadow = 'rgba(0, 0, 0, ' + _options.intensity + ')'; // Create the Intensity Map by looping through each location for (var i = 0, len = _locations.length; i < len; i++) { var loc = _locations[i]; var pixloc = _map.tryLocationToPixel(loc, Microsoft.Maps.PixelReference.control); var x = pixloc.x; var y = pixloc.y; // MODIFICATION: Use location multiplier against the radius, if one exists: var weightedRadius = null; if (loc.multiplier != null && loc.multiplier > 0) { weightedRadius = loc.multiplier * radiusInPixel; } else { weightedRadius = radiusInPixel; } // Create radial gradient centred on this point var grd = ctx.createRadialGradient(x, y, 0, x, y, weightedRadius); grd.addColorStop(0.0, shadow); grd.addColorStop(1.0, 'transparent'); // Draw the heatpoint onto the canvas ctx.fillStyle = grd; ctx.fillRect(x - weightedRadius, y - weightedRadius, 2 * weightedRadius, 2 * weightedRadius); } // Apply the specified colour gradient to the intensity map _colouriseHeatMap(); // Call the callback function, if specified if (_options.callback) { _options.callback(); } } Uploading our Web Resources: We can now upload our two Web Resources, and publish them both. The main HTML page will be of type ‘Web Page (HTML)’ and the heat map module will be of type ‘Script (JScript)’. We must ensure the name we choose for the Heat Map Module JavaScript resource is used in our link to the module in our HTML Web Resource. We can now test our heat map by clicking the ‘URL’ to our HTML Web Resource above: You can now add a link to your heat map with the method you desire, such as using a ribbon button, or using a link from a dashboard. You can create heat maps of accounts, opportunities, leads, service cases, and any other entity that has a location component to it, to help visualize and understand trends in your data by geography, and drive smarter business decisions. The complete code can be found here. Geoff Innis Bing Maps Technical Specialist Источник: http://blogs.msdn.com/b/crm/archive/...amics-crm.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
|
|