我们正在使用wpf开发一个类似cad的应用程序,其中绘图使用Path对象放置在画布上。 我只是遇到了一个小问题,当我缩放/缩放画布时,画布中的所有元素都会缩放,这就是我想要的行为,但这也增加了路径的笔触粗细。
有没有办法增加/缩放/缩放对象,但仍保持路径的笔触粗细。
这方面的任何帮助对我都非常有用。
答案 0 :(得分:13)
更好的解决方案是使用一个或多个System.Windows.Media.Geometry对象来存储路径,点等。
可以使用Pen绘制此几何体,因此在缩放时确实可以更改笔触粗细,但更灵活的是使用“变换”属性。
使用变换,您可以“缩放”几何表示的实际坐标而不是可视化 - 所以当您绘制它时,您不需要使用渲染变换。
要计算变换,我使用以下代码:
public static Matrix TransformShape(Rect fromPosition, Rect toPosition, bool flipVertical) {
Matrix translateThenScale = Matrix.Identity;
//we first translate to origin since that's just easier
translateThenScale.Translate(-fromPosition.X, -fromPosition.Y);
//now we scale the graph to the appropriate dimensions
translateThenScale.Scale(toPosition.Width / fromPosition.Width, toPosition.Height / fromPosition.Height);
//then we flip the graph vertically around the viewport middle since in our graph positive is up, not down.
if (flipVertical)
translateThenScale.ScaleAt(1.0, -1.0, 0.0, toPosition.Height / 2.0);
//now we push the graph to the right spot, which will usually simply be 0,0.
translateThenScale.Translate(toPosition.X, toPosition.Y);
return translateThenScale;
}
其中fromPosition Rect应包含未转换的边界,而toPosition Rect应包含转换的边界。这也简单地允许分别缩放X和Y,这通常是绘图所必需的。
计算几何的边界很容易:
Geometry graphGeom;
//[...]
//the bounds are modified by the transform, so we want no transform!
graphGeom.Transform = Transform.Identity;
Rect graphBounds = graphGeom.Bounds;
//then set the transform again
//or, if the transform is axis-aligned, the following _should_ work:
Rect graphBoundsAlt = graphGeom.Transform.Inverse.TransformBounds(graphGeom.Bounds);
当然,如果有必要,WPF可以告诉你需要渲染哪些边界。把它放在一起,你可以做类似
的事情public void RecomputeTransform(Rect targetRect, bool flipVertical) {
graphGeom.Transform = Transform.Identity;
Rect graphBounds = graphGeom.Bounds;
Matrix transMat = TransformShape(graphBounds,targetRect,flipVertical);
graphGeom.Transform = new MatrixTransform(transMat);
}
使用此解决方案的优点是您不需要使用RenderTransforms,您可以自由地使用剪切和/或缩放X和Y的变换,而不会在您的线条中产生奇怪的扭曲,并且您可以对待笔作为不透明对象(即更容易从UI自定义 - 如果选择笔宽或诸如此类,则无需进一步校正)。
答案 1 :(得分:7)
最后,我得到了上述解决方案的解决方法。我是通过相对于StrokeThickness
的缩放设置Path
的{{1}}来完成的。
像这样:
Canvas
仅当// scale = scaling factor applied to the canvas
path.StrokeThickness = 1.0 / scale;
和ScaleX
统一时才有效。
答案 2 :(得分:1)
有同样的问题,解决方法非常简单。
例如:
// Create your geometry
var rectGeometry = new RectangleGeometry(new Rect(0, 0, 200, 200));
// Let the Path Shape paint your geometry
var path = new Path();
path.Data = rectGeometry;
path.StrokeThickness = 2;
// Modify your geometry, NOT the Path shape
var scaleTransform = new ScaleTransform();
rectGeometry.Transform = scaleTransform;
scaleTransform.ScaleX = 2;
scaleTransform.ScaleY = 1.5;
答案 3 :(得分:0)
我已经多次回到这里,但这个想法刚刚发生在我身上,如何将它包装在Viewbox中呢?
你可以试试这个:弄乱高度/宽度不应该改变厚度与尺寸的比例。也许它还有其他我尚未发现的坏事......
<Viewbox Height="50" Width="50">
<Path Stroke="Black" Fill="Black" StrokeThickness="0.8" Stretch="Uniform"
Data="M0,0 20,20" />
</Viewbox>
答案 4 :(得分:0)
我认为您需要YourPathObject.RenderedGeometry.Transform
属性