Friday, May 15, 2009

Police Dispatcher Demo – ArcGIS API for Microsoft Silverlight

This is a quick sample thrown together that demonstrates some of the capabilities of the ArcGIS API for Microsoft Silverlight.
http://maps.esri.com/sldemos/police/default.aspx

Video in Map Tooltips

One intriguing feature is the ability to extend ESRI’s map tips with multimedia content.  In the police sample, video hosted by the server is streamed into the map tip.

Maptip with video

The following XAML shows how this is achieved.

<esri:Map>
<
esri:Map.Layers>
<
ve:TileLayer Opacity="0" LayerStyle="AerialWithLabels"/>
<
ve:TileLayer Opacity="1" LayerStyle="Road"/>
<esri:GraphicsLayer>
<
esri:GraphicsLayer.MapTip>
<
StackPanel Orientation="Vertical" Background="Transparent">
<
TextBlock Text="..."/>
<
Border
Width="200"
Height="150"
BorderBrush="SkyBlue"
BorderThickness="1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
>
<
Border.Background>
<
VideoBrush
SourceName="video"
Stretch="UniformToFill"
/>
</
Border.Background>
</
Border>
</
StackPanel>
</
esri:GraphicsLayer.MapTip>
</
esri:GraphicsLayer>
</
esri:Map.Layers>
</
esri:Map>


Where “video” is defined as:



<MediaElement 
x:Name="video"
AutoPlay="True"
Source="police-video-large.wmv"
IsMuted="True"
Opacity="0"
IsHitTestVisible="False"
MediaEnded="Video_MediaEnded"
/>


Animated Graphics



The Silverlight animation environment is very powerful.  This power can be leveraged by the ArcGIS API for Silverlight.  For example, the incident graphics are displayed as a red icons with a rotating swirl.  There are three animations in action here:




  1. The graphic enlarges when the user’s mouse hovers over it,

  2. The red swirl rotates clockwise, and

  3. The red swirl gradually fades out over ten seconds.


Incident



This behavior can be achieved by subclassing the ESRI MarkerSymbol and overloading the common and mouseover view states.



IncidentSymbol.cs



using System.IO;
using System.Windows.Controls;
using System.Windows.Markup;
using ESRI.ArcGIS.Symbols;

namespace ESRI.PrototypeLab.PoliceDispatcher {
public class IncidentSymbol : MarkerSymbol {
public IncidentSymbol() : base() {
string key = "<your namespace>.IncidentSymbol.xaml";
Stream stream = typeof(IncidentSymbol).Assembly.
GetManifestResourceStream(key);
string template = new StreamReader(stream).ReadToEnd();
this.ControlTemplate = XamlReader.Load(template)
as ControlTemplate;
}
}
}


IncidentSymbol.xaml



<ControlTemplate
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
>
<
Grid
Cursor="Hand"
RenderTransformOrigin="0.5,0.5"
Height="50"
Width="50"
>
<
Grid.RenderTransform>
<
TransformGroup>
<
ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1" />
<
TranslateTransform X="-25" Y="-25"/>
</
TransformGroup>
</
Grid.RenderTransform>
<
vsm:VisualStateManager.VisualStateGroups>
<
vsm:VisualStateGroup x:Name="CommonStates">
<
vsm:VisualState x:Name="Normal">
<
Storyboard>
<
DoubleAnimation
Storyboard.TargetName="rotateTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360"
Duration="0:0:3"
RepeatBehavior="Forever"
/>
</
Storyboard>
</
vsm:VisualState>
<
vsm:VisualState x:Name="MouseOver">
<
Storyboard>
<
ObjectAnimationUsingKeyFrames
Duration="0"
Storyboard.TargetName="path"
Storyboard.TargetProperty="Visibility"
>
<
DiscreteObjectKeyFrame KeyTime="0"
Value="Collapsed"/>
</
ObjectAnimationUsingKeyFrames>
<
DoubleAnimation
BeginTime="0:0:0"
Storyboard.TargetName="scale"
Storyboard.TargetProperty="ScaleX"
To="2"
Duration="0:0:0.2"
/>
<
DoubleAnimation
BeginTime="0:0:0"
Storyboard.TargetName="scale"
Storyboard.TargetProperty="ScaleY"
To="2"
Duration="0:0:0.2"
/>
</
Storyboard>
</
vsm:VisualState>
</
vsm:VisualStateGroup>
<
vsm:VisualStateGroup x:Name="SelectionStates">
<
vsm:VisualState x:Name="Selected" />
<vsm:VisualState x:Name="Unselected" />
</vsm:VisualStateGroup>
</
vsm:VisualStateManager.VisualStateGroups>
<
Image
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="32"
Width="32"
Source="ESRI.PrototypeLab.PoliceDispatcher;
component/Images/incident.png"
/>
<
Path x:Name="path" Opacity="1" >
<
Path.Data>
<
PathGeometry>
<
PathGeometry.Figures>
<
PathFigureCollection>
<
PathFigure StartPoint="25,0" IsClosed="True">
<
PathFigure.Segments>
<
PathSegmentCollection>
<
ArcSegment
Point="50,25"
Size="25,25"
SweepDirection="Clockwise"
IsLargeArc="False"
RotationAngle="0"
/>
<
LineSegment Point="45,25"/>
<
ArcSegment
Point="25,5"
Size="20,20"
SweepDirection="Counterclockwise"
IsLargeArc="False"
RotationAngle="0"
/>
</
PathSegmentCollection>
</
PathFigure.Segments>
</
PathFigure>
</
PathFigureCollection>
</
PathGeometry.Figures>
</
PathGeometry>
</
Path.Data>
<
Path.Fill>
<
LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<
GradientStop x:Name="color1" Color="#00FF0000"
Offset="0"/>
<
GradientStop x:Name="color2" Color="#FFFF0000"
Offset="1"/>
</
LinearGradientBrush>
</
Path.Fill>
<
Path.RenderTransform>
<
TransformGroup>
<
RotateTransform x:Name="rotateTransform"
Angle="0" CenterX="25" CenterY="25" />
</
TransformGroup>
</
Path.RenderTransform>
</
Path>
</
Grid>
</
ControlTemplate>

3 comments:

  1. Any chance of getting the source code? I'm interested to see how the popup window works.

    Thanks

    ReplyDelete
  2. Nice stuff! I would greatly appreciate if you could post a demo of the source-code!

    Thanks!

    ReplyDelete