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中集成该功能,实现地图上的扯旗标注。

posted @ 2013-07-04 14:20  伯德  阅读(205)  评论(0编辑  收藏  举报