如何在Xamarin中的图像上绘制多边形?

时间:2019-07-16 16:11:25

标签: xamarin drawing shapes skiasharp

我想在xamarin中的图像上绘制一个多边形。 我已经以C#Windows形式实现了它。 这是我在c#中使用Windows窗体所做的屏幕快照,并且我想使用xamarin。

我对此进行了搜索,发现SkiaSharp Library可以做到这一点,但仍然没有找到如何使用xamarin做到这一点的方法。

这是我用来绘制多边形的C#代码,但我需要将其转换为xamarin。

private void boxImg_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.InterpolationMode = InterpolationMode.High;
        if (LstCalibratedPrev.Count != 0)
        {
            Pen thikpen = new Pen(Color.FromArgb(30, 144, 255), 3);
            e.Graphics.DrawPolygon(thikpen, LstCalibratedPrev.ToArray());
            Polygon pgon = new Polygon(LstCalibratedPrev.ToArray());
            foreach (PointF corner in LstCalibratedPrev)
            {
                Rectangle rect = new Rectangle((int)corner.X - object_radius   , (int)corner.Y - object_radius,    2 * object_radius + 1   , 2 * object_radius + 1);   //smaller rect
                Rectangle rect2 = new Rectangle((int)corner.X - object_radius2 , (int)corner.Y - object_radius2,   2 * object_radius2 + 1  , 2 * object_radius2 + 1);  
                e.Graphics.FillEllipse(Brushes.WhiteSmoke, rect);
                Pen Circle = new Pen(Color.FromArgb(30, 144, 255), 1);
                e.Graphics.DrawEllipse(Circle, rect2);
            }
        }
        if (LstCalibratedPrev.Count != 0)
        {
            e.Graphics.FillPolygon(new SolidBrush(Color2Transparent(T, Color.Black)), LstCalibratedPrev.ToArray());
        }
    }

enter image description here

2 个答案:

答案 0 :(得分:0)

在xamarin形式中,您可以使用custom renderers

在共享的应用中将其添加至视图:

<ContentPage.Content>
        <StackLayout Direction="Column">
            <controls:ImagePainterControl
                HeightRequest="500"
                WidthRequest="750"
                ImageSource="{Binding ImgSrc}"
            </controls:ImagePainterControl>
        </StackLayout >      
    </ContentPage.Content>

控制:

    public class ImagePainterControl: ContentView
    {
        public string ImageSource{ get; set; }
    }

android中的自定义渲染器:

[assembly: Xamarin.Forms.ExportRenderer(typeof(ImagePainterControl), typeof(ImagePainterRenderer))]
namespace Nabil.App.Droid.Renderers
{
    class ImagePainterRenderer: ViewRenderer<ImagePainterControl, Android.Views.View>
    {
        private string _imageSource { get; set; }

        public HouseRenderer(Context context) : base(context)
        {            
        }

        protected override void OnElementChanged(ElementChangedEventArgs<HouseCanvas> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null) return;

            var view = e.NewElement as ImagePainterControl;
            _imageSource = view.ImageSource;
        }

        protected override void DispatchDraw(Canvas canvas)
        {
             /* 
             * get the view where canvas will be drawn.
             * Height and width of view is set in XAML with "HeightRequest" and "WidthRequest"
             * We can't set this props in here
             */
            var rect = new Rect();
            this.GetDrawingRect(rect);

            // Set your logic of shape, width and height of your polygon here
            var topLine = rect.Width() * 0.8; 
            var bottomLine = rect.Width() * 0.8; 
            var leftLine = rect.Height() * 0.5;
            var rightLine = rect.Height() * 0.5;

            var polyStroke = new Paint
            {
                Color = _strokeColor,
                StrokeCap = Paint.Cap.Round,
                StrokeWidth = 5
            };

            var polyCircle = new Paint
            {
                Color = _strokeColor,
                StrokeCap = Paint.Cap.Round,
                StrokeWidth = 3
            };

            // Set drawing logic here (0,0 is top left)
            canvas.DrawLine(startX, startY, stopX, stopY, polyStroke ); // top line
            canvas.DrawLine(startX, startY, stopX, stopY, polyStroke ); // bottom line
            canvas.DrawLine(startX, startY, stopX, stopY, polyStroke ); // left line
            canvas.DrawLine(startX, startY, stopX, stopY, polyStroke ); // right line
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // top left circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // top mid circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // top right circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // right circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // left circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // bottom left circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // bottom mid circle
            canvas.DrawCircle(centerX, centerY, 15, polyCircle); // bottom right circle

            /* https://forums.xamarin.com/discussion/comment/24533/#Comment_24533 */
            var img = BitmapFactory.DecodeFile(_imageSource);
            img = Bitmap.CreateScaledBitmap(img, rect.Width(), rect.Height(), true);

            canvas.DrawBitmap(img, 0, 0, new Paint());

            img.Recycle();
            base.DispatchDraw(canvas);
        }
    }

答案 1 :(得分:0)

您还没有说过要使用Xamarin.Forms(XF)还是经典Xamarin。无论哪种方式,您都可以使用每个平台的本地sdk库绘制线条(如果使用的是XF,则将其封装在自定义渲染器中,如@Crunch所示),也可以使用第三方跨平台的图形库,例如{{3 }} SkiaSharp

我建议使用SkiaSharp。它功能强大且快速,是真正的跨平台2D图形库,可用于“经典”项目以及XF。学习如何使用它非常值得投资。您会发现大多数示例都是针对XF的,但可以适用于经典Xamarin。 SkiaSharp将绘制一个SKCanvasView,您可以将其放置在要绘制的视图上方。 SKCanvasView会为每个平台的根View类创建子类,因此可以在iOS中作为子视图或在Android中的任何布局(包括代码和axml)或XF中的XF布局中添加为子视图。

这里有一些参考资料可以帮助您:

https://skia.org/

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/