Maintaining fixed-thickness lines in WPF with Viewbox scaling/stretching

前端 未结 1 1436
囚心锁ツ
囚心锁ツ 2020-12-30 13:02

I have a which contains some vertical and horizontal s. I want the grid to be scalable with the window size, and retain i

相关标签:
1条回答
  • 2020-12-30 13:42

    A Viewbox can only "visually" scale its child element, including the thickness of any rendered stroke. What you need is a scaling that only applies to the geometry of the lines (or other shapes), but leaves the stroke unaffected.

    Instead of using Line objects, you could draw your lines by Path objects that use transformed LineGeometries for their Data property. You could create a ScaleTransform that scales from logical coordinates to viewport coordinates by using the Grid's width and height as scaling factors in x and y direction. Each LineGeometry (or any other Geometry) would use logical coordinates in the range 0..1:

    <Grid x:Name="grid">
        <Grid.Resources>
            <ScaleTransform x:Key="transform"
                            ScaleX="{Binding ActualWidth, ElementName=grid}"
                            ScaleY="{Binding ActualHeight, ElementName=grid}"/>
        </Grid.Resources>
        <Path Stroke="Black" StrokeThickness="1">
            <Path.Data>
                <LineGeometry StartPoint="0.1,0.1" EndPoint="0.9,0.9"
                              Transform="{StaticResource transform}"/>
            </Path.Data>
        </Path>
    </Grid>
    

    In order to get a uniform scaling you may simply bind both the ScaleTransform's ScaleX and ScaleY properties to either the ActualWidth or ActualHeight of the Grid:

    <Grid x:Name="grid">
        <Grid.Resources>
            <ScaleTransform x:Key="transform"
                            ScaleX="{Binding ActualWidth, ElementName=grid}"
                            ScaleY="{Binding ActualWidth, ElementName=grid}"/>
        </Grid.Resources>
        ...
    </Grid>
    

    You may also calculate the uniform scaling factor from the minimum value of the width and height, with a bit of code behind:

    <Grid x:Name="grid" SizeChanged="grid_SizeChanged">
        <Grid.Resources>
            <ScaleTransform x:Key="transform"/>
        </Grid.Resources>
        ...
    </Grid>
    

    with a SizeChanged handler like this:

    private void grid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        var transform = grid.Resources["transform"] as ScaleTransform;
        var minScale = Math.Min(grid.ActualWidth, grid.ActualHeight);
        transform.ScaleX = minScale;
        transform.ScaleY = minScale;
    }
    
    0 讨论(0)
提交回复
热议问题