校园探索者应用:设计与实现解析
1. 应用背景与需求
乔治梅森大学希望在其主网站上引入新功能,帮助潜在学生和访客探索校园。当前虽有校园地图可在线查看或下载打印,但缺乏与校园实际外观的关联,且学术部门等信息需单独查找并手动在地图上定位。因此,该应用的首个版本需具备以下功能:
1. 显示现有地图。
2. 展示单校区内所有建筑,允许用户选择并在地图上高亮显示。
3. 展示学校所有部门,用户选择部门时,显示部门信息并高亮显示部门主办公室所在建筑。
4. 当用户关注某建筑时,以缩略图形式展示相关图像或视频。
5. 用户选择图像或视频缩略图时,显示更详细视图(视频可播放、暂停、恢复、停止)。
6. 显示访客前往学校的主要道路列表,用户选择时,在地图上高亮显示路线,并可附带方向箭头、文字提示等。
7. 确保应用能在 Windows 和 OS X 系统及不同浏览器上运行。
Silverlight 是实现这些功能的理想选择,因其具备跨平台性,便于 .NET 程序员开发,且对图像和视频处理有良好支持。
2. 应用设计
2.1 用户界面设计
- 界面元素可见性 :始终显示高细节地图的缩小版本,用户能看到地图上的建筑列表、学校部门和驾车路线。关注建筑时,能查看相关媒体。
- XAML 文件实现 :使用多个 XAML 文件实现用户界面,包括主应用页面、地图页面和视频缩略图页面。特定页面的功能代码可保留在该页面,如顶部导航按钮和左侧导航选项,更适合作为页面代码而非可复用元素。
2.2 数据表示
在实现前需确定数据表示方式。经收集应用需存储和处理的信息,定义以下数据结构:
|数据类型|属性|
| ---- | ---- |
|学校|名称、缩写|
|校区|名称、地图|
|部门|名称、缩写、描述、建筑编号|
|校园地图|名称、全尺寸图像(路径、宽度、高度)、缩小尺寸图像(路径、宽度、高度)、零个或多个注释|
|地图注释|名称、描述、图像路径、类别|
|建筑|名称、关联地图信息、零个或多个图像和视频|
|建筑地图信息|建筑编号、网格单元、可在地图上高亮显示的位置|
|图像/视频|标题、媒体路径、宽度、高度|
数据模型将转化为对应 XML 文件结构的类,便于 XML 文件序列化、数据绑定,并通过
DisplayText
属性使 XAML 更简洁。部分 XML 文件示例如下:
<?xml version="1.0" encoding="utf-8"?>
<school name="George Mason University" initials="GMU">
<departments>
<department abbreviation="CS" name="Computer Science"
building="44" description="..."/>
</departments>
<campuses>
<campus name="Fairfax">
<mapdata name="Fairfax Campus" source="fairfax.png"
width="2400" height="2000"
downsource="fairfax_down.png"
downwidth="600" downheight="500">
<annotations>
<annotation name="From 66"
category="Driving Directions" description="..."
image="annotations/fairfax_directions_66.png"/>
</annotations>
</mapdata>
<buildings>
<building name="Enterprise Hall">
<mapinfo number="13" highlight="1470,1040,170,120" grid="E5"/>
<images>
<image caption="Stairs to center of campus"
source="/images/EnterpriseBasement.png"
width="100" height="100"/>
</images>
<videos>
<video caption="Outside Main Entrance Floor"
source="/videos/EnterpriseMainEntrance.wmv"
width="100" height="100"/>
<video caption="Outside Bottom Floor"
source="/videos/EnterpriseBottomFloor.wmv"
width="100" height="100"/>
</videos>
</building>
</buildings>
</campus>
</campuses>
</school>
2.3 应用打包
发送给客户端的文件分为三类:
-
Silverlight 应用
:包含应用的 XAP 文件,用户浏览网站应用时下载,可在客户端浏览器缓存。
-
学校数据
:应用初始化后下载,原因如下:
- 更快显示用户界面(即使是进度条),提升用户体验。
- 可将学校数据保存到独立存储,下次加载更快,减少重复访问用户的服务器流量。使用独立存储需实现版本检查,查看服务器数据是否更新。
- 将学校特定信息置于 Silverlight 应用外,便于构建通用应用并出售给其他大学。
-
学校媒体文件
:校园各部分的图像和视频,作为网站一部分打包,文件路径存储在 XML 数据文件中,也可存储在 Silverlight Streaming 并引用。
3. 应用实现
3.1 辅助方法
应用有一个有用的扩展方法
GetHostAddress
,用于获取 Silverlight 应用所在服务器的路径,便于引用网站中的媒体文件:
public static class ApplicationExtensions
{
public static string GetHostAddress(this Application app)
{
return (app.Host.Source.AbsoluteUri.Substring(0,
app.Host.Source.AbsoluteUri.IndexOf(
app.Host.Source.AbsolutePath)));
}
}
使用示例:
video.Source = new Uri(App.Current.GetHostAddress() + "/test.wmv",
UriKind.Absolute);
该方法返回的字符串无尾随斜杠,若网站或应用在虚拟目录下,需修改此方法。
3.2 XAML 组织
应用由四个 XAML 文件组成(不包括 App.xaml):
-
MainPage.xaml
:包含应用主要部分,除交互式地图及其关联信息面板外的所有内容。使用控制模板更改
ListBox
和导航按钮外观,通过暴露 XML 命名空间将
Map.xaml
控件放置在页面上。还包含一个数据下载时覆盖整个界面的弹出窗口,通过
Opacity
实现磨砂效果。
<UserControl x:Class="chapter15.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ce="clr-namespace:chapter15">
<!-- ... -->
<ce:Map Grid.Row="1" Grid.Column="1" x:Name="mapControl"/>
<!-- ... -->
</UserControl>
<Popup x:Name="startupPopup">
<Canvas Background="White" Opacity="0.7"
Width="860" Height="815">
<TextBlock x:Name="dataDownloadProgressText" Text=""
Canvas.Left="400" Canvas.Top="400"/>
</Canvas>
</Popup>
- Map.xaml :包含四个主要元素:顶部信息面板(包含文本、图像、视频)、用户界面上的缩小地图、放大地图和查看大图/视频的弹出窗口。
-
VideoThumbnail.xaml
:用于在
Map.xaml中显示带播放按钮覆盖的视频。 - ErrorFrame.xaml :捕获并显示未处理异常,提供比浏览器错误更流畅的用户体验。
3.3 地图交互列表框
应用左侧列表框展示地图上的建筑、学校部门或驾车路线等注释。默认
ListBox
外观不适合该应用,需修改。通过定义新的控制模板,去除
ListBox
边框,修改
ListBoxItem
控制模板以去除部分动画,使项目外观更扁平。
<Style x:Key="ListBoxStyle1" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Grid>
<ScrollViewer x:Name="ScrollViewer"
BorderThickness="0"
Padding="{TemplateBinding Padding}">
<ItemsPresenter/>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="HoverOverlay"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<ListBox x:Name="mapItemsListBox"
ItemsSource="{Binding Mode=OneWay}"
Width="190" Height="500"
Canvas.Left="15" Canvas.Top="75"
Style="{StaticResource ListBoxStyle1}"
SelectionChanged="mapItemsListBox_SelectionChanged"
ItemContainerStyle="{StaticResource ListBoxItemStyle1}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=DisplayText}" Height="25"
Foreground="Black" FontSize="10"
VerticalAlignment="Top"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
任何具有
DisplayText
属性的对象都可用于此
ListBox
的数据绑定,如
Department
类:
public class Department
{
[XmlAttribute("name")]
public string name { get; set; }
public string DisplayText
{
get
{
return (this.name);
}
}
// ...
}
3.4 地图缩放
应用核心是交互式地图,其有趣功能是地图缩放。通过两张图像实现缩放,高分辨率地图(2400×2000 PNG 文件)先在图形程序中缩放到 600×500,再用于应用。用户按住鼠标左键时,从 2400×2000 图像中截取 200×200 矩形作为放大切片显示,并附带信息文本。
<Image x:Name="zoomedMapImage"
Width="2400" Height="2000" Visibility="Collapsed">
<Image.Clip>
<RectangleGeometry Rect="0,0,200,200">
<RectangleGeometry.Transform>
<TranslateTransform X="0" Y="0"
x:Name="zoomedMapClipTransform"/>
</RectangleGeometry.Transform>
</RectangleGeometry>
</Image.Clip>
<Image.RenderTransform>
<TranslateTransform X="0" Y="0"
x:Name="zoomedMapTransform" />
</Image.RenderTransform>
</Image>
鼠标点击事件处理:
private void mapCanvas_MouseLeftButtonDown(object sender,
MouseButtonEventArgs e)
{
zoomedMapImage.Visibility = Visibility.Visible;
zoomBorder.Visibility = Visibility.Visible;
gridInfoBorder.Visibility = Visibility.Visible;
setZoomedPosition(e.GetPosition(mapCanvas));
}
setZoomedPosition
方法计算切片位置和显示内容:
private void setZoomedPosition(Point p)
{
zoomedMapImage.SetValue(Canvas.LeftProperty, p.X - 100);
zoomedMapImage.SetValue(Canvas.TopProperty, p.Y - 100);
zoomedMapClipTransform.X = ((p.X) / 600) * 2400 - 100;
zoomedMapClipTransform.Y = ((p.Y) / 500) * 2000 - 100;
zoomedMapTransform.X = -1 * zoomedMapClipTransform.X;
zoomedMapTransform.Y = -1 * zoomedMapClipTransform.Y;
// 其他代码
}
用户按住鼠标左键拖动放大切片时,通过处理
MouseMove
事件实现:
private void mapCanvas_MouseMove(object sender, MouseEventArgs e)
{
setZoomedPosition(e.GetPosition(mapCanvas));
}
graph TD;
A[用户按下鼠标左键] --> B[显示放大切片和信息文本];
B --> C[调用 setZoomedPosition 方法];
C --> D[设置切片位置和裁剪区域];
D --> E[移动切片到正确位置];
F[用户拖动鼠标] --> G[再次调用 setZoomedPosition 方法];
G --> D;
校园探索者应用:设计与实现解析
4. 地图其他功能实现
4.1 建筑高亮
数据中包含每栋建筑的位置信息,以便在地图上高亮显示。通过在 XAML 中创建一个初始不可见的黑色椭圆来实现高亮效果:
<Ellipse Stroke="Black" StrokeThickness="5" x:Name="highlight"
Visibility="Collapsed"/>
在代码中,根据建筑的地图信息设置椭圆的可见性和位置:
private void highlightBuilding(Building building)
{
if (!string.IsNullOrEmpty(building.mapinfo.highlight))
{
string[] pieces = building.mapinfo.highlight.Split(',');
highlight.Visibility = Visibility.Visible;
highlight.SetValue(Canvas.LeftProperty, Convert.ToDouble(pieces[0]));
highlight.SetValue(Canvas.TopProperty, Convert.ToDouble(pieces[1]));
highlight.Width = Convert.ToDouble(pieces[2]);
highlight.Height = Convert.ToDouble(pieces[3]);
}
}
4.2 地图注释
地图注释用于为地图添加信息,本应用主要用于显示驾车路线。创建注释有两种方法:
-
使用 Silverlight 绘图原语
:如使用
TextBlock
显示文本,使用线条和椭圆等形状在地图上绘制信息。这种方法可能需要使用 Expression Blend 创建 XAML 或自定义工具。
-
在图形编辑器中绘制
:本应用采用此方法,在图形编辑器(如 Paint.NET)中打开原始地图图像,在新图层上绘制注释,然后删除原始地图图层,保留注释在透明图像上。这样注释可以轻松显示在 600×500 地图和 2400×2000 图像的放大切片上。
以下是显示注释的代码:
public void showAnnotation(string annotationImageSource)
{
clear();
BitmapImage imageSource = new BitmapImage();
imageSource.SetSource(SchoolData.GetMapAnnotation(annotationImageSource));
annotationMapMini.Source = imageSource;
annotationMapMini.Visibility = Visibility.Visible;
}
在 XAML 中,注释图像放置在主地图图像之后,确保其显示在主地图之上:
<Image x:Name="mainMap" Width="600" Height="500"
Canvas.Left="0" Canvas.Top="0"/>
<Image x:Name="annotationMapMini" Width="600" Height="500"
Canvas.Left="0" Canvas.Top="0" Visibility="Collapsed"/>
开发过程中遇到 PNG 图像颜色空间为索引格式,与 Silverlight 透明度不兼容的问题,可使用 ImageMagick 将 PNG 从索引颜色空间转换为 RGBA:
convert.exe <source image> -channel RGBA <destination image>
4.3 信息面板
信息面板位于地图上方,包含一行始终可见的文本,下方可选择性显示额外文本、图像或视频。右侧有一个箭头,用户点击可展开或折叠面板。
箭头的实现如下:
<StackPanel Orientation="Horizontal" Canvas.Left="518" Canvas.Top="0" >
<TextBlock Text="Click to collapse" x:Name="arrowLabel"
Foreground="White" FontSize="12" Margin="0 0 5 0"/>
<Image Source="arrow_down.png" x:Name="arrowButton" Width="18" Height="18"
MouseLeftButtonUp="arrow_MouseLeftButtonUp">
<Image.RenderTransform>
<RotateTransform Angle="0" CenterX="9" CenterY="9"
x:Name="arrowRotation"/>
</Image.RenderTransform>
</Image>
</StackPanel>
点击箭头的事件处理代码:
private void arrow_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (upperPanelExpanded)
{
scrollUp.Begin();
arrowRotation.Angle = 90;
infoText.Visibility = Visibility.Collapsed;
mediaScrollViewer.Visibility = Visibility.Collapsed;
arrowLabel.Text = "Click to expand";
upperPanelExpanded = false;
}
else
{
scrollDown.Begin();
arrowRotation.Angle = 0;
infoText.Visibility = informationalTextVisibility;
mediaScrollViewer.Visibility = mediaListVisibility;
arrowLabel.Text = "Click to collapse";
upperPanelExpanded = true;
}
}
图像和视频的容器是一个位于
ScrollViewer
内的空
StackPanel
,方便在内容过多时提供滚动功能:
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled"
Height="130" Canvas.Left="15" Canvas.Top="30" Width="600"
Visibility="Collapsed" x:Name="mediaScrollViewer">
<StackPanel Orientation="Horizontal" x:Name="mediaStackPanel"/>
</ScrollViewer>
当用户选择建筑或部门时,将相关视频和图像添加到
mediaStackPanel
:
mediaStackPanel.Children.Clear();
if (SchoolData.school.campuses[0].buildings[i].videos != null &&
SchoolData.school.campuses[0].buildings[i].videos.Count > 0)
{
for (int j = 0;
j < SchoolData.school.campuses[0].buildings[i].videos.Count;
j++)
{
VideoThumbnail video = new VideoThumbnail();
video.Source = new Uri(App.Current.GetHostAddress() +
SchoolData.school.campuses[0].buildings[i].videos[j].source,
UriKind.Absolute);
video.MouseLeftButtonUp += media_MouseLeftButtonUp;
video.Margin = new Thickness(10, 0, 10, 0);
video.Tag = j;
mediaStackPanel.Children.Add(video);
}
}
点击图像或视频时,触发
media_MouseLeftButtonUp
事件,显示图像或视频并打开弹出窗口:
<Popup Canvas.Left="20" Canvas.Top="40"
Width="300" Height="300" x:Name="imagePopup">
<Border BorderBrush="Black" BorderThickness="1"
Background="Black">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="zoomedMediaHeader"
HorizontalAlignment="Center"
Text="Front Entrance" Foreground="Red"/>
<Image x:Name="zoomedImage" Width="300" Height="300"
Grid.Row="1" Visibility="Collapsed"/>
<MediaElement x:Name="zoomedVideo" AutoPlay="False"
Width="300" Height="300" Grid.Row="1"
Visibility="Visible"/>
<StackPanel HorizontalAlignment="Center" Grid.Row="2"
Orientation="Horizontal" Height="24">
<Button x:Name="videoPlayStopButton" Content="PLAY"
Margin="2" Click="videoPlayStopButton_Click"/>
<Button x:Name="videoPauseResumeButton" Content="PAUSE"
Margin="2" Click="videoPauseResumeButton_Click"/>
<Button x:Name="popupButton" Content="CLOSE"
Click="popupButton_Click" Margin="2"/>
</StackPanel>
</Grid>
</Border>
</Popup>
信息面板的展开和折叠通过资源字典中的两个故事板实现:
<UserControl.Resources>
<Storyboard x:Name="scrollUp" Storyboard.TargetName="upperPanel"
Storyboard.TargetProperty="Height">
<DoubleAnimationUsingKeyFrames>
<LinearDoubleKeyFrame KeyTime="0:0:0" Value="170"/>
<LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="30"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="scrollDown" Storyboard.TargetName="upperPanel"
Storyboard.TargetProperty="Height">
<DoubleAnimationUsingKeyFrames>
<LinearDoubleKeyFrame KeyTime="0:0:0" Value="30"/>
<LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="170"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
5. 总结
该 Silverlight 应用为用户提供了一个探索校园的交互式平台,实现了显示地图、高亮建筑、展示部门信息、播放媒体等功能。通过合理的设计和实现,确保了应用在不同平台和浏览器上的兼容性。不过,该应用仍有改进空间,例如可以将交互式地图与课程和学生日程表关联起来,在地图上提供更多信息等。Silverlight 为开发者提供了丰富的功能和表现力,开发者可以充分利用这一平台创建更强大的应用。
graph LR;
A[用户选择建筑/部门] --> B[显示建筑信息和媒体缩略图];
B --> C[点击媒体缩略图];
C --> D[打开弹出窗口显示详细媒体];
E[点击箭头] --> F[展开/折叠信息面板];
超级会员免费看
1201

被折叠的 条评论
为什么被折叠?



