原文:使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示

首先来看一看实现的效果:

PS:原始的程序中更新曲线数据时添加了过渡的效果,具体可查看官网的示例:

http://www.visifire.com/silverlight_spline_charts_gallery.php

点击其中的一个例子,然后点击Live Updates,就可看到数据更新时的过渡效果。但是蛋疼的博客园,不知道为什么,我插入了我原始的xap文件,过渡效果却没有了,每次更新数据时,曲线直接就出来了(中间没有过渡行为),开始的时候以为是上传后xap文件有可能发生了变化,或者进行压缩什么的,或者浏览器解析什么的,于是我把上传到博客园的xap文件又下载下来,然后嵌入到一个htm页面中,发现还是有过度效果的,但是为什么在博客园的日志中就没有呢?整了好久还是没有整明白,求解释!

下面来看看具体实现的过程吧:

首先需要添加SLVisifire.Charts,FJ.Core的引用。然后开始我们正式的工作:

1.定义一个Chart,该Chart即为显示的图表,以及定义一个Timer,用于定时刷新数据。

        Chart chart;
Random rand = new Random(DateTime.Now.Millisecond);
System.Windows.Threading.DispatcherTimer timer = new
System.Windows.Threading.DispatcherTimer();

2.定义一个方法:CreateChart实例化Chart,并完成Chart的相关设置(如:高,宽,曲线样式等等)

        /// <summary>
/// Function to create a Visifire Chart
/// </summary>
public void CreateChart()
{
try
{
// Create a new instance of a Chart
chart = new Chart();
//添加X,Y坐标的描述
Axis axisX = new Axis()
{
Title = "月份",
FontSize = ,
};
chart.AxesX.Add(axisX); Axis axisY = new Axis()
{
Title = "实时监测值",
FontSize = ,
};
chart.AxesY.Add(axisY); // 设置图表的高宽
chart.Width = ;
chart.Height = ; //Line数据更新时的过渡效果
chart.AnimatedUpdate = true; // 定义DatatSeries实例,即一条曲线
DataSeries dataSeries1 = new DataSeries();
DataSeries dataSeries2 = new DataSeries();
//只有当Series的个数大于等于2个时Lenged才会生效
dataSeries1.LegendText = "CO2";
dataSeries2.LegendText = "SO2";
// 设置DataSeries样式
dataSeries1.RenderAs = RenderAs.Spline;
dataSeries2.RenderAs = RenderAs.Spline;
// 定义数据点
DataPoint dataPoint1;
DataPoint dataPoint2;
for (int i = ; i <= ; i++)
{
// 实例化数据点
dataPoint1= new DataPoint();
dataPoint2 = new DataPoint();
//设置数据值
dataPoint1.YValue = rand.Next(, );
dataPoint2.YValue = rand.Next(, );
//设置X轴显示名称
dataPoint1.AxisXLabel = string.Format("{0} 月", i);
dataPoint2.AxisXLabel = string.Format("{0} 月", i);
// 添加数据点
dataSeries1.DataPoints.Add(dataPoint1);
dataSeries2.DataPoints.Add(dataPoint2);
} // 将DataSeries(曲线)添加到Chart中
chart.Series.Add(dataSeries1);
chart.Series.Add(dataSeries2);
// 注册Chart Loaded事件,在该事件中设置Timer的间断值及注册Timer Tick事件
chart.Loaded += new RoutedEventHandler(chart_Loaded);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}

3.我们看到在创建Chart中注册了Loaded事件,在该事件的完成函数我们设置Timer的间断值及注册Timer Tick事件

     void chart_Loaded(object sender, RoutedEventArgs e)
{
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = new TimeSpan(, , , , );
}
        /// <summary>
/// Event handler for Tick event of Dispatcher Timer
/// </summary>
/// <param name="sender">System.Windows.Threading.DispatcherTimer</param>
/// <param name="e">EventArgs</param>
void timer_Tick(object sender, EventArgs e)
{
for (Int32 i = ; i < ; i++)
{
// 更新曲线数据
chart.Series[].DataPoints[i].YValue = rand.Next(, );
chart.Series[].DataPoints[i].YValue = rand.Next(, );
}
}

4.这里我们再写一个方法:AddChartToMapLayer,该方法用来将Chart添加到地图中

        /// <summary>
/// Add Chart to Map
/// </summary>
/// <param name="chart">Chart</param>
/// <param name="position">Position</param>
public void AddChartToMapLayer(Chart chart, Graphic position)
{
ElementLayer chartlayer = new ElementLayer();
chartlayer.ID = "ChartLayer";
chartlayer.Opacity = ;
if (Map.Layers["ChartLayer"] != null)
{
Map.Layers.Remove(Map.Layers["ChartLayer"]);
} chart.Titles.Add(new Title()
{
Text=string.Format("City: {0}",position.Attributes["CITY_NAME"].ToString ())
}); //获得Graphic的中心坐标
ESRI.ArcGIS.Client.Geometry.Geometry geometry=position.Geometry;
MapPoint mapPoint=new MapPoint ((geometry.Extent.XMax+geometry.Extent.XMin)/,(geometry.Extent.YMax+geometry.Extent.YMin)/); //获得图层X,Y方向对应的比例
double cell_X = (Map.Extent.XMax - Map.Extent.XMin) / Map.ActualWidth;
double cell_Y = (Map.Extent.YMax - Map.Extent.YMin) / Map.ActualHeight; //Chart的宽度为500所以,Chart的中心则位于宽度等于250的位置,将Chart向右移动,以防Chart覆盖Graphic
Envelope extent = new Envelope(mapPoint.X + ( + ) * cell_X, mapPoint.Y, mapPoint.X + ( + ) * cell_X, mapPoint.Y);
//设置ElementLayer的外包范围
ElementLayer.SetEnvelope(chart, extent);
chartlayer.Children.Add(chart);
Map.Layers.Add(chartlayer);
}

现在准备工作已经完成,下面就调用这些方法来实现上述的功能,我们大体的功能过程是:

当鼠标移入Graphic是就显示其对应的Chart,移除的移除Chart,这里我们注册一下FeatureLayer的MouseEnter和MouseLeave事件就行,我们再后台的XAML中注册这两个事件。

     <esri:FeatureLayer ID="MyFeatureLayer"
Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0"
Where="POP1990 > 500000"
MouseEnter="FeatureLayer_MouseEnter"
MouseLeave="FeatureLayer_MouseLeave"
Renderer="{StaticResource MySimplePointRenderer}"/>

最后在后台添加如下代码:

   private void FeatureLayer_MouseEnter(object sender, GraphicMouseEventArgs e)
{
//绘制Chart
CreateChart();
//将Chart添加到Map
AddChartToMapLayer(chart, e.Graphic);
//启动Timer,定时刷新数据
timer.Start();
} private void FeatureLayer_MouseLeave(object sender, GraphicMouseEventArgs e)
{
//停止Timer
timer.Stop();
//移除ElementLayer
if (Map.Layers["ChartLayer"] != null)
{
Map.Layers.Remove(Map.Layers["ChartLayer"]);
}
}

后台的XAML代码:

<UserControl x:Class="SilverlightChartDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:esri="http://schemas.esri.com/arcgis/client/2009"> <Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<esri:SimpleRenderer x:Key="MySimplePointRenderer">
<esri:SimpleRenderer.Symbol>
<esri:SimpleMarkerSymbol Size="15" Style="Circle">
<esri:SimpleMarkerSymbol.ControlTemplate>
<ControlTemplate>
<Grid x:Name="RootElement" RenderTransformOrigin="0.5,0.5" Width="15" Height="15">
<Grid.RenderTransform>
<ScaleTransform x:Name="customEnlargeRotatingMarkerSymbolScale" ScaleX="1" ScaleY="1" />
</Grid.RenderTransform>
<Grid.Resources>
<DropShadowEffect x:Key="customEnlargeRotatingMarkerSymbolEffect" />
</Grid.Resources>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolScale" Storyboard.TargetProperty="ScaleX" To="1" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolScale" Storyboard.TargetProperty="ScaleY" To="1" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolRotate" Storyboard.TargetProperty="Angle" To="360" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.ShadowDepth)" To="2" Duration="0:0:0.2" />
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolScale" Storyboard.TargetProperty="ScaleX" To="2" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolScale" Storyboard.TargetProperty="ScaleY" To="2" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="customEnlargeRotatingMarkerSymbolRotate" Storyboard.TargetProperty="Angle" To="0" Duration="0:0:0.2" />
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.ShadowDepth)" To="5" Duration="0:0:0.2" />
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Ellipse x:Name="ellipse" Width="15" Height="15" Fill="Green" Stroke="White" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center" Effect="{StaticResource customEnlargeRotatingMarkerSymbolEffect}"></Ellipse>
<Canvas x:Name="RotateCanvas" HorizontalAlignment="Left" VerticalAlignment="Top" Width="15" Height="15" RenderTransformOrigin="0.5,0.5">
<Canvas.Clip>
<EllipseGeometry RadiusX="7.5" RadiusY="7.5" Center="7.5,7.5" />
</Canvas.Clip>
<Canvas.RenderTransform>
<RotateTransform x:Name="customEnlargeRotatingMarkerSymbolRotate" Angle="360" />
</Canvas.RenderTransform>
<Line Stroke="White" StrokeThickness="2" X1="0" Y1="0" X2="15" Y2="15" />
<Line Stroke="White" StrokeThickness="2" X1="0" Y1="15" X2="15" Y2="0" />
</Canvas>
</Grid>
</ControlTemplate>
</esri:SimpleMarkerSymbol.ControlTemplate>
</esri:SimpleMarkerSymbol> </esri:SimpleRenderer.Symbol>
</esri:SimpleRenderer>
</Grid.Resources>
<esri:Map Background="White" HorizontalAlignment="Stretch" Margin="0" Grid.ColumnSpan="3" Name="Map" VerticalAlignment="Stretch" WrapAround="True" Extent="-15000000,2000000,-7000000,8000000">
<esri:Map.Layers>
<esri:LayerCollection>
<esri:ArcGISTiledMapServiceLayer Url="http://www.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer" />
<esri:FeatureLayer ID="MyFeatureLayer"
Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0"
Where="POP1990 > 500000"
MouseEnter="FeatureLayer_MouseEnter"
MouseLeave="FeatureLayer_MouseLeave"
Renderer="{StaticResource MySimplePointRenderer}"/>
</esri:LayerCollection>
</esri:Map.Layers>
</esri:Map> </Grid>
</UserControl>

这样我们便实现了上述的效果。

需要注意的几点:

1.Chart控件第一次加载数据的动画效果(一个点一个点添加),只能使用一次,也就是实例化Chart,加载数据时会有这样的效果,之后更新Chart控件的数据不会有类似第一次加载Chart时显示曲线动画效果,而是上面说的过渡效果。

2.注意设置Chart的AnimatedUpdate属性为True,否则数据更新时绘制曲线没有过渡的效果

3.将Chart作为ElementLayer添加到地图中,注意设置ElementLayer的显示位置。

总结:

以上的过程数据都是用Timer组件来定时生成的,当然这里也可以扩展,比如你的数据也可以是通过SQL查询得到。此外,本例没有用到数据绑定,这是因为本文的Chart是动态生成的,每次选择Graphic时都会重新生成Chart.所以没有用数据绑定。当然如果你的Chart是写死的(实例化一次),或者定义在后台的xaml中,那么建议您选择数据绑定的方式,数据绑定的方式也很简单,例如在XAML定义如下的Chart(详见Visifire documentation):

<vc:Chart Name="MyChart" Width="500" Height="300" Theme="Theme1">

    <vc:Chart.Series>

        <vc:DataSeries RenderAs="Column" DataSource="{Binding}">

            <vc:DataSeries.DataMappings>
<vc:DataMapping MemberName="XValue" Path="Key"></vc:DataMapping>
<vc:DataMapping MemberName="YValue" Path="Value"></vc:DataMapping>
</vc:DataSeries.DataMappings> </vc:DataSeries> </vc:Chart.Series> </vc:Chart>

在后台添加如下代码:

public partial class Page : UserControl
{
public Page()
{
InitializeComponent(); for (int i = ; i < ; i++)
{
values.Add(new KeyValuePair<double,double>(i, i + ));
} MyChart.DataContext = values;
} Random rand = new Random();
ObservableCollection<KeyValuePair<Double, Double>> values = new ObservableCollection<KeyValuePair<double, double>>();
}

这样便可以实现Chart曲线的数据绑定。

PS:有那么一段时间没有用Visifire了,很多又忘记了,以上算是自己的一个总结,同时很多人也问个类似的效果怎么做,在此和大家分享一下,鉴于时间和知识的关系,疏漏和错误在所难免,还望各位指正。

//关于解决地图缩放时Chart偏移的问题。

1.注册Map的ExtentChanging事件,然后在事件完成函数中重新设定Elmentlayer的Envelop,代码如下:

        private void Map_ExtentChanging(object sender, ExtentEventArgs e)
{
double cell_X = (Map.Extent.XMax - Map.Extent.XMin) / Map.ActualWidth;
ESRI.ArcGIS.Client.Geometry.Geometry geometry = selectedGraphic.Geometry;
MapPoint mapPoint = new MapPoint((geometry.Extent.XMax + geometry.Extent.XMin) / , (geometry.Extent.YMax + geometry.Extent.YMin) / );
Envelope extent = new Envelope(mapPoint.X + ( + ) * cell_X, mapPoint.Y, mapPoint.X + ( + ) * cell_X, mapPoint.Y);
Chart Mychart = chartlayer.Children[] as Chart;
ElementLayer.SetEnvelope(Mychart, extent);
}

感谢8楼 vergiljzy的建议和提示,有兴趣的不妨试试采用Inforwindow的方式。

使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示的更多相关文章

  1. 使用ArcGIS API for Silverlight + Visifire绘制地图统计图

    原文:使用ArcGIS API for Silverlight + Visifire绘制地图统计图 最近把很久之前做的统计图又拿出来重新做了一遍,感觉很多时候不复习,不记录就真的忘了,时间是最好的稀释 ...

  2. ArcGIS API for Silverlight动态标绘的实现

    原文:ArcGIS API for Silverlight动态标绘的实现 1.下载2个dll文件,分别是: ArcGISPlotSilverlightAPI.dll 和 Matrix.dll 其下载地 ...

  3. ArcGIS API for Silverlight代码中使用Template模板

    原文:ArcGIS API for Silverlight代码中使用Template模板 在项目开发中,会遇到点选中聚焦闪烁效果,但是因为在使用Symbol的时候,会设置一定的OffSetX和OffS ...

  4. ArcGIS API for Silverlight 绘制降雨路径动画

    原文:ArcGIS API for Silverlight 绘制降雨路径动画 #region 降雨动画演示 2014-04-16 List<Graphic> graphics = new ...

  5. ArcGIS API for Silverlight 当DataGrid选中项时,地图聚焦弹出窗口,并可以播放音频文件

    原文:ArcGIS API for Silverlight 当DataGrid选中项时,地图聚焦弹出窗口,并可以播放音频文件 先看效果图,然后上代码: <UserControl x:Class= ...

  6. ArcGIS API for Silverlight 地图元素点闪烁,线流动显示的处理方式

    原文:ArcGIS API for Silverlight 地图元素点闪烁,线流动显示的处理方式 <Grid x:Name="LayoutRoot" Background=& ...

  7. ArcGIS API for Silverlight 实现修改地图上的工程点位置

    原文:ArcGIS API for Silverlight 实现修改地图上的工程点位置 #region 处理工程点点击编辑相关事件 public Graphic editgraphics = null ...

  8. ArcGIS API for Silverlight 之ElementLayer使用及TextSymbol的模板使用

    原文:ArcGIS API for Silverlight 之ElementLayer使用及TextSymbol的模板使用 在开发中动态在地图上添加文字信息,可以使用TextSymbol添加文字 // ...

  9. ArcGIS API for Silverlight 调用GP服务加载等值线图层

    原文:ArcGIS API for Silverlight 调用GP服务加载等值线图层 第二篇.Silverlight客户端调用GP服务 利用ArcGIS API for Silverlight实现G ...

随机推荐

  1. [精华]Hadoop,HBase分布式集群和solr环境搭建

    1. 机器准备(这里做測试用,目的准备5台CentOS的linux系统) 1.1 准备了2台机器,安装win7系统(64位) 两台windows物理主机: 192.168.131.44 adminis ...

  2. poj 1664 把平果

    这个问题可分为两个子问题:什么时候m<n时刻,例如3苹果放在4阿菜,和3苹果放3一样的. 所以m<n时,f[m][n]=f[m][m]; 当m>=n时.可分为两种放法,一种为至少有一 ...

  3. netfilter/iptables 结构要点

    转载请注明:http://blog.csdn.net/yeasy/article/details/44311169 四张表,每一个表有若干链. filter INPUT(路由表决策后,到本机的进程) ...

  4. 辛星整理3linux笔记,免费下载点,我希望对你有所帮助

    忙乱,这是我第一次看李指出老师的视频时,,这本书是关于116页面,在csdn下载对:点我下载 ,假设左边的地址崩溃了,也能够在浏览器中输入例如以下地址然后下载:http://download.csdn ...

  5. Android:抄QQ照片选择器(按相册类别显示,加入选择题)

    这个例子的目的是为了实现类似至QQ照片选择功能.选择照片后,,使用类似新浪微博 微博 页面上显示. 先上效果图:     本例中使用的主要技术: 1.使用ContentProvider读取SD卡全部图 ...

  6. 二十9天 月出冲击黑鸟 —Spring的AOP_AspectJ @annotation

    6月14日,阴转雨. "四面垂杨十里荷,向云何处最花多, 画楼南畔夕阳和.天气乍凉人寂寞, 光阴须得酒消磨,且来花里听笙歌." 面向切面的框架AspectJ邂逅Spring,不仅造 ...

  7. redis和redis php扩展安装(转)

    redis是一个内存数据库,比memcache支持更丰富的value类型,新浪微博就使用redis来做缓存. redis的源码安装 wget http://download.redis.io/redi ...

  8. [模拟] hdu 4452 Running Rabbits

    意甲冠军: 两个人在一个人(1,1),一个人(N,N) 要人人搬家每秒的速度v.而一个s代表移动s左转方向秒 特别值得注意的是假设壁,反弹.改变方向 例如,在(1,1),采取的一个步骤,以左(1,0) ...

  9. php学习之道:mysql SELECT FOUND_ROWS()与COUNT(*)使用方法差别

    在mysql中 FOUND_ROWS()与COUNT(*)都能够统计记录.假设都一样为什么会有两个这种函数呢.以下我来介绍SELECT FOUND_ROWS()与COUNT(*)使用方法差别 SELE ...

  10. Android AIDL使用特定的解释

    1.什么是aidl:aidl这是 Android Interface definition language缩写,认清,这是android进程间通信接口的叙事语言描述.通过它我们可以定义进程间通信接口 ...