ArcGIS for Silverlight API中实现可拖动的bubble
ArcGIS for Silverlight API中没有像ArcGIS Engine中的BalloonCallout。最近花了两天时间在Silverlight中实现了类似的效果。虽然比较粗糙,不过基本能满座需求吧,后续急需完善。现将实现思路介绍如下。
1、bubble容器的两条对角线将bubble容器分为4个象限。当鼠标拖动该容器移动时,锚点会落到其中的一个象限中,从而改变箭头的方向。
2、绘制bubble,从A点(起点)顺时针绘制。
代码如下:
GeneralTransform gt = _ContentContainer.TransformToVisual(Application.Current.RootVisual as UIElement); Point offset = gt.Transform(new Point()); Point ArrowHead = new Point(Anchor.X - offset.X, Anchor.Y - offset.Y); PathGeometry geometry = new PathGeometry(); PathFigure figure = new PathFigure { IsClosed = true }; geometry.Figures.Add(figure); figure.StartPoint = new Point(source.X, source.Y + CornerRadius); figure.Segments.Add(new ArcSegment { Point = new Point { X = source.X + CornerRadius, Y = source.Y }, SweepDirection = SweepDirection.Clockwise, Size = new Size { Width = CornerRadius, Height = CornerRadius } }); figure.Segments.Add(new LineSegment { Point = new Point { X = source.X + ContentWidth / 2 - Leaderwidth / 2, Y = source.Y } }); figure.Segments.Add(new LineSegment { Point = ArrowHead }); figure.Segments.Add(new LineSegment { Point = new Point { X = source.X + ContentWidth / 2 + Leaderwidth / 2, Y = source.Y } }); figure.Segments.Add(new LineSegment { Point = new Point { X = source.X + ContentWidth - CornerRadius, Y = source.Y } }); figure.Segments.Add(new ArcSegment { Point = new Point { X = source.X + ContentWidth, Y = source.Y + CornerRadius }, SweepDirection = SweepDirection.Clockwise, Size = new Size { Width = CornerRadius, Height = CornerRadius } }); figure.Segments.Add(new LineSegment { Point = new Point { X = source.X + ContentWidth, Y = source.Y + ContentHeight - CornerRadius } }); figure.Segments.Add(new ArcSegment { Point = new Point { X = source.X + ContentWidth - CornerRadius, Y = source.Y + ContentHeight }, SweepDirection = SweepDirection.Clockwise, Size = new Size { Width = CornerRadius, Height = CornerRadius } }); figure.Segments.Add(new LineSegment { Point = new Point { X = source.X + CornerRadius, Y = source.Y + ContentHeight } }); figure.Segments.Add(new ArcSegment { Point = new Point { X = source.X, Y = source.Y + ContentHeight - CornerRadius }, SweepDirection = SweepDirection.Clockwise, Size = new Size { Width = CornerRadius, Height = CornerRadius } }); figure.Segments.Add(new LineSegment { Point = new Point(source.X, source.Y + CornerRadius) });
3、拖动bubble容器,比较简单,废话不多讲。代码是没有二义性的,看代码就能明白。直接上代码吧。
void Bubble_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) { ContentControl item = sender as ContentControl; if (isMouseCaptured) { // Calculate the current position of the object. double deltaV = e.GetPosition(null).Y - mouseVerticalPosition; double deltaH = e.GetPosition(null).X - mouseHorizontalPosition; double newTop = deltaV + (double)item.GetValue(Canvas.TopProperty); double newLeft = deltaH + (double)item.GetValue(Canvas.LeftProperty); // Set new position of object. item.SetValue(Canvas.TopProperty, newTop); item.SetValue(Canvas.LeftProperty, newLeft); // Update position global variables. mouseVerticalPosition = e.GetPosition(null).Y; mouseHorizontalPosition = e.GetPosition(null).X; Render(deltaH, deltaV); } } void Bubble_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { ContentControl item = sender as ContentControl; isMouseCaptured = false; item.ReleaseMouseCapture(); mouseVerticalPosition = -1; mouseHorizontalPosition = -1; } void Bubble_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { ContentControl item = sender as ContentControl; mouseVerticalPosition = e.GetPosition(null).Y; mouseHorizontalPosition = e.GetPosition(null).X; isMouseCaptured = true; item.CaptureMouse(); }
4、最终效果
下一篇介绍在ArcGIS for Silverlight API中集成该功能,实现地图上的扯旗标注。