Thursday, December 23, 2010

Remove map whitespace with an alternative “full extent”

This post describes a technique for calculating an adjusted “full extent” for a layer so that content can uniformly fill a map.

The following XAML will display simple map using ESRI’s ArcGIS API for Silverlight. The map contains the world topo map service from ArcGIS Online.

<UserControl
   x:Class="ESRI.PrototypeLab.DynamicDesign.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:esri="http://schemas.esri.com/arcgis/client/2009" 
   mc:Ignorable="d"
   d:DesignHeight="600"
   d:DesignWidth="800"
   >
    <Grid Background="Gray">
        <esri:Map x:Name="Map">
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer
ID="topo"
Visible="True"
Url="http://services.arcgisonline.com/
ArcGIS/rest/services/World_Topo_Map/MapServer"
/>
            </esri:Map.Layers>
        </esri:Map>
    </Grid>
</UserControl>

The code behind below will zoom to the full extent of topo map service.

using System.Windows.Controls;

namespace ESRI.PrototypeLab.DynamicDesign {
    public partial class MainPage : UserControl {
        public MainPage() {
            InitializeComponent();

            // Zoom to full extent
            this.Map.Layers[0].Initialized += (s, e) => {
                this.Map.ZoomTo(this.Map.Layers[0].FullExtent);
            };
        }
    }
}

Depending on the aspect ratio of the browser, this will result in a map with “white space” (or whatever color you use for the background) at either the top/bottom or left/right as shown below.

Too much "white space"Too much "white space"

To address this I extended the Layer class with a method to return an adjusted full extent for the parent map.

using System.Windows;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;

namespace ESRI.PrototypeLab.DynamicDesign {
    public static class LayerExtension {
        public static Envelope AdjustedFullExtent(this Layer layer,
FrameworkElement parent) {
            Envelope extent = layer.FullExtent;
            double ratioMap = parent.ActualHeight / parent.ActualWidth;
            double ratioLay = extent.Height / extent.Width;
            if (ratioMap < ratioLay) {
                return new Envelope() {
                    XMin = extent.XMin,
                    YMin = extent.GetCenter().Y - 0.5d * ratioMap *
extent.Width,
                    XMax = extent.XMax,
                    YMax = extent.GetCenter().Y + 0.5d * ratioMap *
extent.Width
                };
            }
            return new Envelope() {
                XMin = extent.GetCenter().X - 0.5d *
extent.Height / ratioMap,
                YMin = extent.YMin,
                XMax = extent.GetCenter().X + 0.5d *
extent.Height / ratioMap,
                YMax = extent.YMax
            };
        }
    }
}

Let’s modify the code behind to use the new method, AdjustedFullExtent, defined above.

using System.Windows.Controls;

namespace ESRI.PrototypeLab.DynamicDesign {
    public partial class MainPage : UserControl {
        public MainPage() {
            InitializeComponent();

            // Zoom to full extent
            this.Map.Layers[0].Initialized += (s, e) => {
                this.Map.ZoomTo(
this.Map.Layers[0].AdjustedFullExtent(this.Map));
            };
        }
    }
}

Now, when the application starts, the layer will fill the entire map regardless of the browsers aspect ratio.

No more "white space" No more "white space"

1 comment: