本博客编写时的软件环境为VS 2010sp1+ArcGIS API for Silverlight 3.0@H_403_8@
需求:网络分析之后要求把分析出的最佳路径结果以动画形式实现轨迹回放,并要求回放过程中实现“车头拐角”。@H_403_8@
我们可能会想到使用timer来实现,每个一段时间来实现“小车”的坐标更新,但是你会发现这样会出现闪动效果,亮点之间不是平滑过渡的,这样用户体验不是太好。参考网络上给出了一个更好的方法,把他整理成了博客分享一下,并添加了车头转向的功能,我们知道在Silverlight中有个故事版方便我们实现动画,并且动画都是连续性的。不过如果要使用动画控制 小车的位置的话,必须要求小车的坐标要为依赖属性。所以这个我们要自己扩展@H_403_8@
首先新建 一个名字为Flag的UserControl 作为小车,在这里我添加一个箭头的图片(一个水平向右的箭头)@H_403_8@
@H_403_8@
XAML如下@H_403_8@
[csharp] @H_403_8@ view plain copy @H_403_4@ @H_403_4@ @H_403_4@ <GrID x:name=@H_403_8@"LayoutRoot"@H_403_8@ Background=@H_403_8@"White"@H_403_8@> @H_403_8@@H_403_8@ <Image x:name="Image1"@H_403_8@ Height=@H_403_8@"40"@H_403_8@ WIDth=@H_403_8@"40"@H_403_8@ Source=@H_403_8@"/Car.png"@H_403_8@ Stretch=@H_403_8@"Uniform"@H_403_8@> @H_403_8@@H_403_8@ <Image.Rendertransform> @H_403_8@ <transformGroup> @H_403_8@ <Rotatetransform x:name="RotateItemCanvas"@H_403_8@ CenterX=@H_403_8@"20"@H_403_8@ CenterY=@H_403_8@"20"@H_403_8@/> @H_403_8@@H_403_8@ </transformGroup> @H_403_8@ </Image.Rendertransform> @H_403_8@ </Image> @H_403_8@ </GrID> @H_403_8@ @H_403_4@上面的代码表示,我添加了一个长宽各位40的图片,并且把图片的中心作为旋转的中心。@H_403_8@
我们定义的这个控件的功能就是一个ElementLayer中的一个element 与地图控件中的一条线来绑定,通过调用Start,Stop,Pause,Resume来控制动画,这里需要定义两个依赖属性,这也是我们选择使用Elment,而不是Graphic 来表示小车的原因,因为Graphic的坐标不具有对应的依赖属性。不过控制Element的位置我们可以通过自己定义两个依赖属性Xproperty和Yproperty。然后对应的X,Y来与Element的位置绑定,通过ElementLayer的SetEnvelope来设置小车的位置,如果X,Y有变化的话,在Set方法调用了自定义的resetEnvelope 来重新设定小车的位置,我们同时又定义了CalulateXYAnagle 来根据某一段轨迹的方向来计算小车车头要旋转的的方向。同时可以通过 Interval 属性来控制每个轨迹线段用的时间(动态计算可以设置小车移动的速度);@H_403_8@@H_403_8@
@H_403_8@ copy @H_403_4@ @H_403_4@ @H_403_4@ public@H_403_8@ partial @H_403_8@class@H_403_8@ Flag : UserControl @H_403_8@@H_403_8@ { @H_403_8@ private@H_403_8@ Map _PMap = @H_403_8@null@H_403_8@; @H_403_8@@H_403_8@ private@H_403_8@ @H_403_8@int@H_403_8@ count = 0; @H_403_8@@H_403_8@ private@H_403_8@ ESRI.ArcGIS.ClIEnt.Geometry.PointCollection PCol = @H_403_8@null@H_403_8@; @H_403_8@@H_403_8@ private@H_403_8@ Storyboard sb = @H_403_8@new@H_403_8@ Storyboard(); @H_403_8@@H_403_8@ DoubleAnimation dba; @H_403_8@ DoubleAnimation dba1; @H_403_8@ /// <summary>@H_403_8@ @H_403_8@@H_403_8@ /// 执行结果路线 @H_403_8@ @H_403_8@@H_403_8@ /// </summary>@H_403_8@ @H_403_8@@H_403_8@ private@H_403_8@ Graphic _Route = @H_403_8@null@H_403_8@; @H_403_8@@H_403_8@ public@H_403_8@ Graphic Route @H_403_8@@H_403_8@ { @H_403_8@ get@H_403_8@ { @H_403_8@return@H_403_8@ _Route; } @H_403_8@@H_403_8@ set@H_403_8@ { _Route = value; } @H_403_8@@H_403_8@ } @H_403_8@ public@H_403_8@ Flag() @H_403_8@@H_403_8@ { @H_403_8@ InitializeComponent(); @H_403_8@ @H_403_8@ public@H_403_8@ @H_403_8@string@H_403_8@ ImageSource @H_403_8@@H_403_8@ set@H_403_8@ @H_403_8@@H_403_8@ { @H_403_8@ Image1.source = new@H_403_8@ BitmAPImage(@H_403_8@new@H_403_8@ Uri(value, UriKind.relative)); @H_403_8@@H_403_8@ } @H_403_8@ public@H_403_8@ Map BindMap @H_403_8@@H_403_8@ set@H_403_8@ { _PMap = value; } @H_403_8@@H_403_8@ get@H_403_8@ { @H_403_8@return@H_403_8@ _PMap; } @H_403_8@@H_403_8@ } @H_403_8@ public@H_403_8@ @H_403_8@static@H_403_8@ @H_403_8@Readonly@H_403_8@ DependencyProperty Xproperty = @H_403_8@@H_403_8@ DependencyProperty.Register("X"@H_403_8@, @H_403_8@typeof@H_403_8@(@H_403_8@double@H_403_8@), @H_403_8@typeof@H_403_8@(Flag), @H_403_8@new@H_403_8@ PropertyMetadata(OnXChanged)); @H_403_8@@H_403_8@ public@H_403_8@ @H_403_8@double@H_403_8@ X @H_403_8@@H_403_8@ get@H_403_8@ { @H_403_8@return@H_403_8@ (@H_403_8@double@H_403_8@)@H_403_8@base@H_403_8@.GetValue(Xproperty); } @H_403_8@@H_403_8@ set@H_403_8@ { @H_403_8@base@H_403_8@.SetValue(Xproperty, value); resetEnvelop(); } @H_403_8@@H_403_8@ private@H_403_8@ @H_403_8@static@H_403_8@ @H_403_8@voID@H_403_8@ OnXChanged(@H_403_8@object@H_403_8@ sender, DependencyPropertyChangedEventArgs e) @H_403_8@@H_403_8@ (sender as@H_403_8@ Flag).X = (@H_403_8@double@H_403_8@)e.NewValue; @H_403_8@@H_403_8@ public@H_403_8@ @H_403_8@static@H_403_8@ @H_403_8@Readonly@H_403_8@ DependencyProperty Yproperty = @H_403_8@@H_403_8@ DependencyProperty.Register("Y"@H_403_8@, @H_403_8@typeof@H_403_8@(Flag), @H_403_8@new@H_403_8@ PropertyMetadata(OnYChanged)); @H_403_8@@H_403_8@ public@H_403_8@ @H_403_8@double@H_403_8@ Y @H_403_8@@H_403_8@ get@H_403_8@ { @H_403_8@return@H_403_8@ (@H_403_8@double@H_403_8@)@H_403_8@base@H_403_8@.GetValue(Yproperty); } @H_403_8@@H_403_8@ set@H_403_8@ { @H_403_8@base@H_403_8@.SetValue(Yproperty, value); resetEnvelop(); } @H_403_8@@H_403_8@ private@H_403_8@ @H_403_8@static@H_403_8@ @H_403_8@voID@H_403_8@ OnYChanged(@H_403_8@object@H_403_8@ sender, DependencyPropertyChangedEventArgs e) @H_403_8@@H_403_8@ (sender as@H_403_8@ Flag).Y = (@H_403_8@double@H_403_8@)e.NewValue; @H_403_8@@H_403_8@ private@H_403_8@ ElementLayer _bindLayer = @H_403_8@null@H_403_8@; @H_403_8@@H_403_8@ public@H_403_8@ ElementLayer bindLayer @H_403_8@@H_403_8@ get@H_403_8@ { @H_403_8@return@H_403_8@ _bindLayer; } @H_403_8@@H_403_8@ set@H_403_8@ { _bindLayer = value; } @H_403_8@@H_403_8@ private@H_403_8@ @H_403_8@voID@H_403_8@ resetEnvelop() @H_403_8@@H_403_8@ Flag ele = (Flag)_bindLayer.Children[0]; @H_403_8@ ElementLayer.SetEnvelope(ele, new@H_403_8@ ESRI.ArcGIS.ClIEnt.Geometry.Envelope(X, Y, X, Y)); @H_403_8@@H_403_8@ if@H_403_8@ (_PMap != @H_403_8@null@H_403_8@) @H_403_8@@H_403_8@ ESRI.ArcGIS.ClIEnt.Geometry.polygon gon =