【问题标题】:UWP Canvas drawing out of boundsUWP 画布绘制越界
【发布时间】:2017-10-06 23:39:47
【问题描述】:

我有一个画布(不是 InkCanvas!),我可以在上面绘制折线。这工作得很好,但是像下面的 GIF 中所示的越界绘制存在很大的问题。

我的画布在 ScrollViewer 内,而 ScrollViewer 在 GridView 内。

我试图用以下事件处理程序捕捉离开画布的指针:

canvas.PointerExited += Canvas_PointerExited;
canvas.PointerCaptureLost += Canvas_PointerCaptureLost;

但似乎这些事件的触发速度太慢了。

我尝试使用画布的 Clip 属性,但行为没有变化。 UWP 画布没有“ClipToBound”属性。

我的整个视图是在 Code-Behind 中生成的,因为我必须在一个视图上生成多个画布。

有没有办法阻止这种行为?

EDIT1:

根据要求:更深入地了解我的代码。

XAML 页面如下所示:

<Grid x:Name="BoundingGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="15*"/>
    </Grid.RowDefinitions>
    <Grid x:Name="InkGrid" VerticalAlignment="Top" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
    <Grid x:Name="CanvasGrid" Grid.Row="1" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" VerticalAlignment="Top"/>
</Grid>

这一切都在一个页面内。

我的代码如下:

我的构造函数:

public ImprovedCanvasManager(Grid boundingGrid, Grid overviewGrid, string filepath, double height)
    {
        drawCanvas = new Canvas();

        overviewGrid.Loaded += OverviewGrid_Loaded;
        overviewGrid.SizeChanged += OverviewGrid_SizeChanged;

        RowDefinition rd = new RowDefinition();
        rd.Height = new GridLength(height);

        overviewGrid.RowDefinitions.Add(rd);

        InitializeScrollViewer();

        Grid.SetRow(scroll, overviewGrid.RowDefinitions.Count);
        Grid.SetColumn(scroll, 0);

        scroll.Content = drawCanvas;
        overviewGrid.Children.Add(scroll);
        LoadImage(filepath);
    }

        public ImprovedCanvasManager(Grid boundingGrid, Grid overviewGrid, Grid inkToolGrid, string filepath, double height = 1000) : this(boundingGrid, overviewGrid, filepath, height)
    {
        AddDrawingToolsToCanvas(inkToolGrid, overviewGrid);
        EnableDrawingOnCanvas(drawCanvas);
    }

我只有两个构造器,让我可以简单地实例化具有绘图能力和​​不具有绘图能力的画布。

这就是我初始化 ScrollViewer 的方式:

private void InitializeScrollViewer()
    {
        scroll = new ScrollViewer();

        scroll.VerticalAlignment = VerticalAlignment.Top;
        scroll.VerticalScrollMode = ScrollMode.Auto;
        scroll.HorizontalScrollMode = ScrollMode.Auto;
        scroll.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
        scroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
        scroll.ZoomMode = ZoomMode.Enabled;
        scroll.ManipulationMode = ManipulationModes.All;

        scroll.MinZoomFactor = 1;
        scroll.MaxZoomFactor = 3;
    }

这些是影响任何视图构建的唯一代码行。

编辑 2:

我的画布没有填充左侧周围的网格,而是填充了底部。

【问题讨论】:

  • 对上述内容的快速响应,带有星号的行定义是百分比。所以15* 实际上等于1500%。当您使用星号时,我强烈建议所有值加起来为 1。 &lt;RowDefinition Height=".85*"/&gt;&lt;RowDefinition Height=".15*" /&gt;
  • 折线在哪里添加?怎么组装的?
  • 感谢您的回答。我发现您的代码运行良好。但是我的画布不够宽,无法填充周围的网格。因此,您的代码在顶部和底部边缘完美切割线,而不是在左侧和右侧。我在我的问题中发布了一个屏幕截图。
  • 好的,看起来你应该使用图像而不是画布来加盖。在我的回答中,将canvas 替换为图片参考。您可以看到图像左侧有一些填充。这看起来像死画布空间。
  • 如果您在画布/网格面板上设置背景颜色,您可以更好地可视化事物。你会看到边界。

标签: c# canvas uwp


【解决方案1】:

PointerMoved 处理程序中的代码应该与画布相关。

private void OnPointerMoved(object sender, PointerRoutedEventArgs e)
{
    var point = e.GetCurrentPoint(canvas); // <-- relative to canvas.
    var x = point.Position.X;
    var y = point.Position.Y;

    x = Math.Max(x, 0);
    y = Math.Max(y, 0);
    x = Math.Min(canvas.ActualWidth, x);
    y = Math.Min(canvas.ActualHeight, y);


    // add point to polyline...
}

如果 x/y 为负数或大于画布的大小,则它们超出范围。您可以像上面的代码那样将点限制在画布的边框上,也可以完全放弃该点。

【讨论】:

  • 理论上,您的代码运行良好。当我在画布边缘非常缓慢地绘制时,它完美地切断了线条。但是如果我画得很快,我仍然可以画出界外。这些事件真的那么慢吗?
  • 这应该是不可能的。如果您限制点的 x 和 y 值,那么无论速度如何,它们都不应绘制到画布边界之外。您是否有任何影响绘图的填充/边距/变换?也许发布更多关于如何绘制线条的代码,我会帮助你调试。
  • 我在我的问题中添加了更多细节。我希望这些信息对你有用。也许重要的是要说我的画布在加载网格后首先获取它的大小,因为在周围的网格构建在视图上之前,我没有找到另一种方法来获取它的高度和宽度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-09
  • 2019-02-09
  • 2011-08-04
  • 2016-10-08
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
相关资源
最近更新 更多