0

我正在尝试绘制像网格一样的方格纸作为画布的背景。这个网格与我发现的大多数关于如何执行此操作的解释不同,因为可以缩放画布以实现缩放。我想要做的是有一系列比例的网格线,即每 10^n 个单位。然后,网格线由于缩放而变得靠近时应该淡出。换句话说,如果 n 很大,则与该网格相关联的线应该比那些较小的 n 更暗/更重。

这在 WinForms 中很容易做到,我通过覆盖 OnPaint 并将线条的颜色定义为与下一条网格线的距离的函数来实现它。相距较远的线条比靠近的线条具有更重的权重。

我还没有弄清楚如何在 WPF 中做到这一点。我可以通过根据网格线的间距创建一条具有 StrokeThickness 的线来获得这种行为,但这仅适用于小范围的 StrokeThickness 和缩放值。如果可以将一条线定义为具有非常重的权重,但仍具有较小的 StrokeThickness,它将起作用。

即使通过使用 OnRender 实现自定义控件来做到这一点也很困难,因为我还没有找到一种可靠的方法来在呈现控件时获取控件的比例(ScaleTransform 是其中一个父控件的一部分,而不是直接父控件)。

任何关于如何实现这一目标的想法将不胜感激!

4

1 回答 1

2

我通过不将网格添加到画布来解决这个问题,而是将画布堆叠在另一个包含网格的控件之上:

<Grid>
    <Canvas x:Name="GridLayer"/>
    <Canvas x:Name="DrawingLayer" />
</Grid>

当缩放事件发生时,我只需重新绘制 GridLayer。

这使我可以只画出需要的线,按照我想要的方式画出它们,在我的情况下非常重要,因为我可能有无数的网格线,我不需要画出比需要更长/更高的线. 这样我节省了大量的 CPU 时间。

另一件需要注意的是,我实现了自己的缩放代码。我没有使用 RenderTransform 或 ViewBox,因为我希望线条保持相同的宽度。我所做的只是跟踪左上角的坐标以支持平移和缩放级别。一旦发生这些更改之一,我就会重新绘制画布。我写了两个函数:一个将 Canvas 上的坐标转换为图形坐标,另一个则相反。第一种方法允许我将光标坐标转换为图形坐标,第二种方法将图形坐标转换为可用于在画布上绘制的点。

未经测试的代码并对轴的方向做出很多假设:

Point Graph2Canvas(Point graphPoint)
{
    var canvasPoint = new Point(graphPoint);
    canvasPoint.X *= zoomLevel;
    canvasPoint.Y *= zoomLevel;
    canvasPoint.X -= topLeft.X;
    canvasPoint.Y -= topLeft.Y;
    return canvasPoint;
}

这可以被优化,事实上我创建了更多的函数来为点集合做同样的事情。

额外的:

我最终得到了一个更复杂的设置,看起来有点像这样:

<Grid>
    <Canvas x:Name="BackgroundLayer"/>
    <Canvas x:Name="GridLayer"/>
    <Canvas x:Name="AxisLayer"/>
    <Canvas x:Name="DrawingLayer" />
    <Canvas x:Name="SelectionBoxLayer"/>
    <Canvas x:Name="CursorLayer"/>
</Grid>
于 2013-08-23T08:33:44.140 回答