zoukankan      html  css  js  c++  java
  • 学习使用Bing Maps Silverlight Control(五):离线使用和自定义地图模式

    6 离线使用

    在笔记第一部分的时候就提到如果要使用Bing Maps Silverlight Control 进行开发,需要申请一个key,不让会显示一个错误提示出来。但是在实际开发或使用过程中,使用环境和地图数据可能不是在线的,但控件因为验证失败仍然会显示以下内容:

    6.1

    如何去掉这个提示?最简单的方式就是自己扩展一个Map控件,在其构造方法中将错误提示层给干掉,然后再项目中使用自定义的Map控件,大致可以如下实现:

    首先,自定义一个类型,继承自Map类:

    namespace CustomBingMaps
    {
        public class OfflineMap : Map
        {
            public OfflineMap()
                : base()
            {
                base.LoadingError += (sender, e) =>
                {
                    base.RootLayer.Children.RemoveAt(5);
                };
            }
        }
    }

    然后,在前台引用刚才的自定义类型的命名空间,就可以使用这个扩展的OfflineMap控件了:

    <UserControl x:Class="xwgmap_sl_client.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:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
        xmlns:c="clr-namespace:CustomBingMaps"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
        <Grid x:Name="LayoutRoot" Background="White">
            <c:OfflineMap Name="map" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed"></c:OfflineMap>
        </Grid>
    </UserControl>

    这样在离线使用控件的时候就不会再显示错误了。

    (以上方法转载自:http://www.cnblogs.com/beniao/archive/2010/05/28/1745896.html,相关原理没有转载,有兴趣的话可以去原博客查看。)

    7 自定义显示范围

    如果使用自己的地图数据进行加载使用,一般来说相对于全球只会覆盖一部分的地区,剩下的地区都是空白,还有地图数据不一定对应所有的缩放级别都有,如何限制可以查看的地图范围和缩放级别呢?答案就是自定义MapMode。

    在这里,自定义MapMode来限制视野范围主要是要重写两个方法:GetZoomRange 和 ConstrainView,前者用来限制缩放范围,后者则将经纬度和缩放进行统一限制。

    还有一个问题需要说明,Bing Maps自带的RoadMode(普通地图)和AerialMode(卫星地图)都是继承自MercatorMode(墨卡托投影),所以这里也将直接从MercatorMode派生出自定义MapMode(当然也可以扩展前两个模式)。但是MercatorMode没有任何TileSource,所以如果直接显示出来就什么也看不到了,所以还要再给自定义类型加上Tile图层。

    首先是自定义了一个必应地图(简体中文)的TileSource类:

    /// <summary>
    /// 必应地图的Tile系统
    /// </summary>
    public class BingDituTileSource : LocationRectTileSource
    {
        public BingDituTileSource()
        {
            //设定瓦片源Tile系统的Uri格式,其中的{quadkey}就是每个瓦片quadkey的对应位置
            //这里使用的是必应地图(简体中文)的Tile系统
            UriFormat = "http://r0.tiles.ditu.live.com/tiles/r{quadkey}.png?g=99&mkt=zh-cn";
        }
    }

    下面就开始自定义ChinaMode类,为了方便以后的扩展,这里将对MercatorMode的扩展提取成CustomModeBase,在此基础上再扩展出ChinaMode。所以首先是CustomModeBase的代码:

    /// <summary>
    /// 自定义地图基类,实现了视野范围的限制和自定义瓦片源。
    /// 使用前请初始化:
    /// TileLayer(瓦片源)
    /// LatitudeRange(经度范围)
    /// LongitudeRange(纬度范围)
    /// MapZoomRange(缩放范围)
    /// </summary>
    public class CustomModeBase : MercatorMode
    {
        /// <summary>
        /// 用于呈现Tile层
        /// </summary>
        public override UIElement Content
        {
            get
            {
                return this.TileLayer;
            }
        }
    
        /// <summary>
        /// 存储Tile图层
        /// </summary>
        public MapTileLayer TileLayer;
    
        /// <summary>
        /// 纬度范围
        /// </summary>
        public Range<double> LatitudeRange;
    
        /// <summary>
        /// 经度范围
        /// </summary>
        public Range<double> LongitudeRange;
    
        /// <summary>
        /// 缩放范围
        /// </summary>
        public Range<double> MapZoomRange;
    
        /// <summary>
        /// 初始化基类字段
        /// </summary>
        public CustomModeBase()
        {
            this.TileLayer = new MapTileLayer();
            this.LatitudeRange = new Range<double>(-90, 90);
            this.LongitudeRange = new Range<double>(-180, 180);
            this.MapZoomRange = new Range<double>(1, 20);
        }
    
        /// <summary>
        /// 缩放范围
        /// </summary>
        /// <param name="center"></param>
        /// <returns></returns>
        protected override Range<double> GetZoomRange(Location center)
        {
            return MapZoomRange;
        }
    
        //当地图视野改变时将调用该函数进行处理(即可达到限制地图范围的效果)
        public override bool ConstrainView(Location center, ref double zoomLevel, ref double heading, ref double pitch)
        {
            bool isChanged = base.ConstrainView(center, ref zoomLevel, ref heading, ref pitch);
    
            double newLatitude = center.Latitude;
            double newLongitude = center.Longitude;
    
            //如果视野纬度超出范围,则将视野范围限制在边界
            if (center.Longitude > LongitudeRange.To)
            {
                newLongitude = LongitudeRange.To;
            }
            else if (center.Longitude < LongitudeRange.From)
            {
                newLongitude = LongitudeRange.From;
            }
    
            //如果视野经度超出范围,则将视野范围限制在边界
            if (center.Latitude > LatitudeRange.To)
            {
                newLatitude = LatitudeRange.To;
            }
            else if (center.Latitude < LatitudeRange.From)
            {
                newLatitude = LatitudeRange.From;
            }
    
            //设置新的地图视野(限制在范围中)
            if (newLatitude != center.Latitude || newLongitude != center.Longitude)
            {
                center.Latitude = newLatitude;
                center.Longitude = newLongitude;
                isChanged = true;
            }
    
            //设置新的地图缩放级别(限制在范围中)
            Range<double> range = GetZoomRange(center);
            if (zoomLevel > range.To)
            {
                zoomLevel = range.To;
                isChanged = true;
            }
            else if (zoomLevel < range.From)
            {
                zoomLevel = range.From;
                isChanged = true;
            }
    
            return isChanged;
        }
    }

    然后再新建ChinaMode类,继承自CustomModeBase:

    /// <summary>
    /// 中国地图模式
    /// </summary>
    public class ChinaMode : CustomModeBase
    {
        public ChinaMode()
        {
            //初始化必应地图(简体中文)瓦片源
             BingDituTileSource TileSource = new BingDituTileSource();
    
            //向瓦片图层添加瓦片源
             base.TileLayer.TileSources.Add(TileSource);
    
            //向地图添加限制范围
             base.LatitudeRange = new Range<double>(0, 50);
            base.LongitudeRange = new Range<double>(70, 140);
            base.MapZoomRange = new Range<double>(5, 10);
        }
    }

    需要说明的是:这里经纬度的限制范围并不是边界范围,而是视野中心(Center)的边界,可能是为了方便适应不同的分辨率和缩放级别吧,所以处理经纬度边界的时候需要比较谨慎。缩放的级别就是可以缩放的级别,这个没有问题,缩放级别设定后,界面工具条上的缩放工具栏也会自动的做出相应的改变。

    如何使用MapMode就比较简单了,比如在后台代码进行改变:

    public MainPage()
    {
        InitializeComponent();
    
        map.Mode = new ChinaMode();
    }

    也可以在前台直接设置Mode属性:

    <c:OfflineMap Name="map"CopyrightVisibility="Collapsed" LogoVisibility="Collapsed" ScaleVisibility="Collapsed">
        <c:OfflineMap.Mode>
            <c:ChinaMode></c:ChinaMode>
        </c:OfflineMap.Mode>
    </c:OfflineMap>

    这时可以通过设计视图的预览直接看到效果。

    最终效果(各种限制无法在截图中展示,请自行体验。。。):

    7.1

    (以上内容参考自:http://msdn.microsoft.com/en-us/library/ee681896.aspx,更多内容请参阅msdn。)


    输了你,赢了世界又如何...
  • 相关阅读:
    社区检测算法--Infomap
    correlation matrices 相关矩阵
    多分类评估指标
    juniper修改用户密码
    zabbix4.4监控mysql状态
    高并发linux内核参数优化
    用脚本监控windows tcp的连接数
    使用typeperf监控系统资源
    rsync同步时报错
    windows jenkins编译报错处理
  • 原文地址:https://www.cnblogs.com/xwgli/p/3029071.html
Copyright © 2011-2022 走看看