应用缩放时滚动 canvas 出现故障(Inkscape 中从 svg 到 xaml 的导出不正确)

Scrolling canvas malfunctions when applying zoom (Incorrect export from svg to xaml in Inkscape)

简介:

我正在尝试通过阅读官方文档和使用 Internet 寻求帮助来自学 WPF。

我有 C++ 和原始 WinAPI 背景,但我确实有一些 C# 和 .NET 的经验,包括 WinForms。

我有 .svg 文件应该显示在主 window 中。应用程序应该提供缩放功能,并且应该能够滚动图像以防图像太大而无法放入主图像 window.

由于WPF无法渲染.svg,我用Inkscape将文件转换成.xaml,所以我可以渲染成功。

我为完成任务所做的努力:

由于这里的某些问题,我已经设法解决了滚动部分。缩放也有效,但总体结果并不令人满意。这就是为什么我在这里寻求帮助的原因。在写这个 post 的时候,我正在网上搜索解决方案(虽然仍然没有进展......)。

问题:

放大或缩小时,图片位置不正确,因此滚动条无法完全显示。

由于英语不是我的母语,而且我是WPF的新手,所以我很难解释这个问题。尽管如此,我还是拍了一些快照来证明我在说什么。

让我先从主要 window 的图像开始,当它首次加载到屏幕时:

放大、缩小后出现的问题分别如下:

你可以清楚地看到我无法在第一张图片中向上滚动(放大时)以看到老虎的头顶。

第二张图片我们可以看到老虎错位了,底部水平滚动条看不到,所以我看不到老虎头的底部。

相关信息:

我使用 Inkscape 将 this image 转换为 XAML。 XAML 对于 post 来说太大了(我试过了)所以我展示了我目前所拥有的 XAML 的最低限度:

<Window x:Class="Testing.MainWindow"
        Name="myMainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" KeyUp="myMainWindow_KeyUp">
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <!-- Canvas, and its drawing, were created with Inkscape -->
        <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Name="svg2" Width="494.44705" Height="510.55356">
            <Canvas.RenderTransform>
                <TranslateTransform X="183.99798" Y="144.4264"/>
            </Canvas.RenderTransform>
            <!-- many drawing commands, omitted for brevity -->
        </Canvas>
    </ScrollViewer>
</Window>

Canvas 元素中的所有内容,包括它的 HeightWidth,以及 TranslateTransform 都是由 Inkscape 创建的。这就是为什么我不允许更改该内容。如您所见,我已将 canvas 放置在 scrollviewer 中。

滚动工作正常,但在我应用缩放后它出现故障。

我决定当用户按下 + 时放大,当用户按下 - 时缩小。 KeyUp事件的处理如下所示。

private void myMainWindow_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Add)
    {
        Matrix m = svg2.LayoutTransform.Value;

        m.M11 += 0.5;
        m.M22 += 0.5;

        svg2.LayoutTransform = new MatrixTransform(m);
    }

    if (e.Key == Key.Subtract)
    {
        Matrix m = svg2.LayoutTransform.Value;

        m.M11 -= 0.5;
        m.M22 -= 0.5;

        svg2.LayoutTransform = new MatrixTransform(m);
     }
 }

完整的XAML和后面的代码可以找到here

问题:

我做错了什么?我如何调整提交的代码以便缩放正常工作?

也许使用 ScaleTransform 而不是 MatrixTransform 可能会有所帮助。

MSDN - ScaleTransform

所以。 Canvas 是一个轻量级的容器,旨在将元素排列在指定的位置。 Canvas 可以显示其边界外的元素,但如果您在 Canvas 上设置 ClipToBounds="True",那么不出所料,它会裁剪超出其边界的任何内容。

如果你看看你的 xaml:

 <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Name="svg2" Width="494.44705" Height="510.55356">
                <Canvas.RenderTransform>
                    <TransformGroup>
                        <TranslateTransform X="183.99798" Y="144.4264"/>
                    </TransformGroup>
                </Canvas.RenderTransform>

你会看到,你的 Canvas 实际上是由 TranslateTransform 移动的。在下图中,您可以看到实际的矩形位置,用红色描边。如果你将设置 ClipToBounds="True" 那么这个矩形之外的所有东西都会被剪掉。 (我建议你检查一下名为 Snoop 的程序,它非常有用)

当我发现你的 canvas 有变形时,我决定重新生成你有的图像。 有两种常见的方法:手动(打印为 XPS 文档并提取相关 xaml)或 Inkscape。 我试过第一种方法,但失败了。所以,我使用了最新版本的 Inkscape。 我关注的是以下方框:

然后我将 svg 保存为 xaml 并选中 "Compatible with Silverlight" 选项。 结果如下:

 <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Name="svg2" Width="900" Height="900">
        <Canvas.RenderTransform>
            <TranslateTransform X="0" Y="0"/>
        </Canvas.RenderTransform>
        <Canvas Name="g4">
         <!-- data below -->

并且一切正常没有故障。这是 xaml 我有 http://pastebin.com/tRin96Hi 所以这都是关于不适合 canvas 矩形的线条。

更新 逐步说明如何在 Inkscape 中将 x 和 y 设置为 0。

  1. 已下载最新版本的 Inkscape (0.91)
  2. 已安装
  3. 已下载 svg 图片
  4. 用"Open with... -> Inkscape"
  5. 打开
  6. Ctrl + A 到select所有数字
  7. 第 5 步启用 x 和 y 框。在框中打印 0 并按 Enter(或切换到其他框)以应用更改。对 x 和 y 框都应用 0。
  8. (可选)文件-文档属性-页面-高度&宽度,如果需要裁剪
  9. 已将 svg 另存为 xaml,并选中 "Compatible with Silverlight" 选项。