65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight - 创建带热点的图像地图

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.53/5 (11投票s)

2009 年 12 月 28 日

CPOL

6分钟阅读

viewsIcon

64068

downloadIcon

951

一篇关于如何创建带热点的图像地图,并为其附加单击事件和工具提示的文章。

引言

最近,我正在开发一个 Silverlight 应用程序,其中一个页面包含一张图形。其中一项要求是图形应包含可点击区域(热点),并在最终用户单击时显示动态导航菜单。包含一个或多个热点或可点击区域的图像称为图像地图。我整理了一个简单的教程,介绍如何完成这项工作。

入门

可以使用 Microsoft Expression Design 或 Expression Blend 创建图像地图。

  1. 如果您没有 Microsoft Expression Design,可以从 这里 下载试用版。
  2. 如果您没有 Microsoft Expression Blend,可以从 这里 下载试用版。

Microsoft Expression Designer

准备您喜欢的图像。在本教程中,我使用一张地图图形来演示我们可以使用 Microsoft Expression Designer/Blend 创建不同形状的热点。我从 这里 下载了一张随机地图。请遵循以下步骤。

  1. 打开 Microsoft Expression Design 3。
  2. 转到“文件”>“新建”,填写所有信息,然后单击“确定”按钮。
  3. 转到“视图”>“对齐到点”和“对齐到像素”。
  4. 选择“文件”>“导入图像”,浏览您的图像,然后单击“打开”按钮。
  5. 双击 _Layer1_ 并将其重命名为 _MainImage_。

此时,您应该看到类似以下内容:

图 1

Main Image

在 _MainImage_ 图层的顶部添加一个新图层,选中它,然后选择钢笔工具,在俄罗斯周围绘制一个热点。

图 2

New layer

Pen Tool

Russia

双击 _Layer_ 2 并将其命名为 Russia 或其他有意义的名称,以便我们可以在 Silverlight 应用程序中使用它。选中这些点,然后单击“属性”选项卡。请参见下图:

图 3

Add property

选择您喜欢的颜色,并将其不透明度设置为 40%。

图 4

Set opacity

完成绘制热点后,单击“文件”>“导出”,然后复制下面的设置。

图 5

Export

整合所有内容

打开 Visual Studio 2008,转到“文件”>“新建”>“项目”,然后选择“Silverlight 应用程序”模板。如果您没有 Silverlight Controls Toolkit,可以从 这里 下载。确保您已添加对 System.Windows.Controls.Toolkit 的引用。打开 _MainPage.xaml_ 文件,并将 Viewbox 控件拖到页面上。当我们在调整浏览器大小时,此控件将按比例缩放其中的地图图像。然后,将 _MapsHotSpot.xaml_ 中的内容复制到 _MainPage.xaml_ 的 Viewbox 内容中。请参见下图。

列表 1
<UserControl x:Class="MapsHotspotDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controlsToolkit=
      "clr-namespace:System.Windows.Controls;
       assembly=System.Windows.Controls.Toolkit" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" 
    d:DesignHeight="480"> 
  <Grid x:Name="LayoutRoot">
        <controlsToolkit:Viewbox  x:Name="MapsViewbox"  >
<!-- Maps content here -->
           <Canvas 
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
              x:Name="MapsHotSpot" 
              Width="800" Height="600" 
              Clip="F1 M 0,0L 800,0L 800,600L 0,600L 0,0" 
              UseLayoutRounding="False">
           ...
           </Canvas>
<!-- End Maps content here -->
        </controlsToolkit:Viewbox>
  </Grid>
</UserControl>

Expression Blend

如果您选择使用 Expression Blend 来完成,请按照以下步骤操作:

  1. 打开 Microsoft Expression Blend。
  2. 单击“文件”,选择“新建项目”,然后按照以下设置进行操作。
图 6

Blend New Project

在 _LayoutRoot_ 中添加一个 Viewbox 并命名为 MapsViewbox,然后在 Viewbox 中添加一个 Canvas 并命名为 MapsHotspot。之后,向 MapsHotspot 添加一个 Canvas,并向 Canvas 添加一个 Image 控件。在 Image 控件属性中,指定图像源并设置图像的适当宽度和高度。然后,创建另一个 Canvas 并将其命名为 Russia 或其他有意义或唯一的名称。确保新创建的 Canvas 的宽度和高度与图像匹配,以便在其上绘制点。单击钢笔工具,然后在俄罗斯周围绘制点或顶点。选择一种画笔颜色,并将其不透明度设置为特定的百分比。对其他国家/地区重复相同的过程。

图 7

Blend Hot Spot

工具提示

请记住我们一开始为每个图层命名的名称。导出到 XAML 时,图层和点将分别转换为 CanvasPath 对象。我们可以为每个图层提供一个唯一的名称,或者向其添加一个 tag 属性,并使用它从数据库或资源字典中检索国家/地区信息。为了简化起见,我们将有一个方法来循环遍历 MapsHotspot 中的每个子元素,获取名称,并将其设置为工具提示内容。为每个图层附加一个 MouseMove 事件,以便在鼠标悬停时高亮显示国家/地区。另外,附加一个 MouseLeftButtonUp 事件,以便在释放鼠标左键时弹出菜单。请参阅清单 2。

列表 2
foreach (Canvas c in (this.FindName("MapsHotSpot") as Canvas).Children)
{
    if (!string.IsNullOrEmpty(c.Name))
    {
        c.Cursor = Cursors.Hand;
        ToolTip toolTip = new ToolTip { Content = c.Name };
        c.SetValue(ToolTipService.ToolTipProperty, toolTip);
        c.MouseMove += new MouseEventHandler(c_MouseMove);
        c.MouseLeftButtonUp += new MouseButtonEventHandler(c_MouseLeftButtonUp);
    }
}

下方显示的是 c_MouseMove 方法的实现。在鼠标悬停事件期间,此方法将高亮显示 Canvas/国家/地区,并清除之前的选定内容(如果有)。

列表 3
void c_MouseMove(object sender, MouseEventArgs e)
{
    Canvas c = sender as Canvas;
    ResetLastSelected();

    if (!string.IsNullOrEmpty(c.Name))
    {
        lastSelected = c.Name;
        SetCanvasColor(c, Color.FromArgb(255, 92, 112, 171), 2, Colors.Green);
    }
}

在浏览器中查看,您应该看到类似以下内容。如果调整浏览器大小,您仍然会看到完整的地图。将鼠标悬停在地图图像上以查看工具提示和高亮显示的区域。

图 8

Preview

我们将构建一个包含几个链接的简单菜单。首先,添加一个简单的类来保存链接属性。示例如下:

列表 4
public class Links
{
    public string Title { get; set; }
    public string URL { get; set; }

    public Links(string t, string u)
    {
        Title = t;
        URL = u;
    }
}

之后,创建一个全局 List (T) 类来保存链接对象,并在页面加载时使用以下数据填充链接类。

列表 5
private List<Links> _links = new List<Links>();

void SetupLinks()
{
    _links.Add(new Links("About the people", 
               "http://www.countryreports.org/{0}.aspx"));
    _links.Add(new Links("Economy", 
               "http://www.economicexpert.com/a/{0}.htm"));
    _links.Add(new Links("Global Statistics", 
               "http://www.geohive.com/cntry/{0}.aspx"));
    _links.Add(new Links("Population", 
               "http://www.geohive.com/charts/population1.aspx"));
    _links.Add(new Links("Wiki", 
               "http://en.wikipedia.org/wiki/{0}"));
}

下方是 c_MouseLeftButtonUp 方法的实现。此方法将通过调用 PopulateContextMenu 方法来显示弹出菜单,以响应鼠标左键单击事件。PopulateContextMenu 以国家/地区名称作为参数,循环遍历链接对象列表,并将国家/地区名称附加到其中。PositionContextMenu 方法的目的是设置弹出菜单的位置。我还添加了动画效果以淡入淡出弹出菜单,请参阅 _MainPage.xaml_。

列表 6
void c_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    Canvas c = sender as Canvas;
    if (!string.IsNullOrEmpty(c.Name))
    {
        PopulateContextMenu(c.Name);
        PositionContextMenu(e.GetPosition(
                 contextMenu.Parent as UIElement), true);
        e.Handled = true;
    }
}

void PositionContextMenu(Point p, bool useTransition)
{
    if (useTransition)
        contextMenu.IsOpen = false;
    contextMenu.HorizontalOffset = p.X;
    contextMenu.VerticalOffset = p.Y;
    contextMenu.IsOpen = true;
}

void PopulateContextMenu(string country)
{
    contextListBox.Items.Clear();

    foreach (Links l in _links)
    {
        HyperlinkButton hlb = new HyperlinkButton();
        hlb.Content = l.Title;
        hlb.NavigateUri = new Uri(string.Format(l.URL, country));
        hlb.TargetName = "_blank";

        contextListBox.Items.Add(hlb);
    }   
}

此时,您应该看到类似以下内容:

图 9

Mouse click

最后一步是在页面加载时向布局网格附加一个 MouseLeftButtonUp 事件,以隐藏弹出菜单并在单击地图图像的非可点击区域时清除高亮显示的国家/地区。请参见下图。

列表 7
LayoutRoot.MouseLeftButtonUp += 
   new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);

void LayoutRoot_MouseLeftButtonUp(object sender, 
                MouseButtonEventArgs e)
{      
    ResetLastSelected();
    HideMenu();
}

void HideMenu()
{
    HidePopup.Begin();
    contextMenu.HorizontalOffset = -50.0;
}

关注点

最初,我曾计划使用我在 这里 找到的右键单击事件类来触发弹出菜单,但在阅读了 这里 关于其缺点的文章后,我决定将其排除。

我发现这篇 文章 很有用,尽管它是用 VB.NET 编写的,而且我无法编译它,但我能够利用其中嵌入的逻辑。

结论

如果您发现任何错误或不同意内容,请给我发消息,我会与您一起纠正。我建议下载演示并进行探索,以便充分理解其概念,因为我可能遗漏了一些有用的信息。我希望这篇文章对如何创建图像热点或图像地图有所帮助。

资源

© . All rights reserved.