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

使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示,第1张

概述  首先来看一看实现的效果: PS:原始的程序中更新曲线数据时添加了过渡的效果,具体可查看官网的示例: http://www.visifire.com/silverlight_spline_charts_gallery.php 点击其中的一个例子,然后点击Live Updates,就可看到数据更新时的过渡效果。但是蛋疼的博客园,不知道为什么,我插入了我原始的xap文件,过渡效果却没有了,每次更新数 @H_403_1@

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

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 = 18,};                  chart.AxesX.Add(axisX);                    Axis axisY = new Axis()                  {                      Title = "实时监测值",FontSize = 16,};                  chart.AxesY.Add(axisY);                    // 设置图表的高宽                  chart.WIDth = 640;                  chart.Height = 300;                    //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 = 1; i <= 12; i++)                  {                      // 实例化数据点                      dataPoint1= new DataPoint();                      dataPoint2 = new DataPoint();                      //设置数据值                      dataPoint1.YValue = rand.Next(0,99);                      dataPoint2.YValue = rand.Next(0,99);                      //设置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(0,0,2000);          }
        /// <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 = 0; i < 12; i++)              {                  // 更新曲线数据                  chart.SerIEs[0].DataPoints[i].YValue = rand.Next(0,99);                   chart.SerIEs[1].DataPoints[i].YValue = rand.Next(20,80);               }          }

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 = 1;              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)/2,(geometry.Extent.YMax+geometry.Extent.YMin)/2);                          //获得图层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 + (320 + 20) * cell_X,mapPoint.Y,mapPoint.X + (320 + 20) * 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代码:

VIEw Code
<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 = 0; i < 10; i++)          {              values.Add(new keyvaluePair<double,double>(i,i + 1));          }                        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) / 2,(geometry.Extent.YMax + geometry.Extent.YMin) / 2);              Envelope extent = new Envelope(mapPoint.X + (320 + 20) * cell_X,mapPoint.Y);              Chart Mychart = chartlayer.Children[0] as Chart;              ElementLayer.SetEnvelope(Mychart,extent);          }

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

总结

以上是内存溢出为你收集整理的使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示全部内容,希望文章能够帮你解决使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1019337.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存