Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SKCanvasView IOS data does not update in the OnPaintSurface method #2965

Open
1 task done
NastyaZorro169 opened this issue Aug 1, 2024 · 3 comments
Open
1 task done

Comments

@NastyaZorro169
Copy link

Description

Good morning. I am drawing a circle using SKCanvasView. On Android, everything works fine, but on iOS, the data does not update in the OnPaintSurface method, so the circle does not change its radius when the points are moved. If I change the visibility, the radius changes.

Code

public partial class NewContent1 : ContentView
{
    private IDraggableDotOffsetService DDOS;
    private double startX, startY;
    public float width;
    public float height;
    float halfPointSize = 9 + 5;
    public NewContent1()
	{
		InitializeComponent();
        DDOS = IPlatformApplication.Current.Services.GetService<IDraggableDotOffsetService>();
        PanGestureRecognizer onPanUpdatedCircle = new PanGestureRecognizer();
        onPanUpdatedCircle.PanUpdated += (s, e) => OnPanUpdatedCircle(s, e);
        DotCircleLayout1.GestureRecognizers.Add(onPanUpdatedCircle);
        DotCircleLayout2.GestureRecognizers.Add(onPanUpdatedCircle);

        DotCircleLayout1.Initialize();
        DotCircleLayout2.Initialize();
        DotCircleLayout1.TranslationX = DotCircleLayout1.iosX = 100;
        DotCircleLayout1.TranslationY = DotCircleLayout1.iosY = 150;

        DotCircleLayout2.TranslationX = DotCircleLayout2.iosX = 200;
        DotCircleLayout2.TranslationY = DotCircleLayout2.iosY = 150;
        UpdateCircle();
    }
    

    public void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        SKImageInfo info = e.Info;
        SKSurface surface = e.Surface;
        SKCanvas canvas = surface.Canvas;
        canvas.Clear(SKColors.Transparent);

        SKPaint paint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = Color.FromRgb(255, 255, 255).ToSKColor(),
            StrokeWidth = 6
        };

        canvas.DrawCircle(info.Width / 2, info.Height / 2, info.Width / 2 - 3, paint);
    }
    //---------------------------------------------------------
    void OnPanUpdatedCircle(object sender, PanUpdatedEventArgs args)
    {
        var layout = (CustomAbsoluteLayout)sender;
        float radius = (float)Math.Sqrt(Math.Pow(DotCircleLayout2.TranslationX - DotCircleLayout1.TranslationX, 2) + Math.Pow(DotCircleLayout2.TranslationY - DotCircleLayout1.TranslationY, 2));
        float angle = (float)Math.Atan2(DotCircleLayout2.TranslationY - DotCircleLayout1.TranslationY, DotCircleLayout2.TranslationX - DotCircleLayout1.TranslationX);

        switch (args.StatusType)
        {
            case GestureStatus.Started:
                (startX, startY) = DDOS.Started(args.TotalX, args.TotalY, layout.iosX, layout.iosY);
                break;
            case GestureStatus.Running:

                if (layout == DotCircleLayout1)
                {
                    (var newCenterX, var newCenterY) = DDOS.Running(startX, startY, args.TotalX, args.TotalY, layout.TranslationX, layout.TranslationY);
                    DotCircleLayout1.TranslationX = newCenterX;
                    DotCircleLayout2.TranslationY = newCenterY;
                    DotCircleLayout2.TranslationX = layout.TranslationX + radius * Math.Cos(angle);
                    DotCircleLayout2.TranslationY = layout.TranslationY + radius * Math.Sin(angle);
                }
                else if (layout == DotCircleLayout2)
                {
                    (var newDot2X, var newDot2Y) = (layout.iosX, layout.iosY) = DDOS.Running(startX, startY, args.TotalX, args.TotalY, layout.TranslationX, layout.TranslationY);

                    float newRadius = (float)Math.Sqrt(Math.Pow(newDot2X - DotCircleLayout1.TranslationX, 2) + Math.Pow(newDot2Y - DotCircleLayout1.TranslationY, 2));
                    radius = newRadius;
                    // Устанавливаем DotLayout2 на новом радиусе от DotLayout1
                    angle = (float)Math.Atan2(newDot2Y - DotCircleLayout1.TranslationY, newDot2X - DotCircleLayout1.TranslationX);
                    DotCircleLayout2.TranslationX = DotCircleLayout1.TranslationX + radius * Math.Cos(angle);
                    DotCircleLayout2.TranslationY = DotCircleLayout1.TranslationY + radius * Math.Sin(angle);
                }
                UpdateCircle();
                break;
        }
    }

    private void Test_Clicked(object sender, EventArgs e)
    {
        canvas.IsVisible = DotCircleLayout1.IsVisible = DotCircleLayout2.IsVisible = !canvas.IsVisible;
    }

    //---------------------------------------------------------
    private void UpdateCircle()
    {
        double radius = Math.Sqrt(Math.Pow((DotCircleLayout2.TranslationX + halfPointSize) -
            (DotCircleLayout1.TranslationX + halfPointSize), 2) +
            Math.Pow((DotCircleLayout2.TranslationY + halfPointSize) -
            (DotCircleLayout1.TranslationY + halfPointSize), 2));
        canvas.WidthRequest = radius * 2;
        canvas.HeightRequest = radius * 2;
        canvas.TranslationX = DotCircleLayout1.TranslationX + halfPointSize - radius;
        canvas.TranslationY = DotCircleLayout1.TranslationY + halfPointSize - radius;
        canvas.InvalidateSurface();
    }
    //---------------------------------------------------------
}

You can also share some XAML:

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.NewContent1"
             xmlns:controls="clr-namespace:MauiApp1"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls">
    <AbsoluteLayout x:Name="AbsoluteLayoutContainer">
        <Button x:Name="Test" Text="Click" Clicked="Test_Clicked" BackgroundColor="Blue"/>
        <AbsoluteLayout 
            AbsoluteLayout.LayoutBounds="0,0,1,1"
            AbsoluteLayout.LayoutFlags="All"
            InputTransparent="True">
            <skia:SKCanvasView x:Name="canvas" PaintSurface="OnPaintSurface" BackgroundColor="Crimson"/>
        </AbsoluteLayout>
        <controls:CustomAbsoluteLayout x:Name="DotCircleLayout1"
         WidthRequest="28"
         HeightRequest="28"
         TranslationX="22"
         TranslationY="22">
            <Ellipse WidthRequest="10"
      HeightRequest="10"
      Fill="Black"
      AbsoluteLayout.LayoutBounds="9,9,10,10"/>
            <Image Source="dotnet_bot.svg"
    AbsoluteLayout.LayoutBounds="5, 5, 18, 18"
    AbsoluteLayout.LayoutFlags="None">
            </Image>
        </controls:CustomAbsoluteLayout>
        <controls:CustomAbsoluteLayout x:Name="DotCircleLayout2"
         WidthRequest="28"
         HeightRequest="28"
         TranslationX="322"
         TranslationY="222">
            <Ellipse WidthRequest="10"
      HeightRequest="10"
      Fill="Black"
      AbsoluteLayout.LayoutBounds="9,9,10,10"/>
            <Image Source="dotnet_bot.svg"
    AbsoluteLayout.LayoutBounds="5, 5, 18, 18"
    AbsoluteLayout.LayoutFlags="None">
            </Image>
        </controls:CustomAbsoluteLayout>
    </AbsoluteLayout>
</ContentView>

DraggableDotOffsetService in IOS

namespace MauiApp1.iOS
{
    public class DraggableDotOffsetService : IDraggableDotOffsetService
    {
        public (double X, double Y) Running(double startX, double startY, double TotalX, double TotalY, double X, double Y)
        {
            return (startX + TotalX, startY + TotalY);
        }

        public (double X, double Y) Started(double startX, double startY, double iosX, double iosY)
        {
            return (iosX, iosY);
        }
    }
}

IDraggableDotOffsetService.cs

namespace MauiApp1
{
    public interface IDraggableDotOffsetService
    {
        (double X, double Y) Running(double startX, double startY, double TotalX, double TotalY, double X, double Y);
        (double X, double Y) Started(double startX, double startY, double iosX, double iosY);
    }
}

CustomAbsoluteLayout.cs

namespace MauiApp1
{
    public class CustomAbsoluteLayout : AbsoluteLayout
    {
        public double iosX = 0;
        public double iosY = 0;

        public void Initialize()
        {
            iosX = TranslationX;
            iosY = TranslationY;
        }
    }
}

Expected Behavior

I expect that the data will be updated in the OnPaintSurface method, similar to how it is done in Android.

Actual Behavior

In fact, the data in SKImageInfo is not being updated.

Version of SkiaSharp

2.88.3 (Current)

Last Known Good Version of SkiaSharp

2.88.2 (Previous)

IDE / Editor

Visual Studio (Windows)

Platform / Operating System

Android, iOS

Platform / Operating System Version

No response

Devices

No response

Relevant Screenshots

No response

Relevant Log Output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@mattleibow mattleibow changed the title [BUG] <SKCanvasView IOS> SKCanvasView IOS data does not update in the OnPaintSurface method Sep 18, 2024
@mattleibow
Copy link
Contributor

Are you able to put this into a sample project so I can test. There are a lot of code snippets here and it is a bit hard to test.

Copy link
Contributor

Hi @NastyaZorro169. We have added the status/needs-repro label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone.

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@mattleibow
Copy link
Contributor

Also, I assume you are using VS on windows and either an iOS device plugged into the windows machine or connected to a mac? If you try the other option, does it work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants