InkCanvas Strokes are not rendered with proper bounds when switching PC

自古美人都是妖i 提交于 2019-12-12 21:25:53

问题


I have one UWP App using a UWP InkCanvas with a Load and Save Ink Buttons. I made a draw with the app on one laptop, saved the ink as a gif (+embedded isf) and sent the gif file to another laptop with a smaller screen to try it out.

When opening the ink with the same app but on this other laptop, the draw is clipped at the boundaries, as if it does not fit the screen, which arguably is due to the laptop's smaller screen size.

I tried to resize the InkCanvas as a whole by encapsulating it in a Scrollviewer but the draw follows the InkCanvas zooming, hence the draw remains clipped at the boundaries. Same with a render transform on the InkCanvas. I also tried the copy paste methods of the StrokeContainer when loading the ink. It does not work and furthermore I find it bulky as one needs to loop through all strokes to get them selected and then copy pasted.

I am looking at a way to automatically resize the InkCanvas (preferred) or the Strokes such that the drawing appears entirely on the InkCanvas, regardless of the size of the laptop's screen. I was expecting this to happen by default but somewhat it does not.

Although the code I use is very simple, I provide it as a start:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid Background="White" Grid.Row="1">
         <InkCanvas x:Name="inkCanvas"/>
    </Grid> 
    <StackPanel>
            <Button Content="Load" Click="LoadButton_Click"/>
            <Button Content="Save" Click="SaveButton_Click"/>
    </StackPanel>
</Grid>


    private async void LoadButton_Click(object sender, RoutedEventArgs e)
    {
        FileOpenPicker openPicker = new FileOpenPicker();
        openPicker.FileTypeFilter.Clear();
        openPicker.FileTypeFilter.Add(".isf");
        openPicker.FileTypeFilter.Add(".gif");

        openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;

        StorageFile file = await openPicker.PickSingleFileAsync();

        if (file != null)
        {
            IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);

            using (var inputStream = stream.GetInputStreamAt(0))
            {
                await inkCanvas.InkPresenter.StrokeContainer.LoadAsync(inputStream);
            }
            stream.Dispose();

     }
    }

回答1:


The StrokeContainer.SaveAsync() method will create a GIF. I am not sure exactly how it preserves the ink stroke data, but it seems to be point for point. Since your InkCanvas is stretching based on its parent Grid, its final bounds will be different screen to screen, and even in resized UWP window.

So, when you reload the stroke data, it will put the points exactly where it was generated. It will not transform anything for you. This is raw data.

If you want the data to appear in a different location, you can apply a transformation on the points. Here's a quick sample of how to shrink all data by 50%:

var container = inkCanvas.InkPresenter.StrokeContainer;
var strokes = container.GetStrokes();
var bounds = container.BoundingRect;
var center = new Vector2((float)bounds.Left, (float)bounds.Top);
var transform = Matrix3x2.CreateScale(.5f, .5f, center);

foreach (var stroke in strokes)
{
    stroke.PointTransform *= transform;
}

You could put that snippet of code after await container.LoadAsync(inputStream).

You need to decide what to do with your output. It will depend on the user experience you want. If you want to scale the output, use the snippet above. If you want to move it, then use Matrix3x2.CreateTranslation(...).



来源:https://stackoverflow.com/questions/43280886/inkcanvas-strokes-are-not-rendered-with-proper-bounds-when-switching-pc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!